summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/extensions
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/chrome/browser/extensions
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/browser/extensions')
-rw-r--r--chromium/chrome/browser/extensions/BUILD.gn49
-rw-r--r--chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_apitest.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc40
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h5
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc35
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc17
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc57
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h3
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc19
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.h3
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc52
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h38
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_unittest.cc45
-rw-r--r--chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc420
-rw-r--r--chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h4
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.h2
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc164
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.h5
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store.cc76
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h10
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store_unittest.cc42
-rw-r--r--chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h3
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_api.cc35
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_api.h19
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_apitest.cc57
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h7
-rw-r--r--chromium/chrome/browser/extensions/api/debugger/debugger_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc26
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/content_action.cc30
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/content_action.h8
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc110
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc59
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc393
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc80
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc52
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/DEPS6
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/entry_picker.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc145
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc174
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h1
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc206
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_networking_attributes/OWNERS3
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.cc90
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.h30
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc210
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc139
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h17
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc45
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h6
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc49
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc36
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/page_action_apitest.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/page_action_interactive_test.cc36
-rw-r--r--chromium/chrome/browser/extensions/api/feedback_private/OWNERS1
-rw-r--r--chromium/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc143
-rw-r--r--chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h67
-rw-r--r--chromium/chrome/browser/extensions/api/gcm/gcm_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc33
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h16
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_apitest.cc288
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.cc112
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.h90
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc175
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h14
-rw-r--r--chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation.cc19
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h12
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc100
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h14
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc416
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h126
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h4
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc75
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h8
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc182
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/management/DEPS10
-rw-r--r--chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_api_unittest.cc166
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_apitest.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_browsertest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc46
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc45
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/DEPS10
-rw-r--r--chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc190
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.h39
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc32
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h37
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h22
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc75
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h12
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc77
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc63
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h28
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc97
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.h10
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc17
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/processes/processes_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/resources_private/resources_private_api.cc122
-rw-r--r--chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc264
-rw-r--r--chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h66
-rw-r--r--chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc205
-rw-r--r--chromium/chrome/browser/extensions/api/sessions/sessions_api.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/generated_pref.cc29
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/generated_pref.h7
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.h66
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/generated_prefs.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc32
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/storage/managed_value_store_cache.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/storage/policy_value_store.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/storage/settings_apitest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/system_indicator/system_indicator_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_api.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/windows_event_router.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc33
-rw-r--r--chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc455
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc40
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.cc68
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.h19
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc306
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc79
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h6
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc144
192 files changed, 5638 insertions, 3106 deletions
diff --git a/chromium/chrome/browser/extensions/BUILD.gn b/chromium/chrome/browser/extensions/BUILD.gn
index 358b0a3b16f..a1f5e2a7e0e 100644
--- a/chromium/chrome/browser/extensions/BUILD.gn
+++ b/chromium/chrome/browser/extensions/BUILD.gn
@@ -190,6 +190,8 @@ static_library("extensions") {
"api/identity/identity_constants.h",
"api/identity/identity_get_accounts_function.cc",
"api/identity/identity_get_accounts_function.h",
+ "api/identity/identity_get_auth_token_error.cc",
+ "api/identity/identity_get_auth_token_error.h",
"api/identity/identity_get_auth_token_function.cc",
"api/identity/identity_get_auth_token_function.h",
"api/identity/identity_get_profile_user_info_function.cc",
@@ -610,14 +612,14 @@ 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",
- "forced_extensions/installation_reporter_factory.h",
- "forced_extensions/installation_tracker.cc",
- "forced_extensions/installation_tracker.h",
+ "forced_extensions/force_installed_metrics.cc",
+ "forced_extensions/force_installed_metrics.h",
+ "forced_extensions/force_installed_tracker.cc",
+ "forced_extensions/force_installed_tracker.h",
+ "forced_extensions/install_stage_tracker.cc",
+ "forced_extensions/install_stage_tracker.h",
+ "forced_extensions/install_stage_tracker_factory.cc",
+ "forced_extensions/install_stage_tracker_factory.h",
"global_shortcut_listener.cc",
"global_shortcut_listener.h",
"global_shortcut_listener_mac.h",
@@ -645,6 +647,8 @@ static_library("extensions") {
"launch_util.h",
"load_error_reporter.cc",
"load_error_reporter.h",
+ "media_router_extension_access_logger_impl.cc",
+ "media_router_extension_access_logger_impl.h",
"menu_manager.cc",
"menu_manager.h",
"menu_manager_factory.cc",
@@ -751,7 +755,7 @@ static_library("extensions") {
# Lots of APIs use headers from the list above.
"//chrome/browser/extensions/api:api_registration",
- # TODO(loyso): Remove this circular dependency. http://crbug.com/876576.
+ # TODO(crbug.com/1065748): Remove this circular dependency.
"//chrome/browser/web_applications/extensions",
# TODO(crbug/925153): Remove this circular dependency.
@@ -796,11 +800,13 @@ static_library("extensions") {
"//chrome/browser/resource_coordinator:intervention_policy_database_proto",
"//chrome/browser/resource_coordinator:mojo_bindings",
"//chrome/browser/safe_browsing",
+ "//chrome/browser/web_applications",
"//chrome/browser/web_applications/components",
+
+ # TODO(crbug.com/1065748): Remove this dependency:
"//chrome/browser/web_applications/extensions",
"//chrome/common/extensions/api:extensions_features",
"//chrome/common/safe_browsing:proto",
- "//chrome/services/app_service/public/mojom",
"//chrome/services/removable_storage_writer/public/mojom",
"//components/autofill/content/browser",
"//components/bookmarks/browser",
@@ -853,6 +859,7 @@ static_library("extensions") {
"//components/safe_browsing/core/common:safe_browsing_prefs",
"//components/safe_browsing/core/db:database_manager",
"//components/search_engines",
+ "//components/services/app_service/public/mojom",
"//components/services/patch/content",
"//components/services/unzip/content",
"//components/services/unzip/public/cpp",
@@ -897,6 +904,7 @@ static_library("extensions") {
"//services/audio/public/cpp",
"//services/data_decoder/public/cpp",
"//services/device/public/mojom",
+ "//services/metrics/public/cpp:ukm_builders",
"//services/network/public/mojom",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
@@ -947,6 +955,8 @@ static_library("extensions") {
"api/certificate_provider/certificate_provider_api.h",
"api/enterprise_device_attributes/enterprise_device_attributes_api.cc",
"api/enterprise_device_attributes/enterprise_device_attributes_api.h",
+ "api/enterprise_networking_attributes/enterprise_networking_attributes_api.cc",
+ "api/enterprise_networking_attributes/enterprise_networking_attributes_api.h",
"api/enterprise_platform_keys/enterprise_platform_keys_api.cc",
"api/enterprise_platform_keys/enterprise_platform_keys_api.h",
"api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc",
@@ -1004,10 +1014,12 @@ static_library("extensions") {
"//ash/keyboard/ui:resources_grit_grit",
"//ash/public/cpp",
"//chrome/browser/chromeos/crostini:crostini_installer_types_mojom",
- "//chrome/browser/resources/chromeos/camera:chrome_camera_app",
"//chrome/browser/ui/webui/settings/chromeos/constants:mojom",
"//chromeos",
"//chromeos/attestation",
+ "//chromeos/components/camera_app_ui",
+ "//chromeos/components/camera_app_ui:mojo_bindings",
+ "//chromeos/components/camera_app_ui/resources:chrome_camera_app",
"//chromeos/components/proximity_auth",
"//chromeos/constants",
"//chromeos/cryptohome",
@@ -1023,11 +1035,11 @@ static_library("extensions") {
"//chromeos/services/machine_learning/public/cpp",
"//chromeos/services/machine_learning/public/mojom",
"//chromeos/services/media_perception/public/mojom",
+ "//chromeos/services/tts/public/mojom",
"//chromeos/settings",
"//chromeos/system",
"//chromeos/tpm",
"//components/arc",
- "//components/chromeos_camera:camera_app_helper",
"//components/constrained_window",
"//components/drive",
"//components/user_manager",
@@ -1160,17 +1172,6 @@ static_library("extensions") {
]
}
- if (is_win || (is_linux && !is_chromeos)) {
- sources += [
- "api/input_ime/input_ime_api.cc",
- "api/input_ime/input_ime_api.h",
- "api/input_ime/input_ime_api_nonchromeos.cc",
- "api/input_ime/input_ime_api_nonchromeos.h",
- "api/input_ime/input_ime_event_router_base.cc",
- "api/input_ime/input_ime_event_router_base.h",
- ]
- }
-
if (enable_plugins) {
sources += [
"plugin_manager.cc",
@@ -1220,7 +1221,7 @@ static_library("extensions") {
"api/braille_display_private/brlapi_keycode_map.cc",
"api/braille_display_private/brlapi_keycode_map.h",
]
- deps += [ "//build/linux/libbrlapi" ]
+ deps += [ "//third_party/libbrlapi" ]
} else {
sources += [ "api/braille_display_private/braille_controller_stub.cc" ]
}
diff --git a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_apitest.cc b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_apitest.cc
index 5d7be8f6b8c..f26c3ec2c48 100644
--- a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_apitest.cc
@@ -58,13 +58,13 @@ class ActivityLogApiTest : public ExtensionApiTest {
base::CommandLine saved_cmdline_;
};
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-// TODO(crbug.com/299393): Flaky on Mac, Windows and Linux.
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER)
+// TODO(crbug.com/299393): This test is very long and can time out in debug or
+// ASAN builds.
#define MAYBE_TriggerEvent DISABLED_TriggerEvent
#else
#define MAYBE_TriggerEvent TriggerEvent
#endif
-
// The test extension sends a message to its 'friend'. The test completes
// if it successfully sees the 'friend' receive the message.
IN_PROC_BROWSER_TEST_F(ActivityLogApiTest, MAYBE_TriggerEvent) {
@@ -82,4 +82,3 @@ IN_PROC_BROWSER_TEST_F(ActivityLogApiTest, MAYBE_TriggerEvent) {
}
} // namespace extensions
-
diff --git a/chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc b/chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc
index eacee156995..1de49aa22be 100644
--- a/chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc
@@ -6,6 +6,7 @@
#include "content/public/test/browser_test.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/api/test.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"
@@ -15,12 +16,20 @@ using extensions::ResultCatcher;
namespace extensions {
-class AlarmsApiTest : public ExtensionApiTest {
+using ContextType = ExtensionApiTest::ContextType;
+
+class AlarmsApiTest : public ExtensionApiTest,
+ public testing::WithParamInterface<ContextType> {
public:
void SetUpOnMainThread() override {
ExtensionApiTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(StartEmbeddedTestServer());
+
+ // Service Workers are currently only available on certain channels, so set
+ // the channel for those tests.
+ if (GetParam() == ContextType::kServiceWorker)
+ current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>();
}
static std::unique_ptr<base::ListValue> BuildEventArguments(
@@ -30,11 +39,30 @@ class AlarmsApiTest : public ExtensionApiTest {
info.last_message = last_message;
return api::test::OnMessage::Create(info);
}
+
+ const Extension* LoadAlarmsExtensionIncognito(const char* path) {
+ int flags = kFlagEnableFileAccess | kFlagEnableIncognito;
+ if (GetParam() == ContextType::kServiceWorker)
+ flags |= kFlagRunAsServiceWorkerBasedExtension;
+
+ return LoadExtensionWithFlags(
+ test_data_dir_.AppendASCII("alarms").AppendASCII(path), flags);
+ }
+
+ private:
+ std::unique_ptr<ScopedWorkerBasedExtensionsChannel> current_channel_;
};
+INSTANTIATE_TEST_SUITE_P(EventPage,
+ AlarmsApiTest,
+ ::testing::Values(ContextType::kEventPage));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ AlarmsApiTest,
+ ::testing::Values(ContextType::kServiceWorker));
+
// 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) {
+IN_PROC_BROWSER_TEST_P(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();
@@ -48,8 +76,7 @@ IN_PROC_BROWSER_TEST_F(AlarmsApiTest, IncognitoSplit) {
ExtensionTestMessageListener listener_incognito("ready: true", false);
- ASSERT_TRUE(LoadExtensionIncognito(
- test_data_dir_.AppendASCII("alarms").AppendASCII("split")));
+ ASSERT_TRUE(LoadAlarmsExtensionIncognito("split"));
EXPECT_TRUE(listener.WaitUntilSatisfied());
EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
@@ -67,12 +94,11 @@ IN_PROC_BROWSER_TEST_F(AlarmsApiTest, IncognitoSplit) {
// 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) {
+IN_PROC_BROWSER_TEST_P(AlarmsApiTest, IncognitoSpanning) {
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
- ASSERT_TRUE(LoadExtensionIncognito(
- test_data_dir_.AppendASCII("alarms").AppendASCII("spanning")));
+ ASSERT_TRUE(LoadAlarmsExtensionIncognito("spanning"));
// Open incognito window.
OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
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
index a96f3c9d9d7..cb6fe1e90f2 100644
--- 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
@@ -189,9 +189,19 @@ void AutofillAssistantPrivateEventRouter::OnInfoBoxChanged(
void AutofillAssistantPrivateEventRouter::OnProgressChanged(int progress) {}
+void AutofillAssistantPrivateEventRouter::OnProgressActiveStepChanged(
+ int active_step) {}
+
void AutofillAssistantPrivateEventRouter::OnProgressVisibilityChanged(
bool visible) {}
+void AutofillAssistantPrivateEventRouter::OnStepProgressBarConfigurationChanged(
+ const autofill_assistant::ShowProgressBarProto::
+ StepProgressBarConfiguration& configuration) {}
+
+void AutofillAssistantPrivateEventRouter::OnProgressBarErrorStateChanged(
+ bool error) {}
+
void AutofillAssistantPrivateEventRouter::OnTouchableAreaChanged(
const autofill_assistant::RectF& visual_viewport,
const std::vector<autofill_assistant::RectF>& touchable_areas,
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
index d9b1b8fdea7..034c4e7decc 100644
--- 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
@@ -139,7 +139,12 @@ class AutofillAssistantPrivateEventRouter
void OnDetailsChanged(const autofill_assistant::Details* details) override;
void OnInfoBoxChanged(const autofill_assistant::InfoBox* info_box) override;
void OnProgressChanged(int progress) override;
+ void OnProgressActiveStepChanged(int active_step) override;
void OnProgressVisibilityChanged(bool visible) override;
+ void OnStepProgressBarConfigurationChanged(
+ const autofill_assistant::ShowProgressBarProto::
+ StepProgressBarConfiguration& configuration) override;
+ void OnProgressBarErrorStateChanged(bool error) override;
void OnTouchableAreaChanged(
const autofill_assistant::RectF& visual_viewport,
const std::vector<autofill_assistant::RectF>& touchable_areas,
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 450445fb776..9e6591918d7 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
@@ -347,11 +347,31 @@ ExtensionFunction::ResponseAction AutofillPrivateSaveCreditCardFunction::Run() {
base::UTF8ToUTF16(*card->expiration_year));
}
+ if (card->nickname) {
+ credit_card.SetNickname(base::UTF8ToUTF16(*card->nickname));
+ }
+
if (use_existing_card) {
+ // Only updates when the card info changes.
+ if (existing_card && existing_card->Compare(credit_card) == 0)
+ return RespondNow(NoArguments());
+
+ // Record when nickname is updated.
+ if (credit_card.HasValidNickname() &&
+ existing_card->nickname() != credit_card.nickname()) {
+ base::RecordAction(
+ base::UserMetricsAction("AutofillCreditCardsEditedWithNickname"));
+ }
+
personal_data->UpdateCreditCard(credit_card);
+ base::RecordAction(base::UserMetricsAction("AutofillCreditCardsEdited"));
} else {
personal_data->AddCreditCard(credit_card);
base::RecordAction(base::UserMetricsAction("AutofillCreditCardsAdded"));
+ if (credit_card.HasValidNickname()) {
+ base::RecordAction(
+ base::UserMetricsAction("AutofillCreditCardsAddedWithNickname"));
+ }
}
return RespondNow(NoArguments());
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 00a1b8607db..48da5f15a0a 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
@@ -44,8 +44,7 @@ class AutofillPrivateApiTest : public ExtensionApiTest {
// TODO(hcarmona): Investigate converting these tests to unittests.
-// TODO(crbug.com/643097) Disabled for flakiness.
-IN_PROC_BROWSER_TEST_F(AutofillPrivateApiTest, DISABLED_GetCountryList) {
+IN_PROC_BROWSER_TEST_F(AutofillPrivateApiTest, GetCountryList) {
EXPECT_TRUE(RunAutofillSubtest("getCountryList")) << message_;
}
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc b/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc
index cbe58c41776..10fe596182d 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc
@@ -146,6 +146,10 @@ autofill_private::CreditCardEntry CreditCardToCreditCardEntry(
credit_card.GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH))));
card.expiration_year.reset(new std::string(base::UTF16ToUTF8(
credit_card.GetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR))));
+ if (!credit_card.nickname().empty()) {
+ card.nickname.reset(
+ new std::string(base::UTF16ToUTF8(credit_card.nickname())));
+ }
// Create address metadata and add it to |address|.
std::unique_ptr<autofill_private::AutofillMetadata> metadata(
diff --git a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc
index 660aa4ed198..806848fbcb0 100644
--- a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc
@@ -757,7 +757,7 @@ IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, WriteCharacteristicValue) {
.WillRepeatedly(Return(chrc0_.get()));
std::vector<uint8_t> write_value;
- EXPECT_CALL(*chrc0_, WriteRemoteCharacteristic_(_, _, _))
+ EXPECT_CALL(*chrc0_, DeprecatedWriteRemoteCharacteristic_(_, _, _))
.Times(2)
.WillOnce(InvokeCallbackArgument<2>(
BluetoothRemoteGattService::GATT_ERROR_FAILED))
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 7b0cdb28d3d..cde5b9d368a 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
@@ -68,12 +68,12 @@ namespace StartDrag = api::bookmark_manager_private::StartDrag;
namespace {
// Returns a single bookmark node from the argument ID.
-// This returns NULL in case of failure.
+// This returns nullptr in case of failure.
const BookmarkNode* GetNodeFromString(BookmarkModel* model,
const std::string& id_string) {
int64_t id;
if (!base::StringToInt64(id_string, &id))
- return NULL;
+ return nullptr;
return bookmarks::GetBookmarkNodeByID(model, id);
}
@@ -197,7 +197,7 @@ void BookmarkManagerPrivateEventRouter::BookmarkModelChanged() {}
void BookmarkManagerPrivateEventRouter::BookmarkModelBeingDeleted(
BookmarkModel* model) {
- bookmark_model_ = NULL;
+ bookmark_model_ = nullptr;
}
BookmarkManagerPrivateAPI::BookmarkManagerPrivateAPI(
@@ -304,7 +304,7 @@ const BookmarkNodeData*
BookmarkManagerPrivateDragEventRouter::GetBookmarkNodeData() {
if (bookmark_drag_data_.is_valid())
return &bookmark_drag_data_;
- return NULL;
+ return nullptr;
}
void BookmarkManagerPrivateDragEventRouter::ClearBookmarkNodeData() {
@@ -509,7 +509,7 @@ BookmarkManagerPrivateGetSubtreeFunction::RunOnReady() {
if (!params)
return BadMessage();
- const BookmarkNode* node = NULL;
+ const BookmarkNode* node = nullptr;
if (params->id.empty()) {
BookmarkModel* model =
diff --git a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h
index b2617d86624..27e4655bd64 100644
--- a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h
+++ b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h
@@ -104,7 +104,7 @@ class BookmarkManagerPrivateDragEventRouter
void OnDrop(const bookmarks::BookmarkNodeData& data) override;
// The bookmark drag and drop data. This gets set after a drop was done on
- // the page. This returns NULL if no data is available.
+ // the page. This returns nullptr if no data is available.
const bookmarks::BookmarkNodeData* GetBookmarkNodeData();
// Clears the drag and drop data.
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
index 5f90d3df246..8671eb11e31 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
@@ -35,11 +35,11 @@ namespace bookmark_api_helpers {
class ExtensionBookmarksTest : public testing::Test {
public:
ExtensionBookmarksTest()
- : managed_(NULL),
- model_(NULL),
- node_(NULL),
- node2_(NULL),
- folder_(NULL) {}
+ : managed_(nullptr),
+ model_(nullptr),
+ node_(nullptr),
+ node2_(nullptr),
+ folder_(nullptr) {}
void SetUp() override {
profile_.CreateBookmarkModel(false);
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc
index 0664a2e51ba..78136b17ddb 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc
@@ -19,12 +19,37 @@
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_test.h"
+#include "extensions/common/scoped_worker_based_extensions_channel.h"
using bookmarks::BookmarkModel;
namespace extensions {
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Bookmarks) {
+using ContextType = ExtensionApiTest::ContextType;
+
+class BookmarksApiTest : public ExtensionApiTest,
+ public testing::WithParamInterface<ContextType> {
+ public:
+ void SetUp() override {
+ ExtensionApiTest::SetUp();
+ // Service Workers are currently only available on certain channels, so set
+ // the channel for those tests.
+ if (GetParam() == ContextType::kServiceWorker)
+ current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>();
+ }
+
+ private:
+ std::unique_ptr<ScopedWorkerBasedExtensionsChannel> current_channel_;
+};
+
+INSTANTIATE_TEST_SUITE_P(EventPage,
+ BookmarksApiTest,
+ ::testing::Values(ContextType::kEventPage));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ BookmarksApiTest,
+ ::testing::Values(ContextType::kServiceWorker));
+
+IN_PROC_BROWSER_TEST_P(BookmarksApiTest, Bookmarks) {
// Add test managed bookmarks to verify that the bookmarks API can read them
// and can't modify them.
Profile* profile = browser()->profile();
@@ -45,7 +70,13 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Bookmarks) {
profile->GetPrefs()->Set(bookmarks::prefs::kManagedBookmarks, list);
ASSERT_EQ(2u, managed->managed_node()->children().size());
- ASSERT_TRUE(RunExtensionTest("bookmarks")) << message_;
+ if (GetParam() == ContextType::kEventPage) {
+ ASSERT_TRUE(RunExtensionTest("bookmarks")) << message_;
+ } else {
+ ASSERT_TRUE(RunExtensionTestWithFlags(
+ "bookmarks", kFlagRunAsServiceWorkerBasedExtension, kFlagNone))
+ << message_;
+ }
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
index f7fa8079e88..2e7f7b8235d 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -272,7 +272,7 @@ void BookmarkEventRouter::BookmarkModelLoaded(BookmarkModel* model,
}
void BookmarkEventRouter::BookmarkModelBeingDeleted(BookmarkModel* model) {
- model_ = NULL;
+ model_ = nullptr;
}
void BookmarkEventRouter::BookmarkNodeMoved(BookmarkModel* model,
@@ -744,17 +744,12 @@ void BookmarksIOFunction::ShowSelectFileDialog(
gfx::NativeWindow owning_window =
web_contents ? platform_util::GetTopLevel(web_contents->GetNativeView())
: gfx::kNullNativeWindow;
- // |web_contents| can be NULL (for background pages), which is fine. In such
- // a case if file-selection dialogs are forbidden by policy, we will not
+ // |web_contents| can be nullptr (for background pages), which is fine. In
+ // such a case if file-selection dialogs are forbidden by policy, we will not
// show an InfoBar, which is better than letting one appear out of the blue.
- select_file_dialog_->SelectFile(type,
- base::string16(),
- default_path,
- &file_type_info,
- 0,
- base::FilePath::StringType(),
- owning_window,
- NULL);
+ select_file_dialog_->SelectFile(
+ type, base::string16(), default_path, &file_type_info, 0,
+ base::FilePath::StringType(), owning_window, nullptr);
}
void BookmarksIOFunction::FileSelectionCanceled(void* params) {
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.h b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.h
index e604b22d732..73703408cde 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.h
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.h
@@ -165,7 +165,7 @@ class BookmarksFunction : public ExtensionFunction,
bool EditBookmarksEnabled();
// Helper that checks if |node| can be modified. Returns false if |node|
- // is NULL, or a managed node, or the root node. In these cases the node
+ // is nullptr, or a managed node, or the root node. In these cases the node
// can't be edited, can't have new child nodes appended, and its direct
// children can't be moved or reordered.
bool CanBeModified(const bookmarks::BookmarkNode* node, std::string* error);
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 ab44ae9d90a..c1a99212564 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
@@ -15,7 +15,6 @@
#include "base/bind.h"
#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"
@@ -74,18 +73,17 @@ BrailleControllerImpl::~BrailleControllerImpl() {
void BrailleControllerImpl::TryLoadLibBrlApi() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (libbrlapi_loader_.loaded())
+ if (skip_libbrlapi_so_load_ || libbrlapi_loader_.loaded())
return;
- // These versions of libbrlapi work the same for the functions we
- // are using. (0.6.0 adds brlapi_writeWText).
- static const char* const kSupportedVersions[] = {
- "libbrlapi.so.0.5", "libbrlapi.so.0.6", "libbrlapi.so.0.7",
- "libbrlapi.so.0.8"};
- for (size_t i = 0; i < base::size(kSupportedVersions); ++i) {
- if (libbrlapi_loader_.Load(kSupportedVersions[i]))
- return;
+
+ // This api version needs to match the one contained in
+ // third_party/libbrlapi/brlapi.h.
+ static const char* const kSupportedVersion = "libbrlapi.so.0.8";
+
+ if (!libbrlapi_loader_.Load(kSupportedVersion)) {
+ LOG(WARNING) << "Couldn't load libbrlapi(" << kSupportedVersion << ": "
+ << strerror(errno);
}
- LOG(WARNING) << "Couldn't load libbrlapi: " << strerror(errno);
}
std::unique_ptr<DisplayState> BrailleControllerImpl::GetDisplayState() {
@@ -102,6 +100,10 @@ std::unique_ptr<DisplayState> BrailleControllerImpl::GetDisplayState() {
display_state->available = true;
display_state->text_column_count.reset(new int(columns));
display_state->text_row_count.reset(new int(rows));
+
+ unsigned int cell_size = 0;
+ connection_->GetCellSize(&cell_size);
+ display_state->cell_size.reset(new int(cell_size));
}
}
return display_state;
@@ -134,9 +136,9 @@ void BrailleControllerImpl::WriteDots(const std::vector<uint8_t>& cells,
void BrailleControllerImpl::AddObserver(BrailleObserver* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!base::PostTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&BrailleControllerImpl::StartConnecting,
- base::Unretained(this)))) {
+ if (!content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&BrailleControllerImpl::StartConnecting,
+ base::Unretained(this)))) {
NOTREACHED();
}
observers_.AddObserver(observer);
@@ -168,7 +170,7 @@ void BrailleControllerImpl::StartConnecting() {
return;
started_connecting_ = true;
TryLoadLibBrlApi();
- if (!libbrlapi_loader_.loaded()) {
+ if (!libbrlapi_loader_.loaded() && !skip_libbrlapi_so_load_) {
return;
}
@@ -212,8 +214,8 @@ void BrailleControllerImpl::OnSocketDirChangedOnTaskThread(
LOG(ERROR) << "Error watching brlapi directory: " << path.value();
return;
}
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&BrailleControllerImpl::OnSocketDirChangedOnIOThread,
base::Unretained(this)));
}
@@ -230,7 +232,7 @@ void BrailleControllerImpl::OnSocketDirChangedOnIOThread() {
void BrailleControllerImpl::TryToConnect() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(libbrlapi_loader_.loaded());
+ DCHECK(skip_libbrlapi_so_load_ || libbrlapi_loader_.loaded());
connect_scheduled_ = false;
if (!connection_.get())
connection_ = create_brlapi_connection_function_.Run();
@@ -271,10 +273,11 @@ void BrailleControllerImpl::ScheduleTryToConnect() {
}
VLOG(1) << "Scheduling connection retry to brlapi";
connect_scheduled_ = true;
- base::PostDelayedTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&BrailleControllerImpl::TryToConnect,
- base::Unretained(this)),
- kConnectionDelay);
+ content::GetIOThreadTaskRunner({})->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&BrailleControllerImpl::TryToConnect,
+ base::Unretained(this)),
+ kConnectionDelay);
}
void BrailleControllerImpl::Disconnect() {
@@ -288,7 +291,7 @@ void BrailleControllerImpl::Disconnect() {
std::unique_ptr<BrlapiConnection>
BrailleControllerImpl::CreateBrlapiConnection() {
- DCHECK(libbrlapi_loader_.loaded());
+ DCHECK(skip_libbrlapi_so_load_ || libbrlapi_loader_.loaded());
return BrlapiConnection::Create(&libbrlapi_loader_);
}
@@ -316,8 +319,8 @@ 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,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&BrailleControllerImpl::DispatchKeyEvent,
base::Unretained(this), std::move(event)));
return;
}
@@ -329,8 +332,8 @@ void BrailleControllerImpl::DispatchKeyEvent(std::unique_ptr<KeyEvent> event) {
void BrailleControllerImpl::DispatchOnDisplayStateChanged(
std::unique_ptr<DisplayState> new_state) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- if (!base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ if (!content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&BrailleControllerImpl::DispatchOnDisplayStateChanged,
base::Unretained(this), std::move(new_state)))) {
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
index fc98d3d832d..db1054e140c 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
@@ -83,6 +83,9 @@ class BrailleControllerImpl : public BrailleController {
// Manipulated by the SequencedTaskRunner.
base::FilePathWatcher file_path_watcher_;
+ // Set by tests to skip libbrlapi.so loading.
+ bool skip_libbrlapi_so_load_ = false;
+
friend struct base::DefaultSingletonTraits<BrailleControllerImpl>;
DISALLOW_COPY_AND_ASSIGN(BrailleControllerImpl);
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.cc b/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.cc
index fb509eb68ac..f77120a3600 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.cc
@@ -89,7 +89,7 @@ bool BrailleDisplayPrivateAPI::IsProfileActive() {
// Since we are creating one instance per profile / user, we should be fine
// comparing against the active user. That said - if we ever change that,
// this code will need to be changed.
- return profile_->IsSameProfile(ProfileManager::GetActiveUserProfile());
+ return profile_->IsSameOrParent(ProfileManager::GetActiveUserProfile());
#else // !defined(OS_CHROMEOS)
return true;
#endif
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc b/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
index 12ff95b9219..573132b3aa6 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/containers/circular_deque.h"
-#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -50,6 +49,7 @@ struct MockBrlapiConnectionData {
bool connected;
size_t display_columns;
size_t display_rows;
+ size_t cell_size;
brlapi_error_t error;
std::vector<std::string> written_content;
// List of brlapi key codes. A negative number makes the connection mock
@@ -69,8 +69,8 @@ class MockBrlapiConnection : public BrlapiConnection {
data_->connected = true;
on_data_ready_ = on_data_ready;
if (!data_->pending_keys.empty()) {
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&MockBrlapiConnection::NotifyDataReady,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&MockBrlapiConnection::NotifyDataReady,
base::Unretained(this)));
}
return CONNECT_SUCCESS;
@@ -80,8 +80,8 @@ class MockBrlapiConnection : public BrlapiConnection {
data_->connected = false;
if (data_->reappear_on_disconnect) {
data_->display_columns *= 2;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&BrailleControllerImpl::PokeSocketDirForTesting,
base::Unretained(BrailleControllerImpl::GetInstance())));
@@ -125,12 +125,17 @@ class MockBrlapiConnection : public BrlapiConnection {
}
}
+ bool GetCellSize(unsigned int* cell_size) override {
+ *cell_size = data_->cell_size;
+ return true;
+ }
+
private:
void NotifyDataReady() {
on_data_ready_.Run();
if (!data_->pending_keys.empty()) {
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&MockBrlapiConnection::NotifyDataReady,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&MockBrlapiConnection::NotifyDataReady,
base::Unretained(this)));
}
}
@@ -152,6 +157,7 @@ class BrailleDisplayPrivateApiTest : public ExtensionApiTest {
base::Bind(
&BrailleDisplayPrivateApiTest::CreateBrlapiConnection,
base::Unretained(this)));
+ BrailleControllerImpl::GetInstance()->skip_libbrlapi_so_load_ = true;
DisableAccessibilityManagerBraille();
}
@@ -178,6 +184,7 @@ class BrailleDisplayPrivateApiTest : public ExtensionApiTest {
IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, WriteDots) {
connection_data_.display_columns = 11;
connection_data_.display_rows = 1;
+ connection_data_.cell_size = 6;
ASSERT_TRUE(RunComponentExtensionTest("braille_display_private/write_dots"))
<< message_;
ASSERT_EQ(3U, connection_data_.written_content.size());
@@ -195,6 +202,7 @@ IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, WriteDots) {
IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, KeyEvents) {
connection_data_.display_columns = 11;
connection_data_.display_rows = 1;
+ connection_data_.cell_size = 6;
// Braille navigation commands.
connection_data_.pending_keys.push_back(BRLAPI_KEY_TYPE_CMD |
@@ -259,6 +267,7 @@ IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, KeyEvents) {
IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateApiTest, DisplayStateChanges) {
connection_data_.display_columns = 11;
connection_data_.display_rows = 1;
+ connection_data_.cell_size = 6;
connection_data_.pending_keys.push_back(kErrorKeyCode);
connection_data_.reappear_on_disconnect = true;
ASSERT_TRUE(RunComponentExtensionTest(
@@ -321,7 +330,7 @@ IN_PROC_BROWSER_TEST_F(BrailleDisplayPrivateAPIUserTest, KeyEventOnLockScreen) {
// Make sure the signin profile and active profile are different.
Profile* signin_profile = chromeos::ProfileHelper::GetSigninProfile();
Profile* user_profile = ProfileManager::GetActiveUserProfile();
- ASSERT_FALSE(signin_profile->IsSameProfile(user_profile))
+ ASSERT_FALSE(signin_profile->IsSameOrParent(user_profile))
<< signin_profile->GetDebugName() << " vs "
<< user_profile->GetDebugName();
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc b/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc
index 4995fa32b19..3d04c0cdc44 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.cc
@@ -7,6 +7,7 @@
#include <errno.h>
#include "base/files/file_descriptor_watcher_posix.h"
+#include "base/logging.h"
#include "base/memory/free_deleter.h"
#include "base/stl_util.h"
#include "base/system/sys_info.h"
@@ -44,6 +45,7 @@ class BrlapiConnectionImpl : public BrlapiConnection {
bool GetDisplaySize(unsigned int* rows, unsigned int* columns) override;
bool WriteDots(const std::vector<unsigned char>& cells) override;
int ReadKey(brlapi_keyCode_t* keyCode) override;
+ bool GetCellSize(unsigned int* cell_size) override;
private:
bool CheckConnected();
@@ -180,6 +182,23 @@ int BrlapiConnectionImpl::ReadKey(brlapi_keyCode_t* key_code) {
handle_.get(), 0 /*wait*/, key_code);
}
+bool BrlapiConnectionImpl::GetCellSize(unsigned int* cell_size) {
+ if (!CheckConnected()) {
+ return false;
+ }
+
+ brlapi_param_deviceCellSize_t device_cell_size;
+ ssize_t result = libbrlapi_loader_->brlapi__getParameter(
+ handle_.get(), BRLAPI_PARAM_DEVICE_CELL_SIZE, 0, BRLAPI_PARAMF_GLOBAL,
+ &device_cell_size, sizeof(device_cell_size));
+
+ if (result == -1 || result != sizeof(device_cell_size))
+ return false;
+
+ *cell_size = device_cell_size;
+ return true;
+}
+
bool BrlapiConnectionImpl::CheckConnected() {
if (!handle_) {
BrlapiError()->brlerrno = BRLAPI_ERROR_ILLEGAL_INSTRUCTION;
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.h b/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.h
index 0d1fddeb00a..3a7d028e6a8 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.h
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_connection.h
@@ -67,6 +67,9 @@ class BrlapiConnection {
// value.
virtual int ReadKey(brlapi_keyCode_t* keyCode) = 0;
+ // Gets the number of dots in a braille cell.
+ virtual bool GetCellSize(unsigned int* cell_size) = 0;
+
protected:
BrlapiConnection();
DISALLOW_COPY_AND_ASSIGN(BrlapiConnection);
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc b/chromium/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
index 0e07e7aa2e6..2b2b867331b 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
@@ -9,7 +9,7 @@ namespace api {
namespace braille_display_private {
MockBrailleController::MockBrailleController()
- : available_(false), observer_(NULL) {}
+ : available_(false), observer_(nullptr) {}
std::unique_ptr<DisplayState> MockBrailleController::GetDisplayState() {
std::unique_ptr<DisplayState> state(new DisplayState());
@@ -22,13 +22,13 @@ std::unique_ptr<DisplayState> MockBrailleController::GetDisplayState() {
}
void MockBrailleController::AddObserver(BrailleObserver* observer) {
- CHECK(observer_ == NULL);
+ CHECK(!observer_);
observer_ = observer;
}
void MockBrailleController::RemoveObserver(BrailleObserver* observer) {
CHECK(observer == observer_);
- observer_ = NULL;
+ observer_ = nullptr;
}
void MockBrailleController::SetAvailable(bool available) {
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 3ec6c150da5..a769041140d 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
@@ -12,7 +12,6 @@
#include <utility>
#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/chrome_browsing_data_remover_delegate.h"
@@ -102,7 +101,7 @@ static_assert((kFilterableDataTypes &
"kFilterableDataTypes must be a subset of "
"ChromeBrowsingDataRemoverDelegate::FILTERABLE_DATA_TYPES");
-int MaskForKey(const char* key) {
+uint64_t MaskForKey(const char* key) {
if (strcmp(key, extension_browsing_data_api_constants::kAppCacheKey) == 0)
return content::BrowsingDataRemover::DATA_TYPE_APP_CACHE;
if (strcmp(key, extension_browsing_data_api_constants::kCacheKey) == 0)
@@ -133,12 +132,12 @@ int MaskForKey(const char* key) {
if (strcmp(key, extension_browsing_data_api_constants::kWebSQLKey) == 0)
return content::BrowsingDataRemover::DATA_TYPE_WEB_SQL;
- return 0;
+ return 0ULL;
}
// Returns false if any of the selected data types are not allowed to be
// deleted.
-bool IsRemovalPermitted(int removal_mask, PrefService* prefs) {
+bool IsRemovalPermitted(uint64_t removal_mask, PrefService* prefs) {
// Enterprise policy or user preference might prohibit deleting browser or
// download history.
if ((removal_mask & ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY) ||
@@ -391,8 +390,8 @@ void BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported(
if (!PluginDataRemoverHelper::IsSupported(plugin_prefs.get()))
removal_mask_ &= ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&BrowsingDataRemoverFunction::StartRemoving, this));
}
#endif
@@ -456,7 +455,7 @@ void BrowsingDataRemoverFunction::StartRemoving() {
bool BrowsingDataRemoverFunction::ParseOriginTypeMask(
const base::DictionaryValue& options,
- int* origin_type_mask) {
+ uint64_t* origin_type_mask) {
// Parse the |options| dictionary to generate the origin set mask. Default to
// UNPROTECTED_WEB if the developer doesn't specify anything.
*origin_type_mask = content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
@@ -533,7 +532,7 @@ bool BrowsingDataRemoverFunction::ParseOrigins(const base::Value& list_value,
// Parses the |dataToRemove| argument to generate the removal mask.
// Returns false if parse was not successful, i.e. if 'dataToRemove' is not
// present or any data-type keys don't have supported (boolean) values.
-bool BrowsingDataRemoveFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveFunction::GetRemovalMask(uint64_t* removal_mask) {
base::DictionaryValue* data_to_remove;
if (!args_->GetDictionary(1, &data_to_remove))
return false;
@@ -556,73 +555,82 @@ bool BrowsingDataRemoveFunction::IsPauseSyncAllowed() {
return false;
}
-bool BrowsingDataRemoveAppcacheFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveAppcacheFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_APP_CACHE;
return true;
}
-bool BrowsingDataRemoveCacheFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveCacheFunction::GetRemovalMask(uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_CACHE;
return true;
}
-bool BrowsingDataRemoveCookiesFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveCookiesFunction::GetRemovalMask(uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_COOKIES;
return true;
}
-bool BrowsingDataRemoveDownloadsFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveDownloadsFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS;
return true;
}
-bool BrowsingDataRemoveFileSystemsFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveFileSystemsFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS;
return true;
}
-bool BrowsingDataRemoveFormDataFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveFormDataFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA;
return true;
}
-bool BrowsingDataRemoveHistoryFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveHistoryFunction::GetRemovalMask(uint64_t* removal_mask) {
*removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
return true;
}
-bool BrowsingDataRemoveIndexedDBFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveIndexedDBFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_INDEXED_DB;
return true;
}
-bool BrowsingDataRemoveLocalStorageFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveLocalStorageFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE;
return true;
}
-bool BrowsingDataRemovePluginDataFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemovePluginDataFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;
return true;
}
-bool BrowsingDataRemovePasswordsFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemovePasswordsFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS;
return true;
}
bool BrowsingDataRemoveServiceWorkersFunction::GetRemovalMask(
- int* removal_mask) {
+ uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS;
return true;
}
-bool BrowsingDataRemoveCacheStorageFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveCacheStorageFunction::GetRemovalMask(
+ uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE;
return true;
}
-bool BrowsingDataRemoveWebSQLFunction::GetRemovalMask(int* removal_mask) {
+bool BrowsingDataRemoveWebSQLFunction::GetRemovalMask(uint64_t* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_WEB_SQL;
return true;
}
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 6d39a5dfc38..e181262ab99 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
@@ -116,7 +116,7 @@ class BrowsingDataRemoverFunction
// based on the API call they represent.
// Returns whether or not removal mask retrieval was successful.
// |removal_mask| is populated with the result, if successful.
- virtual bool GetRemovalMask(int* removal_mask) = 0;
+ virtual bool GetRemovalMask(uint64_t* removal_mask) = 0;
// Returns true if the data removal is allowed to pause Sync. Returns true by
// default. Subclasses can override it to return false and prevent Sync from
@@ -135,7 +135,7 @@ class BrowsingDataRemoverFunction
// that can be used with the BrowsingDataRemover.
// Returns true if parsing was successful.
bool ParseOriginTypeMask(const base::DictionaryValue& options,
- int* origin_type_mask);
+ uint64_t* origin_type_mask);
// Parses the developer-provided list of origins into |result|.
// Returns whether or not parsing was successful. In case of parse failure,
@@ -152,8 +152,8 @@ class BrowsingDataRemoverFunction
void OnTaskFinished();
base::Time remove_since_;
- int removal_mask_ = 0;
- int origin_type_mask_ = 0;
+ uint64_t removal_mask_ = 0;
+ uint64_t origin_type_mask_ = 0;
std::vector<url::Origin> origins_;
content::BrowsingDataFilterBuilder::Mode mode_ =
content::BrowsingDataFilterBuilder::Mode::BLACKLIST;
@@ -174,7 +174,7 @@ class BrowsingDataRemoveAppcacheFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveAppcacheFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveFunction : public BrowsingDataRemoverFunction {
@@ -185,7 +185,7 @@ class BrowsingDataRemoveFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
bool IsPauseSyncAllowed() override;
};
@@ -198,7 +198,7 @@ class BrowsingDataRemoveCacheFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveCacheFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveCookiesFunction : public BrowsingDataRemoverFunction {
@@ -210,7 +210,7 @@ class BrowsingDataRemoveCookiesFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveCookiesFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveDownloadsFunction : public BrowsingDataRemoverFunction {
@@ -222,7 +222,7 @@ class BrowsingDataRemoveDownloadsFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveDownloadsFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveFileSystemsFunction
@@ -235,7 +235,7 @@ class BrowsingDataRemoveFileSystemsFunction
~BrowsingDataRemoveFileSystemsFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveFormDataFunction : public BrowsingDataRemoverFunction {
@@ -247,7 +247,7 @@ class BrowsingDataRemoveFormDataFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveFormDataFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveHistoryFunction : public BrowsingDataRemoverFunction {
@@ -259,7 +259,7 @@ class BrowsingDataRemoveHistoryFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveHistoryFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveIndexedDBFunction : public BrowsingDataRemoverFunction {
@@ -271,7 +271,7 @@ class BrowsingDataRemoveIndexedDBFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveIndexedDBFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveLocalStorageFunction
@@ -284,7 +284,7 @@ class BrowsingDataRemoveLocalStorageFunction
~BrowsingDataRemoveLocalStorageFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemovePluginDataFunction
@@ -297,7 +297,7 @@ class BrowsingDataRemovePluginDataFunction
~BrowsingDataRemovePluginDataFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemovePasswordsFunction : public BrowsingDataRemoverFunction {
@@ -309,7 +309,7 @@ class BrowsingDataRemovePasswordsFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemovePasswordsFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveServiceWorkersFunction
@@ -322,7 +322,7 @@ class BrowsingDataRemoveServiceWorkersFunction
~BrowsingDataRemoveServiceWorkersFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveCacheStorageFunction
@@ -335,7 +335,7 @@ class BrowsingDataRemoveCacheStorageFunction
~BrowsingDataRemoveCacheStorageFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
class BrowsingDataRemoveWebSQLFunction : public BrowsingDataRemoverFunction {
@@ -347,7 +347,7 @@ class BrowsingDataRemoveWebSQLFunction : public BrowsingDataRemoverFunction {
~BrowsingDataRemoveWebSQLFunction() override {}
// BrowsingDataRemoverFunction:
- bool GetRemovalMask(int* removal_mask) override;
+ bool GetRemovalMask(uint64_t* removal_mask) override;
};
#endif // CHROME_BROWSER_EXTENSIONS_API_BROWSING_DATA_BROWSING_DATA_API_H_
diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
index 9713ed1a3d0..8dc6ced4f5b 100644
--- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
+++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -29,6 +29,7 @@
#include "google_apis/gaia/google_service_auth_error.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "url/gurl.h"
using extension_function_test_utils::RunFunctionAndReturnSingleResult;
@@ -61,10 +62,9 @@ bool SetGaiaCookieForProfile(Profile* profile) {
bool success = false;
base::RunLoop loop;
base::OnceClosure loop_quit = loop.QuitClosure();
- base::OnceCallback<void(net::CanonicalCookie::CookieInclusionStatus)>
- callback = base::BindLambdaForTesting(
- [&success,
- &loop_quit](net::CanonicalCookie::CookieInclusionStatus s) {
+ base::OnceCallback<void(net::CookieInclusionStatus)> callback =
+ base::BindLambdaForTesting(
+ [&success, &loop_quit](net::CookieInclusionStatus s) {
success = s.IsInclude();
std::move(loop_quit).Run();
});
@@ -74,9 +74,9 @@ bool SetGaiaCookieForProfile(Profile* profile) {
cookie_manager->SetCanonicalCookie(
cookie, google_url, net::CookieOptions::MakeAllInclusive(),
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- std::move(callback), net::CanonicalCookie::CookieInclusionStatus(
- net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_UNKNOWN_ERROR)));
+ std::move(callback),
+ net::CookieInclusionStatus(
+ net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)));
loop.Run();
return success;
}
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 eb659cae14f..953451e762f 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
@@ -72,15 +72,17 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
return remover_->GetLastUsedBeginTimeForTesting();
}
- int GetRemovalMask() { return remover_->GetLastUsedRemovalMaskForTesting(); }
+ uint64_t GetRemovalMask() {
+ return remover_->GetLastUsedRemovalMaskForTesting();
+ }
- int GetOriginTypeMask() {
+ uint64_t GetOriginTypeMask() {
return remover_->GetLastUsedOriginTypeMaskForTesting();
}
- int GetAsMask(const base::DictionaryValue* dict,
- std::string path,
- int mask_value) {
+ uint64_t GetAsMask(const base::DictionaryValue* dict,
+ std::string path,
+ uint64_t mask_value) {
bool result;
EXPECT_TRUE(dict->GetBoolean(path, &result)) << "for " << path;
return result ? mask_value : 0;
@@ -88,7 +90,7 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
void RunBrowsingDataRemoveFunctionAndCompareRemovalMask(
const std::string& data_types,
- int expected_mask) {
+ uint64_t expected_mask) {
auto function = base::MakeRefCounted<BrowsingDataRemoveFunction>();
SCOPED_TRACE(data_types);
EXPECT_EQ(NULL, RunFunctionAndReturnSingleResult(
@@ -99,15 +101,16 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
EXPECT_EQ(UNPROTECTED_WEB, GetOriginTypeMask());
}
- void RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(const std::string& key,
- int expected_mask) {
+ void RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
+ const std::string& key,
+ uint64_t expected_mask) {
RunBrowsingDataRemoveFunctionAndCompareRemovalMask(
std::string("{\"") + key + "\": true}", expected_mask);
}
void RunBrowsingDataRemoveFunctionAndCompareOriginTypeMask(
const std::string& protectedStr,
- int expected_mask) {
+ uint64_t expected_mask) {
auto function = base::MakeRefCounted<BrowsingDataRemoveFunction>();
SCOPED_TRACE(protectedStr);
EXPECT_EQ(NULL, RunFunctionAndReturnSingleResult(
@@ -119,7 +122,7 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
}
template <class ShortcutFunction>
- void RunAndCompareRemovalMask(int expected_mask) {
+ void RunAndCompareRemovalMask(uint64_t expected_mask) {
scoped_refptr<ShortcutFunction> function = new ShortcutFunction();
SCOPED_TRACE(ShortcutFunction::function_name());
EXPECT_EQ(NULL,
@@ -161,8 +164,8 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
}
void SetPrefsAndVerifySettings(int data_type_flags,
- int expected_origin_type_mask,
- int expected_removal_mask) {
+ uint64_t expected_origin_type_mask,
+ uint64_t expected_removal_mask) {
PrefService* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
browsing_data::prefs::kLastClearBrowsingDataTab,
@@ -200,8 +203,8 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
}
void SetBasicPrefsAndVerifySettings(int data_type_flags,
- int expected_origin_type_mask,
- int expected_removal_mask) {
+ uint64_t expected_origin_type_mask,
+ uint64_t expected_removal_mask) {
PrefService* prefs = browser()->profile()->GetPrefs();
prefs->SetInteger(
browsing_data::prefs::kLastClearBrowsingDataTab,
@@ -223,8 +226,8 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
VerifyRemovalMask(expected_origin_type_mask, expected_removal_mask);
}
- void VerifyRemovalMask(int expected_origin_type_mask,
- int expected_removal_mask) {
+ void VerifyRemovalMask(uint64_t expected_origin_type_mask,
+ uint64_t expected_removal_mask) {
scoped_refptr<BrowsingDataSettingsFunction> function =
new BrowsingDataSettingsFunction();
SCOPED_TRACE("settings");
@@ -238,7 +241,7 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
EXPECT_TRUE(result->GetDictionary("options", &options));
base::DictionaryValue* origin_types;
EXPECT_TRUE(options->GetDictionary("originTypes", &origin_types));
- int origin_type_mask =
+ uint64_t origin_type_mask =
GetAsMask(origin_types, "unprotectedWeb", UNPROTECTED_WEB) |
GetAsMask(origin_types, "protectedWeb", PROTECTED_WEB) |
GetAsMask(origin_types, "extension", EXTENSION);
@@ -246,7 +249,7 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
base::DictionaryValue* data_to_remove;
EXPECT_TRUE(result->GetDictionary("dataToRemove", &data_to_remove));
- int removal_mask =
+ uint64_t removal_mask =
GetAsMask(data_to_remove, "appcache",
content::BrowsingDataRemover::DATA_TYPE_APP_CACHE) |
GetAsMask(data_to_remove, "cache",
@@ -467,9 +470,9 @@ TEST_F(BrowsingDataApiTest, BrowsingDataRemovalInputFromSettings) {
prefs->SetBoolean(browsing_data::prefs::kDeleteHostedAppsData, false);
prefs->SetBoolean(browsing_data::prefs::kDeletePasswords, false);
prefs->SetBoolean(prefs::kClearPluginLSODataEnabled, false);
- int expected_mask = content::BrowsingDataRemover::DATA_TYPE_CACHE |
- content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS |
- ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
+ uint64_t expected_mask = content::BrowsingDataRemover::DATA_TYPE_CACHE |
+ content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
std::string json;
// Scoping for the traces.
{
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
deleted file mode 100644
index 6ebf8e5713e..00000000000
--- a/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc
+++ /dev/null
@@ -1,420 +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 <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <cmath>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/thread_restrictions.h"
-#include "build/build_config.h"
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/common/chrome_switches.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test.h"
-#include "extensions/common/switches.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/video_frame.h"
-#include "media/cast/cast_config.h"
-#include "media/cast/cast_environment.h"
-#include "media/cast/test/utility/audio_utility.h"
-#include "media/cast/test/utility/default_config.h"
-#include "media/cast/test/utility/in_process_receiver.h"
-#include "media/cast/test/utility/net_utility.h"
-#include "media/cast/test/utility/standalone_cast_environment.h"
-#include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
-#include "net/log/net_log_source.h"
-#include "net/socket/udp_server_socket.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using media::cast::test::GetFreeLocalPort;
-
-namespace extensions {
-
-class CastStreamingApiTest : public ExtensionApiTest {
- public:
- void SetUpCommandLine(base::CommandLine* command_line) override {
- ExtensionApiTest::SetUpCommandLine(command_line);
- command_line->AppendSwitchASCII(
- extensions::switches::kWhitelistedExtensionID,
- "ddchlicdkolnonkihahngkmmmjnjlkkf");
- command_line->AppendSwitchASCII(::switches::kWindowSize, "300,300");
- }
-};
-
-// Test running the test extension for Cast Mirroring API.
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTest, Basics) {
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "basics.html")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTest, Stats) {
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "stats.html")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTest, BadLogging) {
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "bad_logging.html"))
- << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTest, DestinationNotSet) {
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "destination_not_set.html"))
- << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTest, StopNoStart) {
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "stop_no_start.html"))
- << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTest, NullStream) {
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "null_stream.html"))
- << message_;
-}
-
-namespace {
-
-struct YUVColor {
- int y;
- int u;
- int v;
-
- YUVColor() : y(0), u(0), v(0) {}
- YUVColor(int y_val, int u_val, int v_val) : y(y_val), u(u_val), v(v_val) {}
-};
-
-media::cast::FrameReceiverConfig WithFakeAesKeyAndIv(
- media::cast::FrameReceiverConfig config) {
- config.aes_key = "0123456789abcdef";
- config.aes_iv_mask = "fedcba9876543210";
- return config;
-}
-
-// An in-process Cast receiver that examines the audio/video frames being
-// received for expected colors and tones. Used in
-// CastStreamingApiTest.EndToEnd, below.
-class TestPatternReceiver : public media::cast::InProcessReceiver {
- public:
- explicit TestPatternReceiver(
- const scoped_refptr<media::cast::CastEnvironment>& cast_environment,
- const net::IPEndPoint& local_end_point)
- : InProcessReceiver(
- cast_environment,
- local_end_point,
- net::IPEndPoint(),
- WithFakeAesKeyAndIv(media::cast::GetDefaultAudioReceiverConfig()),
- WithFakeAesKeyAndIv(media::cast::GetDefaultVideoReceiverConfig())) {
- }
-
- ~TestPatternReceiver() override {}
-
- void AddExpectedTone(int tone_frequency) {
- expected_tones_.push_back(tone_frequency);
- }
-
- void AddExpectedColor(const YUVColor& yuv_color) {
- expected_yuv_colors_.push_back(yuv_color);
- }
-
- // Blocks the caller until all expected tones and colors have been observed.
- void WaitForExpectedTonesAndColors() {
- base::RunLoop run_loop;
- cast_env()->PostTask(
- media::cast::CastEnvironment::MAIN, FROM_HERE,
- base::BindOnce(
- &TestPatternReceiver::NotifyOnceObservedAllTonesAndColors,
- base::Unretained(this),
- media::BindToCurrentLoop(run_loop.QuitClosure())));
- run_loop.Run();
- }
-
- private:
- void NotifyOnceObservedAllTonesAndColors(const base::Closure& done_callback) {
- DCHECK(cast_env()->CurrentlyOn(media::cast::CastEnvironment::MAIN));
- done_callback_ = done_callback;
- MaybeRunDoneCallback();
- }
-
- void MaybeRunDoneCallback() {
- DCHECK(cast_env()->CurrentlyOn(media::cast::CastEnvironment::MAIN));
- if (done_callback_.is_null())
- return;
- if (expected_tones_.empty() && expected_yuv_colors_.empty()) {
- std::move(done_callback_).Run();
- } else {
- LOG(INFO) << "Waiting to encounter " << expected_tones_.size()
- << " more tone(s) and " << expected_yuv_colors_.size()
- << " more color(s).";
- }
- }
-
- // Invoked by InProcessReceiver for each received audio frame.
- void OnAudioFrame(std::unique_ptr<media::AudioBus> audio_frame,
- base::TimeTicks playout_time,
- bool is_continuous) override {
- DCHECK(cast_env()->CurrentlyOn(media::cast::CastEnvironment::MAIN));
-
- if (audio_frame->frames() <= 0) {
- NOTREACHED() << "OnAudioFrame called with no samples?!?";
- return;
- }
-
- if (done_callback_.is_null() || expected_tones_.empty())
- return; // No need to waste CPU doing analysis on the signal.
-
- // Assume the audio signal is a single sine wave (it can have some
- // low-amplitude noise). Count zero crossings, and extrapolate the
- // frequency of the sine wave in |audio_frame|.
- int crossings = 0;
- for (int ch = 0; ch < audio_frame->channels(); ++ch) {
- crossings += media::cast::CountZeroCrossings(audio_frame->channel(ch),
- audio_frame->frames());
- }
- crossings /= audio_frame->channels(); // Take the average.
- const float seconds_per_frame =
- audio_frame->frames() / static_cast<float>(audio_config().rtp_timebase);
- const float frequency = crossings / seconds_per_frame / 2.0f;
- VLOG(1) << "Current audio tone frequency: " << frequency;
-
- const int kTargetWindowHz = 20;
- for (auto it = expected_tones_.begin(); it != expected_tones_.end(); ++it) {
- if (abs(static_cast<int>(frequency) - *it) < kTargetWindowHz) {
- LOG(INFO) << "Heard tone at frequency " << *it << " Hz.";
- expected_tones_.erase(it);
- MaybeRunDoneCallback();
- break;
- }
- }
- }
-
- void OnVideoFrame(scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks playout_time,
- bool is_continuous) override {
- DCHECK(cast_env()->CurrentlyOn(media::cast::CastEnvironment::MAIN));
-
- CHECK(video_frame->format() == media::PIXEL_FORMAT_YV12 ||
- video_frame->format() == media::PIXEL_FORMAT_I420 ||
- video_frame->format() == media::PIXEL_FORMAT_I420A);
-
- if (done_callback_.is_null() || expected_yuv_colors_.empty())
- return; // No need to waste CPU doing analysis on the frame.
-
- // Take the median value of each plane because the test image will contain a
- // letterboxed content region of mostly a solid color plus a small piece of
- // "something" that's animating to keep the tab capture pipeline generating
- // new frames.
- const gfx::Rect region = FindLetterboxedContentRegion(*video_frame);
- YUVColor current_color;
- current_color.y = ComputeMedianIntensityInRegionInPlane(
- region,
- video_frame->stride(media::VideoFrame::kYPlane),
- video_frame->data(media::VideoFrame::kYPlane));
- current_color.u = ComputeMedianIntensityInRegionInPlane(
- gfx::ScaleToEnclosedRect(region, 0.5f),
- video_frame->stride(media::VideoFrame::kUPlane),
- video_frame->data(media::VideoFrame::kUPlane));
- current_color.v = ComputeMedianIntensityInRegionInPlane(
- gfx::ScaleToEnclosedRect(region, 0.5f),
- video_frame->stride(media::VideoFrame::kVPlane),
- video_frame->data(media::VideoFrame::kVPlane));
- VLOG(1) << "Current video color: yuv(" << current_color.y << ", "
- << current_color.u << ", " << current_color.v << ')';
-
- // Note: The range of acceptable colors is quite large because there's no
- // way to know whether software compositing is being used for screen
- // capture; and, if software compositing is being used, there is no color
- // space management and color values can be off by a lot. That said, color
- // accuracy is being tested by a suite of content_browsertests.
- const int kTargetWindow = 50;
- for (auto it = expected_yuv_colors_.begin();
- it != expected_yuv_colors_.end(); ++it) {
- if (abs(current_color.y - it->y) < kTargetWindow &&
- abs(current_color.u - it->u) < kTargetWindow &&
- abs(current_color.v - it->v) < kTargetWindow) {
- LOG(INFO) << "Saw expected color yuv(" << it->y << ", " << it->u << ", "
- << it->v << ") as yuv(" << current_color.y << ", "
- << current_color.u << ", " << current_color.v << ").";
- expected_yuv_colors_.erase(it);
- MaybeRunDoneCallback();
- break;
- }
- }
- }
-
- // Return the region that excludes the black letterboxing borders surrounding
- // the content within |frame|, if any.
- static gfx::Rect FindLetterboxedContentRegion(
- const media::VideoFrame& frame) {
- const int kNonBlackIntensityThreshold = 20; // 16 plus some fuzz.
- const int width = frame.row_bytes(media::VideoFrame::kYPlane);
- const int height = frame.rows(media::VideoFrame::kYPlane);
- const int stride = frame.stride(media::VideoFrame::kYPlane);
-
- gfx::Rect result;
-
- // Scan from the bottom-right until the first non-black pixel is
- // encountered.
- for (int y = height - 1; y >= 0; --y) {
- const uint8_t* const start =
- frame.data(media::VideoFrame::kYPlane) + y * stride;
- const uint8_t* const end = start + width;
- for (const uint8_t* p = end - 1; p >= start; --p) {
- if (*p > kNonBlackIntensityThreshold) {
- result.set_width(p - start + 1);
- result.set_height(y + 1);
- y = 0; // Discontinue outer loop.
- break;
- }
- }
- }
-
- // Scan from the upper-left until the first non-black pixel is encountered.
- for (int y = 0; y < result.height(); ++y) {
- const uint8_t* const start =
- frame.data(media::VideoFrame::kYPlane) + y * stride;
- const uint8_t* const end = start + result.width();
- for (const uint8_t* p = start; p < end; ++p) {
- if (*p > kNonBlackIntensityThreshold) {
- result.set_x(p - start);
- result.set_width(result.width() - result.x());
- result.set_y(y);
- result.set_height(result.height() - result.y());
- y = result.height(); // Discontinue outer loop.
- break;
- }
- }
- }
-
- return result;
- }
-
- static uint8_t ComputeMedianIntensityInRegionInPlane(const gfx::Rect& region,
- int stride,
- const uint8_t* data) {
- if (region.IsEmpty())
- return 0;
- const size_t num_values = region.size().GetArea();
- std::unique_ptr<uint8_t[]> values(new uint8_t[num_values]);
- for (int y = 0; y < region.height(); ++y) {
- memcpy(values.get() + y * region.width(),
- data + (region.y() + y) * stride + region.x(),
- region.width());
- }
- const size_t middle_idx = num_values / 2;
- std::nth_element(values.get(),
- values.get() + middle_idx,
- values.get() + num_values);
- return values[middle_idx];
- }
-
- std::vector<int> expected_tones_;
- std::vector<YUVColor> expected_yuv_colors_;
- base::Closure done_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(TestPatternReceiver);
-};
-
-} // namespace
-
-class CastStreamingApiTestWithPixelOutput
- : public CastStreamingApiTest,
- public testing::WithParamInterface<bool> {
- public:
-
- void SetUp() override {
- EnablePixelOutput();
- CastStreamingApiTest::SetUp();
- }
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitchASCII(::switches::kWindowSize, "128,128");
- CastStreamingApiTest::SetUpCommandLine(command_line);
- }
-
- private:
- base::test::ScopedFeatureList audio_service_features_;
-};
-
-// Tests the Cast streaming API and its basic functionality end-to-end. An
-// extension subtest is run to generate test content, capture that content, and
-// use the API to send it out. At the same time, this test launches an
-// in-process Cast receiver, listening on a localhost UDP socket, to receive the
-// content and check whether it matches expectations.
-#if defined(NDEBUG) && !defined(OS_MACOSX)
-#define MAYBE_EndToEnd EndToEnd
-#else
-// Flaky on Mac: https://crbug.com/841387
-#define MAYBE_EndToEnd DISABLED_EndToEnd // crbug.com/396413
-#endif
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTestWithPixelOutput, MAYBE_EndToEnd) {
- std::unique_ptr<net::UDPServerSocket> receive_socket(
- new net::UDPServerSocket(NULL, net::NetLogSource()));
- receive_socket->AllowAddressReuse();
- ASSERT_EQ(net::OK, receive_socket->Listen(GetFreeLocalPort()));
- net::IPEndPoint receiver_end_point;
- ASSERT_EQ(net::OK, receive_socket->GetLocalAddress(&receiver_end_point));
- receive_socket.reset();
-
- // Start the in-process receiver that examines audio/video for the expected
- // test patterns.
- const scoped_refptr<media::cast::StandaloneCastEnvironment> cast_environment(
- new media::cast::StandaloneCastEnvironment());
- TestPatternReceiver* const receiver =
- new TestPatternReceiver(cast_environment, receiver_end_point);
-
- // Launch the page that: 1) renders the source content; 2) uses the
- // chrome.tabCapture and chrome.cast.streaming APIs to capture its content and
- // stream using Cast; and 3) calls chrome.test.succeed() once it is
- // operational.
- const std::string page_url = base::StringPrintf(
- "end_to_end_sender.html?port=%d&aesKey=%s&aesIvMask=%s",
- receiver_end_point.port(),
- base::HexEncode(receiver->audio_config().aes_key.data(),
- receiver->audio_config().aes_key.size()).c_str(),
- base::HexEncode(receiver->audio_config().aes_iv_mask.data(),
- receiver->audio_config().aes_iv_mask.size()).c_str());
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", page_url)) << message_;
-
- // Examine the Cast receiver for expected audio/video test patterns. The
- // colors and tones specified here must match those in end_to_end_sender.js.
- // Note that we do not check that the color and tone are received
- // simultaneously since A/V sync should be measured in perf tests.
- receiver->AddExpectedTone(200 /* Hz */);
- receiver->AddExpectedTone(500 /* Hz */);
- receiver->AddExpectedTone(1800 /* Hz */);
- receiver->AddExpectedColor(YUVColor(63, 102, 239)); // rgb(255, 0, 0)
- receiver->AddExpectedColor(YUVColor(173, 41, 26)); // rgb(0, 255, 0)
- receiver->AddExpectedColor(YUVColor(32, 239, 117)); // rgb(0, 0, 255)
- receiver->Start();
- receiver->WaitForExpectedTonesAndColors();
- receiver->Stop();
-
- delete receiver;
- base::ScopedAllowBlockingForTesting allow_blocking;
- cast_environment->Shutdown();
-}
-
-#if !defined(OS_MACOSX)
-#define MAYBE_RtpStreamError RtpStreamError
-#else
-// Flaky on Mac https://crbug.com/841986
-#define MAYBE_RtpStreamError DISABLED_RtpStreamError
-#endif
-IN_PROC_BROWSER_TEST_F(CastStreamingApiTestWithPixelOutput,
- MAYBE_RtpStreamError) {
- ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "rtp_stream_error.html"));
-}
-
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc b/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc
index 69a5d995237..5be83c91173 100644
--- a/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc
+++ b/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc
@@ -742,9 +742,14 @@ IN_PROC_BROWSER_TEST_P(CastV2PerformanceTest, DISABLED_Performance) {
// Load the extension and test page, and tell the extension to start tab
// capture + Cast Streaming.
- LoadExtension(GetApiTestDataDir()
- .AppendASCII("cast_streaming")
- .AppendASCII("perftest_extension"));
+
+ // TODO(https://crbug.com/974427): Update test to no longer require
+ // extension APIs.
+
+ // LoadExtension(GetApiTestDataDir()
+ // .AppendASCII("cast_streaming")
+ // .AppendASCII("perftest_extension"));
+
NavigateToTestPage(test_page_html_);
const base::Value response = SendMessageToExtension(base::StringPrintf(
"{start:true, enableAutoThrottling:%s, maxFrameRate:%d, recvPort:%d,"
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 80918c5ca00..472210d290f 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
@@ -249,8 +249,8 @@ CertificateProviderStopPinRequestFunction::
ExtensionFunction::ResponseAction
CertificateProviderStopPinRequestFunction::Run() {
- std::unique_ptr<api_cp::RequestPin::Params> params(
- api_cp::RequestPin::Params::Create(*args_));
+ std::unique_ptr<api_cp::StopPinRequest::Params> params(
+ api_cp::StopPinRequest::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
// TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
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 57049879e4c..f9fe19fc02a 100644
--- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -46,15 +46,12 @@
#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/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"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
-#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"
@@ -62,6 +59,7 @@
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
+#include "extensions/browser/supervised_user_extensions_delegate.h"
#include "extensions/browser/value_store/value_store_factory.h"
#include "google_apis/gaia/gaia_urls.h"
#include "printing/buildflags/buildflags.h"
@@ -81,7 +79,7 @@
#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"
+#include "chrome/browser/supervised_user/supervised_user_extensions_delegate_impl.h"
#endif
namespace extensions {
@@ -116,10 +114,6 @@ void ChromeExtensionsAPIClient::AttachWebContentsHelpers(
extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
web_contents);
- if (auto* performance_manager_registry =
- performance_manager::PerformanceManagerRegistry::GetInstance()) {
- performance_manager_registry->CreatePageNodeForWebContents(web_contents);
- }
}
bool ChromeExtensionsAPIClient::ShouldHideResponseHeader(
@@ -340,10 +334,10 @@ ManagementAPIDelegate* ChromeExtensionsAPIClient::CreateManagementAPIDelegate()
return new ChromeManagementAPIDelegate;
}
-std::unique_ptr<SupervisedUserServiceDelegate>
-ChromeExtensionsAPIClient::CreateSupervisedUserServiceDelegate() const {
+std::unique_ptr<SupervisedUserExtensionsDelegate>
+ChromeExtensionsAPIClient::CreateSupervisedUserExtensionsDelegate() const {
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
- return std::make_unique<SupervisedUserServiceManagementAPIDelegate>();
+ return std::make_unique<SupervisedUserExtensionsDelegateImpl>();
#else
return nullptr;
#endif
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 a9498af9053..98d45c99383 100644
--- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h
+++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h
@@ -67,8 +67,8 @@ 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<SupervisedUserExtensionsDelegate>
+ CreateSupervisedUserExtensionsDelegate() const override;
std::unique_ptr<DisplayInfoProvider> CreateDisplayInfoProvider()
const override;
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 cd71b0bd21c..f21fdbb45dd 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
@@ -33,6 +33,7 @@
#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/features.h"
#include "components/permissions/features.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -311,6 +312,16 @@ ContentSettingsContentSettingSetFunction::Run() {
store->SetExtensionContentSetting(extension_id(), primary_pattern,
secondary_pattern, content_type,
resource_identifier, setting, scope);
+
+ if (base::FeatureList::IsEnabled(
+ content_settings::kDisallowWildcardsInPluginContentSettings) &&
+ content_type == ContentSettingsType::PLUGINS &&
+ primary_pattern.HasHostWildcards()) {
+ WriteToConsole(
+ blink::mojom::ConsoleMessageLevel::kError,
+ content_settings_api_constants::kWildcardPatternsForPluginsDisallowed);
+ }
+
return RespondNow(NoArguments());
}
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.cc
index efd89b9c283..27aa53d3720 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.cc
@@ -23,6 +23,8 @@ const char kIncognitoSessionOnlyError[] =
"You cannot read incognito content settings when no incognito window "
"is open.";
const char kInvalidUrlError[] = "The URL \"*\" is invalid.";
-
+const char kWildcardPatternsForPluginsDisallowed[] =
+ "Host wildcards ('*') and \"<all_urls>\" are no longer "
+ "supported in `primaryPattern` for `plugins`.";
} // namespace content_settings_api_constants
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.h b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.h
index 492fb00260e..65cef1f6b24 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.h
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api_constants.h
@@ -23,7 +23,7 @@ extern const char kSecondaryPatternKey[];
extern const char kIncognitoContextError[];
extern const char kIncognitoSessionOnlyError[];
extern const char kInvalidUrlError[];
-
+extern const char kWildcardPatternsForPluginsDisallowed[];
}
} // 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 b34033a96b1..60626f7d26f 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
@@ -18,15 +18,19 @@
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/permissions/permission_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.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/content_settings/core/common/features.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/permissions/permission_manager.h"
+#include "components/permissions/permission_result.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
@@ -36,12 +40,15 @@
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/test_extension_registry_observer.h"
+#include "extensions/common/scoped_worker_based_extensions_channel.h"
namespace extensions {
+using ContextType = ExtensionApiTest::ContextType;
+
class ExtensionContentSettingsApiTest : public ExtensionApiTest {
public:
- ExtensionContentSettingsApiTest() : profile_(NULL) {}
+ ExtensionContentSettingsApiTest() : profile_(nullptr) {}
void SetUpOnMainThread() override {
ExtensionApiTest::SetUpOnMainThread();
@@ -89,7 +96,7 @@ class ExtensionContentSettingsApiTest : public ExtensionApiTest {
map->GetContentSetting(example_url, example_url,
ContentSettingsType::JAVASCRIPT, std::string()));
EXPECT_EQ(
- CONTENT_SETTING_ALLOW,
+ CONTENT_SETTING_BLOCK,
map->GetContentSetting(example_url, example_url,
ContentSettingsType::PLUGINS, std::string()));
EXPECT_EQ(
@@ -134,7 +141,7 @@ class ExtensionContentSettingsApiTest : public ExtensionApiTest {
EXPECT_EQ(CONTENT_SETTING_BLOCK,
map->GetContentSetting(url, url, ContentSettingsType::JAVASCRIPT,
std::string()));
- EXPECT_EQ(CONTENT_SETTING_DETECT_IMPORTANT_CONTENT,
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
map->GetContentSetting(url, url, ContentSettingsType::PLUGINS,
std::string()));
EXPECT_EQ(CONTENT_SETTING_ALLOW,
@@ -256,6 +263,42 @@ class ExtensionContentSettingsApiTest : public ExtensionApiTest {
std::unique_ptr<ScopedKeepAlive> keep_alive_;
};
+class ExtensionContentSettingsApiLazyTest
+ : public ExtensionContentSettingsApiTest,
+ public testing::WithParamInterface<ContextType> {
+ public:
+ void SetUp() override {
+ ExtensionContentSettingsApiTest::SetUp();
+ // Service Workers are currently only available on certain channels, so set
+ // the channel for those tests.
+ if (GetParam() == ContextType::kServiceWorker)
+ current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>();
+ }
+
+ protected:
+ bool RunLazyTest(const std::string& extension_name) {
+ return RunLazyTestWithArg(extension_name, nullptr);
+ }
+
+ bool RunLazyTestWithArg(const std::string& extension_name, const char* arg) {
+ int browser_test_flags = kFlagNone;
+ if (GetParam() == ContextType::kServiceWorker)
+ browser_test_flags |= kFlagRunAsServiceWorkerBasedExtension;
+
+ return RunExtensionTestWithFlagsAndArg(extension_name, arg,
+ browser_test_flags, kFlagNone);
+ }
+
+ std::unique_ptr<ScopedWorkerBasedExtensionsChannel> current_channel_;
+};
+
+INSTANTIATE_TEST_SUITE_P(EventPage,
+ ExtensionContentSettingsApiLazyTest,
+ ::testing::Values(ContextType::kEventPage));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ ExtensionContentSettingsApiLazyTest,
+ ::testing::Values(ContextType::kServiceWorker));
+
IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, Standard) {
CheckContentSettingsDefault();
@@ -285,7 +328,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, Standard) {
// brittle or just have the JS side look for the additional plugins.
//
// Flaky on the trybots. See http://crbug.com/96725.
-IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
+IN_PROC_BROWSER_TEST_P(ExtensionContentSettingsApiLazyTest,
DISABLED_GetResourceIdentifiers) {
base::FilePath::CharType kFooPath[] =
FILE_PATH_LITERAL("/plugins/foo.plugin");
@@ -307,21 +350,22 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
base::ASCIIToUTF16("bar")),
false);
- EXPECT_TRUE(RunExtensionTest("content_settings/getresourceidentifiers"))
+ EXPECT_TRUE(RunLazyTest("content_settings/getresourceidentifiers"))
<< message_;
}
-IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
+IN_PROC_BROWSER_TEST_P(ExtensionContentSettingsApiLazyTest,
UnsupportedDefaultSettings) {
const char kExtensionPath[] = "content_settings/unsupporteddefaultsettings";
- EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_;
+ EXPECT_TRUE(RunExtensionTest(kExtensionPath)) << message_;
}
// Tests if an extension clearing content settings for one content type leaves
// the others unchanged.
-IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, ClearProperlyGranular) {
+IN_PROC_BROWSER_TEST_P(ExtensionContentSettingsApiLazyTest,
+ ClearProperlyGranular) {
const char kExtensionPath[] = "content_settings/clearproperlygranular";
- EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_;
+ EXPECT_TRUE(RunLazyTest(kExtensionPath)) << message_;
}
// Tests if changing permissions in incognito mode keeps the previous state of
@@ -333,9 +377,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, IncognitoIsolation) {
std::vector<int> content_settings_before = GetContentSettingsSnapshot(url);
// Run extension, set all permissions to allow, and check if they are changed.
- EXPECT_TRUE(RunExtensionSubtest("content_settings/incognitoisolation",
- "test.html?allow", kFlagEnableIncognito,
- kFlagUseIncognito))
+ EXPECT_TRUE(RunExtensionSubtestWithArgAndFlags(
+ "content_settings/incognitoisolation", "test.html", "allow",
+ kFlagEnableIncognito, kFlagUseIncognito))
<< message_;
// Get content settings after running extension to ensure nothing is changed.
@@ -343,9 +387,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, IncognitoIsolation) {
EXPECT_EQ(content_settings_before, content_settings_after);
// Run extension, set all permissions to block, and check if they are changed.
- EXPECT_TRUE(RunExtensionSubtest("content_settings/incognitoisolation",
- "test.html?block", kFlagEnableIncognito,
- kFlagUseIncognito))
+ EXPECT_TRUE(RunExtensionSubtestWithArgAndFlags(
+ "content_settings/incognitoisolation", "test.html", "block",
+ kFlagEnableIncognito, kFlagUseIncognito))
<< message_;
// Get content settings after running extension to ensure nothing is changed.
@@ -356,16 +400,16 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, IncognitoIsolation) {
// Tests if changing incognito mode permissions in regular profile are rejected.
IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
IncognitoNotAllowedInRegular) {
- EXPECT_FALSE(RunExtensionSubtest("content_settings/incognitoisolation",
- "test.html?allow"))
+ EXPECT_FALSE(RunExtensionSubtestWithArg("content_settings/incognitoisolation",
+ "test.html", "allow"))
<< message_;
}
-IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
+IN_PROC_BROWSER_TEST_P(ExtensionContentSettingsApiLazyTest,
EmbeddedSettingsMetric) {
base::HistogramTester histogram_tester;
const char kExtensionPath[] = "content_settings/embeddedsettingsmetric";
- EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_;
+ EXPECT_TRUE(RunLazyTest(kExtensionPath)) << message_;
size_t num_values = 0;
int images_type = ContentSettingTypeToHistogramValue(
@@ -391,7 +435,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
}
class ExtensionContentSettingsApiTestWithPermissionDelegationDisabled
- : public ExtensionContentSettingsApiTest {
+ : public ExtensionContentSettingsApiLazyTest {
public:
ExtensionContentSettingsApiTestWithPermissionDelegationDisabled() {
feature_list_.InitAndDisableFeature(
@@ -402,8 +446,18 @@ class ExtensionContentSettingsApiTestWithPermissionDelegationDisabled
base::test::ScopedFeatureList feature_list_;
};
+INSTANTIATE_TEST_SUITE_P(
+ EventPage,
+ ExtensionContentSettingsApiTestWithPermissionDelegationDisabled,
+ ::testing::Values(ContextType::kEventPage));
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorker,
+ ExtensionContentSettingsApiTestWithPermissionDelegationDisabled,
+ ::testing::Values(ContextType::kServiceWorker));
+
class ExtensionContentSettingsApiTestWithPermissionDelegationEnabled
- : public ExtensionContentSettingsApiTest {
+ : public ExtensionContentSettingsApiLazyTest {
public:
ExtensionContentSettingsApiTestWithPermissionDelegationEnabled() {
feature_list_.InitAndEnableFeature(
@@ -414,20 +468,76 @@ class ExtensionContentSettingsApiTestWithPermissionDelegationEnabled
base::test::ScopedFeatureList feature_list_;
};
-IN_PROC_BROWSER_TEST_F(
+INSTANTIATE_TEST_SUITE_P(
+ EventPage,
+ ExtensionContentSettingsApiTestWithPermissionDelegationEnabled,
+ ::testing::Values(ContextType::kEventPage));
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorker,
+ ExtensionContentSettingsApiTestWithPermissionDelegationEnabled,
+ ::testing::Values(ContextType::kServiceWorker));
+
+IN_PROC_BROWSER_TEST_P(
ExtensionContentSettingsApiTestWithPermissionDelegationDisabled,
EmbeddedSettings) {
const char kExtensionPath[] = "content_settings/embeddedsettings";
- EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_;
+ EXPECT_TRUE(RunLazyTestWithArg(kExtensionPath, nullptr)) << message_;
}
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
ExtensionContentSettingsApiTestWithPermissionDelegationEnabled,
EmbeddedSettings) {
const char kExtensionPath[] = "content_settings/embeddedsettings";
- EXPECT_TRUE(
- RunExtensionSubtest(kExtensionPath, "test.html?permission_delegation"))
- << message_;
+ EXPECT_TRUE(RunLazyTestWithArg(kExtensionPath, "permission")) << message_;
+}
+
+class ExtensionContentSettingsApiTestWithWildcardMatchingDisabled
+ : public ExtensionContentSettingsApiLazyTest {
+ public:
+ ExtensionContentSettingsApiTestWithWildcardMatchingDisabled() {
+ scoped_feature_list_.InitAndEnableFeature(
+ content_settings::kDisallowWildcardsInPluginContentSettings);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ EventPage,
+ ExtensionContentSettingsApiTestWithWildcardMatchingDisabled,
+ ::testing::Values(ContextType::kEventPage));
+
+INSTANTIATE_TEST_SUITE_P(
+ ServiceWorker,
+ ExtensionContentSettingsApiTestWithWildcardMatchingDisabled,
+ ::testing::Values(ContextType::kServiceWorker));
+
+IN_PROC_BROWSER_TEST_P(
+ ExtensionContentSettingsApiTestWithWildcardMatchingDisabled,
+ PluginTest) {
+ constexpr char kExtensionPath[] = "content_settings/pluginswildcardmatching";
+ EXPECT_TRUE(RunLazyTest(kExtensionPath)) << message_;
+
+ constexpr char kGoogleMailUrl[] = "http://mail.google.com:443";
+ constexpr char kGoogleDriveUrl[] = "http://drive.google.com:443";
+
+ permissions::PermissionManager* permission_manager =
+ PermissionManagerFactory::GetForProfile(browser()->profile());
+ EXPECT_EQ(
+ permission_manager
+ ->GetPermissionStatus(ContentSettingsType::PLUGINS,
+ GURL(kGoogleMailUrl), GURL(kGoogleMailUrl))
+ .content_setting,
+ ContentSetting::CONTENT_SETTING_BLOCK);
+
+ EXPECT_EQ(
+ permission_manager
+ ->GetPermissionStatus(ContentSettingsType::PLUGINS,
+ GURL(kGoogleDriveUrl), GURL(kGoogleDriveUrl))
+ .content_setting,
+ ContentSetting::CONTENT_SETTING_ALLOW);
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.cc
index a8042a43b0e..40b9e99f0de 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.cc
@@ -32,6 +32,14 @@ std::unique_ptr<RuleIterator> CustomExtensionProvider::GetRuleIterator(
incognito);
}
+std::unique_ptr<RuleIterator> CustomExtensionProvider::GetDiscardedRuleIterator(
+ ContentSettingsType content_type,
+ const ResourceIdentifier& resource_identifier,
+ bool incognito) const {
+ return extensions_settings_->GetDiscardedRuleIterator(
+ content_type, resource_identifier, incognito);
+}
+
bool CustomExtensionProvider::SetWebsiteSetting(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.h b/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.h
index 3532f1f10c9..45e74998fd9 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.h
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_custom_extension_provider.h
@@ -30,6 +30,11 @@ class CustomExtensionProvider : public ObservableProvider,
const ResourceIdentifier& resource_identifier,
bool incognito) const override;
+ std::unique_ptr<RuleIterator> GetDiscardedRuleIterator(
+ ContentSettingsType content_type,
+ const ResourceIdentifier& resource_identifier,
+ bool incognito) const override;
+
bool SetWebsiteSetting(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
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 ca3eab1fb10..bc148ab971c 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
@@ -25,6 +25,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/content_settings/core/common/features.h"
#include "components/permissions/features.h"
#include "content/public/browser/browser_thread.h"
@@ -37,6 +38,51 @@ using content_settings::ResourceIdentifier;
namespace extensions {
+namespace {
+
+enum class FilterType {
+ WANT_DISCARDED_PATTERNS,
+ WANT_VALID_PATTERNS,
+};
+
+class FilterRuleIterator : public RuleIterator {
+ public:
+ FilterRuleIterator(std::unique_ptr<RuleIterator> iterator,
+ const FilterType filter_type)
+ : iterator_(std::move(iterator)), filter_type_(filter_type) {}
+
+ ~FilterRuleIterator() override = default;
+
+ bool HasNext() const override {
+ if (!iterator_)
+ return false;
+ if (current_rule_)
+ return true;
+ while (iterator_->HasNext()) {
+ current_rule_ = iterator_->Next();
+ if (!((filter_type_ == FilterType::WANT_DISCARDED_PATTERNS) ^
+ current_rule_->primary_pattern.HasHostWildcards())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Rule Next() override {
+ DCHECK(current_rule_.has_value());
+ Rule rule = std::move(*current_rule_);
+ current_rule_.reset();
+ return rule;
+ }
+
+ private:
+ std::unique_ptr<RuleIterator> iterator_;
+ const FilterType filter_type_;
+ mutable base::Optional<Rule> current_rule_;
+};
+
+} // namespace
+
struct ContentSettingsStore::ExtensionEntry {
// Extension id.
std::string id;
@@ -63,6 +109,36 @@ std::unique_ptr<RuleIterator> ContentSettingsStore::GetRuleIterator(
ContentSettingsType type,
const content_settings::ResourceIdentifier& identifier,
bool incognito) const {
+ if (base::FeatureList::IsEnabled(
+ content_settings::kDisallowWildcardsInPluginContentSettings) &&
+ type == ContentSettingsType::PLUGINS) {
+ return std::make_unique<FilterRuleIterator>(
+ GetAllRulesIterator(type, identifier, incognito),
+ FilterType::WANT_VALID_PATTERNS);
+ } else {
+ return GetAllRulesIterator(type, identifier, incognito);
+ }
+}
+
+std::unique_ptr<RuleIterator> ContentSettingsStore::GetDiscardedRuleIterator(
+ ContentSettingsType type,
+ const content_settings::ResourceIdentifier& identifier,
+ bool incognito) const {
+ if (base::FeatureList::IsEnabled(
+ content_settings::kDisallowWildcardsInPluginContentSettings) &&
+ type == ContentSettingsType::PLUGINS) {
+ return std::make_unique<FilterRuleIterator>(
+ GetAllRulesIterator(type, identifier, incognito),
+ FilterType::WANT_DISCARDED_PATTERNS);
+ } else {
+ return std::make_unique<content_settings::EmptyRuleIterator>();
+ }
+}
+
+std::unique_ptr<RuleIterator> ContentSettingsStore::GetAllRulesIterator(
+ ContentSettingsType type,
+ const content_settings::ResourceIdentifier& identifier,
+ bool incognito) const {
std::vector<std::unique_ptr<RuleIterator>> iterators;
// The individual |RuleIterators| shouldn't lock; pass |lock_| to the
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h
index 286201f338a..291975c5aa2 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h
@@ -59,6 +59,16 @@ class ContentSettingsStore
const content_settings::ResourceIdentifier& identifier,
bool incognito) const;
+ std::unique_ptr<content_settings::RuleIterator> GetDiscardedRuleIterator(
+ ContentSettingsType type,
+ const content_settings::ResourceIdentifier& identifier,
+ bool incognito) const;
+
+ std::unique_ptr<content_settings::RuleIterator> GetAllRulesIterator(
+ ContentSettingsType type,
+ const content_settings::ResourceIdentifier& identifier,
+ bool incognito) const;
+
// Sets the content |setting| for |pattern| of extension |ext_id|. The
// |incognito| flag allow to set whether the provided setting is for
// incognito mode only.
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 ec02e12ba9a..51f9f783604 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
@@ -15,6 +15,7 @@
#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/common/features.h"
#include "components/content_settings/core/test/content_settings_test_utils.h"
#include "components/permissions/features.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -374,4 +375,45 @@ TEST_F(ContentSettingsStoreTest, RemoveEmbedded) {
store()->RemoveObserver(&observer);
}
+TEST_F(ContentSettingsStoreTest, DisallowWildcardsInFlash) {
+ // Enabling the feature which disallows wildcard matching for Plugin content
+ // settings.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ content_settings::kDisallowWildcardsInPluginContentSettings);
+
+ // Register extension.
+ std::string ext_id("my_extension");
+ RegisterExtension(ext_id);
+ ContentSettingsPattern primary_pattern =
+ ContentSettingsPattern::FromString("https://[*.]google.com");
+ ContentSettingsPattern secondary_pattern = ContentSettingsPattern::Wildcard();
+ store()->SetExtensionContentSetting(
+ ext_id, primary_pattern, secondary_pattern, ContentSettingsType::PLUGINS,
+ std::string(), CONTENT_SETTING_ALLOW, kExtensionPrefsScopeRegular);
+ store()->SetExtensionContentSetting(
+ ext_id, primary_pattern, secondary_pattern, ContentSettingsType::COOKIES,
+ std::string(), CONTENT_SETTING_ALLOW, kExtensionPrefsScopeRegular);
+
+ std::vector<content_settings::Rule> rules;
+ rules = GetSettingsForOneTypeFromStore(store(), ContentSettingsType::PLUGINS,
+ std::string(), false);
+ // Number of rules will be zero because we tried to add a pattern with
+ // wildcards.
+ ASSERT_EQ(rules.size(), 0u);
+
+ rules = GetSettingsForOneTypeFromStore(store(), ContentSettingsType::COOKIES,
+ std::string(), false);
+ // Here we will have one rule because wildcard patterns are allowed for
+ // ContentSettingsType::COOKIES.
+ ASSERT_EQ(rules.size(), 1u);
+
+ std::unique_ptr<content_settings::RuleIterator> discarded_rules_iterator =
+ store()->GetDiscardedRuleIterator(ContentSettingsType::PLUGINS,
+ std::string(), false);
+ ASSERT_TRUE(discarded_rules_iterator->HasNext());
+ ASSERT_EQ(discarded_rules_iterator->Next().primary_pattern, primary_pattern);
+ ASSERT_FALSE(discarded_rules_iterator->HasNext());
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.cc b/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.cc
index a4f8124fa44..8710a97caf1 100644
--- a/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.cc
@@ -99,6 +99,10 @@ MenuItem::ContextList GetContexts(const std::vector<
// Not available for <webview>.
contexts.Add(extensions::MenuItem::PAGE_ACTION);
break;
+ case extensions::api::context_menus::CONTEXT_TYPE_ACTION:
+ // Not available for <webview>.
+ contexts.Add(extensions::MenuItem::ACTION);
+ break;
case extensions::api::context_menus::CONTEXT_TYPE_NONE:
NOTREACHED();
}
diff --git a/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h b/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h
index 28335e39113..b45a66a8a0a 100644
--- a/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h
+++ b/chromium/chrome/browser/extensions/api/context_menus/context_menus_api_helpers.h
@@ -101,7 +101,8 @@ bool CreateMenuItem(const PropertyWithEnumT& create_properties,
}
if (contexts.Contains(MenuItem::BROWSER_ACTION) ||
- contexts.Contains(MenuItem::PAGE_ACTION)) {
+ contexts.Contains(MenuItem::PAGE_ACTION) ||
+ contexts.Contains(MenuItem::ACTION)) {
// Action items are not allowed for <webview>.
if (!extension->is_extension() || is_webview) {
*error = kActionNotAllowedError;
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
index 8fa3cd840d0..5dbb6f601d9 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -256,16 +256,17 @@ ExtensionFunction::ResponseAction CookiesGetFunction::Run() {
}
void CookiesGetFunction::GetCookieListCallback(
- const net::CookieStatusList& cookie_status_list,
- const net::CookieStatusList& excluded_cookies) {
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (const net::CookieWithStatus& cookie_with_status : cookie_status_list) {
+ for (const net::CookieWithAccessResult& cookie_with_access_result :
+ cookie_list) {
// Return the first matching cookie. Relies on the fact that the
// CookieManager interface returns them in canonical order (longest path,
// then earliest creation time).
- if (cookie_with_status.cookie.Name() == parsed_args_->details.name) {
+ if (cookie_with_access_result.cookie.Name() == parsed_args_->details.name) {
api::cookies::Cookie api_cookie = cookies_helpers::CreateCookie(
- cookie_with_status.cookie, *parsed_args_->details.store_id);
+ cookie_with_access_result.cookie, *parsed_args_->details.store_id);
Respond(ArgumentList(api::cookies::Get::Results::Create(api_cookie)));
return;
}
@@ -336,14 +337,14 @@ void CookiesGetAllFunction::GetAllCookiesCallback(
}
void CookiesGetAllFunction::GetCookieListCallback(
- const net::CookieStatusList& cookie_status_list,
- const net::CookieStatusList& excluded_cookies) {
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ResponseValue response;
if (extension()) {
std::vector<api::cookies::Cookie> match_vector;
- cookies_helpers::AppendMatchingCookiesFromCookieStatusListToVector(
- cookie_status_list, &parsed_args_->details, extension(), &match_vector);
+ cookies_helpers::AppendMatchingCookiesFromCookieAccessResultListToVector(
+ cookie_list, &parsed_args_->details, extension(), &match_vector);
response =
ArgumentList(api::cookies::GetAll::Results::Create(match_vector));
@@ -437,7 +438,8 @@ ExtensionFunction::ResponseAction CookiesSetFunction::Run() {
// is generated.
success_ = false;
state_ = SET_COMPLETED;
- GetCookieListCallback(net::CookieStatusList(), net::CookieStatusList());
+ GetCookieListCallback(net::CookieAccessResultList(),
+ net::CookieAccessResultList());
return AlreadyResponded();
}
@@ -461,7 +463,7 @@ ExtensionFunction::ResponseAction CookiesSetFunction::Run() {
}
void CookiesSetFunction::SetCanonicalCookieCallback(
- net::CanonicalCookie::CookieInclusionStatus set_cookie_result) {
+ net::CookieInclusionStatus set_cookie_result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(NO_RESPONSE, state_);
state_ = SET_COMPLETED;
@@ -469,8 +471,8 @@ void CookiesSetFunction::SetCanonicalCookieCallback(
}
void CookiesSetFunction::GetCookieListCallback(
- const net::CookieStatusList& cookie_list,
- const net::CookieStatusList& excluded_cookies) {
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(SET_COMPLETED, state_);
state_ = GET_COMPLETED;
@@ -485,16 +487,17 @@ void CookiesSetFunction::GetCookieListCallback(
}
ResponseValue value;
- for (const net::CookieWithStatus& cookie_with_status : cookie_list) {
+ for (const net::CookieWithAccessResult& cookie_with_access_result :
+ cookie_list) {
// Return the first matching cookie. Relies on the fact that the
// CookieMonster returns them in canonical order (longest path, then
// earliest creation time).
std::string name =
parsed_args_->details.name.get() ? *parsed_args_->details.name
: std::string();
- if (cookie_with_status.cookie.Name() == name) {
+ if (cookie_with_access_result.cookie.Name() == name) {
api::cookies::Cookie api_cookie = cookies_helpers::CreateCookie(
- cookie_with_status.cookie, *parsed_args_->details.store_id);
+ cookie_with_access_result.cookie, *parsed_args_->details.store_id);
value = ArgumentList(api::cookies::Set::Results::Create(api_cookie));
break;
}
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_api.h b/chromium/chrome/browser/extensions/api/cookies/cookies_api.h
index d6b171b5f04..a506809822a 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_api.h
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_api.h
@@ -23,6 +23,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_change_dispatcher.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "url/gurl.h"
@@ -105,8 +106,9 @@ class CookiesGetFunction : public ExtensionFunction {
ResponseAction Run() override;
private:
- void GetCookieListCallback(const net::CookieStatusList& cookie_status_list,
- const net::CookieStatusList& excluded_cookies);
+ void GetCookieListCallback(
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies);
GURL url_;
mojo::Remote<network::mojom::CookieManager> store_browser_cookie_manager_;
@@ -130,8 +132,9 @@ class CookiesGetAllFunction : public ExtensionFunction {
// For the two different callback signatures for getting cookies for a URL vs
// getting all cookies. They do the same thing.
void GetAllCookiesCallback(const net::CookieList& cookie_list);
- void GetCookieListCallback(const net::CookieStatusList& cookie_status_list,
- const net::CookieStatusList& excluded_cookies);
+ void GetCookieListCallback(
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies);
GURL url_;
mojo::Remote<network::mojom::CookieManager> store_browser_cookie_manager_;
@@ -150,10 +153,10 @@ class CookiesSetFunction : public ExtensionFunction {
ResponseAction Run() override;
private:
- void SetCanonicalCookieCallback(
- net::CanonicalCookie::CookieInclusionStatus set_cookie_result);
- void GetCookieListCallback(const net::CookieStatusList& cookie_list,
- const net::CookieStatusList& excluded_cookies);
+ void SetCanonicalCookieCallback(net::CookieInclusionStatus set_cookie_result);
+ void GetCookieListCallback(
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies);
enum { NO_RESPONSE, SET_COMPLETED, GET_COMPLETED } state_;
GURL url_;
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_apitest.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_apitest.cc
index bf114b6f2be..e5f22089cac 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_apitest.cc
@@ -6,10 +6,16 @@
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test.h"
+#include "extensions/common/scoped_worker_based_extensions_channel.h"
#include "net/cookies/cookie_util.h"
namespace extensions {
+using ContextType = ExtensionApiTest::ContextType;
+
+// TODO(crbug.com/1093066): This test uses the DOM to set and
+// check cookies for one test. Figure out how to isolate that
+// test and adapt the rest of it for a SW-based extension.
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Cookies) {
ASSERT_TRUE(RunExtensionTestWithArg(
"cookies/api",
@@ -19,21 +25,60 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Cookies) {
<< message_;
}
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CookiesEvents) {
- ASSERT_TRUE(RunExtensionTest("cookies/events")) << message_;
+class CookiesApiTest : public ExtensionApiTest,
+ public testing::WithParamInterface<ContextType> {
+ public:
+ void SetUp() override {
+ ExtensionApiTest::SetUp();
+ // Service Workers are currently only available on certain channels, so set
+ // the channel for those tests.
+ if (GetParam() == ContextType::kServiceWorker)
+ current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>();
+ }
+
+ protected:
+ bool RunTest(const std::string& extension_name) {
+ return RunTestWithFlags(extension_name, kFlagNone);
+ }
+
+ bool RunTestIncognito(const std::string& extension_name) {
+ return RunTestWithFlags(extension_name, kFlagEnableIncognito);
+ }
+
+ bool RunTestWithFlags(const std::string& extension_name,
+ int browser_test_flags) {
+ if (GetParam() == ContextType::kServiceWorker)
+ browser_test_flags |= kFlagRunAsServiceWorkerBasedExtension;
+
+ return RunExtensionTestWithFlags(extension_name, browser_test_flags,
+ kFlagNone);
+ }
+
+ std::unique_ptr<ScopedWorkerBasedExtensionsChannel> current_channel_;
+};
+
+INSTANTIATE_TEST_SUITE_P(EventPage,
+ CookiesApiTest,
+ ::testing::Values(ContextType::kEventPage));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ CookiesApiTest,
+ ::testing::Values(ContextType::kServiceWorker));
+
+IN_PROC_BROWSER_TEST_P(CookiesApiTest, CookiesEvents) {
+ ASSERT_TRUE(RunTest("cookies/events")) << message_;
}
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CookiesEventsSpanning) {
+IN_PROC_BROWSER_TEST_P(CookiesApiTest, CookiesEventsSpanning) {
// We need to initialize an incognito mode window in order have an initialized
// incognito cookie store. Otherwise, the chrome.cookies.set operation is just
// ignored and we won't be notified about a newly set cookie for which we want
// to test whether the storeId is set correctly.
OpenURLOffTheRecord(browser()->profile(), GURL("chrome://newtab/"));
- ASSERT_TRUE(RunExtensionTestIncognito("cookies/events_spanning")) << message_;
+ ASSERT_TRUE(RunTestIncognito("cookies/events_spanning")) << message_;
}
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CookiesNoPermission) {
- ASSERT_TRUE(RunExtensionTest("cookies/no_permission")) << message_;
+IN_PROC_BROWSER_TEST_P(CookiesApiTest, CookiesNoPermission) {
+ ASSERT_TRUE(RunTest("cookies/no_permission")) << message_;
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc
index 43bb1619bfb..9aee1f6143b 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -182,14 +182,14 @@ void AppendMatchingCookiesFromCookieListToVector(
}
}
-void AppendMatchingCookiesFromCookieStatusListToVector(
- const net::CookieStatusList& all_cookies_with_statuses,
+void AppendMatchingCookiesFromCookieAccessResultListToVector(
+ const net::CookieAccessResultList& all_cookies_with_access_result,
const GetAll::Params::Details* details,
const Extension* extension,
std::vector<Cookie>* match_vector) {
- for (const net::CookieWithStatus& cookie_with_status :
- all_cookies_with_statuses) {
- const net::CanonicalCookie& cookie = cookie_with_status.cookie;
+ for (const net::CookieWithAccessResult& cookie_with_access_result :
+ all_cookies_with_access_result) {
+ const net::CanonicalCookie& cookie = cookie_with_access_result.cookie;
AppendCookieToVectorIfMatchAndHasHostPermission(cookie, details, extension,
match_vector);
}
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h
index 298b16e49a7..9d5acf0fbc7 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h
@@ -85,9 +85,10 @@ void AppendMatchingCookiesFromCookieListToVector(
const Extension* extension,
std::vector<api::cookies::Cookie>* match_vector);
-// Same as above except takes a CookieStatusList (and ignores the statuses).
-void AppendMatchingCookiesFromCookieStatusListToVector(
- const net::CookieStatusList& all_cookies_with_statuses,
+// Same as above except takes a CookieAccessResultList (and ignores the access
+// results).
+void AppendMatchingCookiesFromCookieAccessResultListToVector(
+ const net::CookieAccessResultList& all_cookies_with_access_result,
const api::cookies::GetAll::Params::Details* details,
const Extension* extension,
std::vector<api::cookies::Cookie>* match_vector);
diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
index 253ce751bd9..3aaf2863859 100644
--- a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -389,9 +389,7 @@ bool ExtensionDevToolsClientHost::MayWriteLocalFiles() {
// DebuggerFunction -----------------------------------------------------------
-DebuggerFunction::DebuggerFunction()
- : client_host_(NULL) {
-}
+DebuggerFunction::DebuggerFunction() : client_host_(nullptr) {}
DebuggerFunction::~DebuggerFunction() = default;
diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc
index 704f95eed0c..71ce5a3399d 100644
--- a/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc
@@ -381,4 +381,24 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDebuggerExtensionApiTest, Debugger) {
<< message_;
}
+IN_PROC_BROWSER_TEST_F(SitePerProcessDebuggerExtensionApiTest,
+ AutoAttachPermissions) {
+ GURL url(embedded_test_server()->GetURL(
+ "a.com",
+ "/extensions/api_test/debugger_auto_attach_permissions/page.html"));
+ ASSERT_TRUE(RunExtensionTestWithArg("debugger_auto_attach_permissions",
+ url.spec().c_str()))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessDebuggerExtensionApiTest,
+ NavigateSubframe) {
+ GURL url(embedded_test_server()->GetURL(
+ "a.com",
+ "/extensions/api_test/debugger_navigate_subframe/inspected_page.html"));
+ ASSERT_TRUE(
+ RunExtensionTestWithArg("debugger_navigate_subframe", url.spec().c_str()))
+ << message_;
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc b/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
index 13265b25237..06daba2fe34 100644
--- a/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
@@ -199,18 +199,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, PersistRules) {
EXPECT_EQ(kTestTitle, GetTitle());
}
-// Disabled for flakiness: http://crbug.com/851854
-#if defined(OS_MACOSX) && defined(ADDRESS_SANITIZER)
-#define MAYBE_ExtensionLifetimeRulesHandling \
- DISABLED_ExtensionLifetimeRulesHandling
-#else
-#define MAYBE_ExtensionLifetimeRulesHandling ExtensionLifetimeRulesHandling
-#endif
-
// Test that the rules are correctly persisted and (de)activated during
// changing the "installed" and "enabled" status of an extension.
-IN_PROC_BROWSER_TEST_F(DeclarativeApiTest,
- MAYBE_ExtensionLifetimeRulesHandling) {
+IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, ExtensionLifetimeRulesHandling) {
TestExtensionDir ext_dir;
// 1. Install the extension. Rules should become active.
@@ -276,17 +267,10 @@ IN_PROC_BROWSER_TEST_F(DeclarativeApiTest,
EXPECT_EQ(0u, NumberOfRegisteredRules(extension_id));
}
-// Disabled for flakiness: http://crbug.com/851854
-#if defined(OS_MACOSX) && defined(ADDRESS_SANITIZER)
-#define MAYBE_NoTracesAfterUninstalling DISABLED_NoTracesAfterUninstalling
-#else
-#define MAYBE_NoTracesAfterUninstalling NoTracesAfterUninstalling
-#endif
-
// When an extension is uninstalled, the state store deletes all preferences
// stored for that extension. We need to make sure we don't store anything after
// that deletion occurs.
-IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, MAYBE_NoTracesAfterUninstalling) {
+IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, NoTracesAfterUninstalling) {
TestExtensionDir ext_dir;
// 1. Install the extension. Verify that rules become active and some prefs
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 8b25d8e15ff..97ef56d188a 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
@@ -10,11 +10,11 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
#include "chrome/test/base/testing_profile.h"
#include "components/version_info/channel.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/api/declarative/test_rules_registry.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
@@ -84,23 +84,23 @@ TEST_F(RulesRegistryServiceTest, TestConstructionAndMultiThreading) {
EXPECT_TRUE(registry_service.GetRulesRegistry(key, "io").get());
EXPECT_FALSE(registry_service.GetRulesRegistry(key, "foo").get());
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&InsertRule, registry_service.GetRulesRegistry(key, "ui"),
"ui_task"));
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&InsertRule, registry_service.GetRulesRegistry(key, "io"),
"io_task"));
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&VerifyNumberOfRules,
registry_service.GetRulesRegistry(key, "ui"), 1));
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&VerifyNumberOfRules,
registry_service.GetRulesRegistry(key, "io"), 1));
@@ -120,13 +120,13 @@ TEST_F(RulesRegistryServiceTest, TestConstructionAndMultiThreading) {
.Build();
registry_service.SimulateExtensionUninstalled(extension.get());
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&VerifyNumberOfRules,
registry_service.GetRulesRegistry(key, "ui"), 0));
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&VerifyNumberOfRules,
registry_service.GetRulesRegistry(key, "io"), 0));
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 9951f0a2666..b06e0ae94c4 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc
@@ -235,7 +235,7 @@ std::unique_ptr<ContentAction> RequestContentScript::Create(
// static
std::unique_ptr<ContentAction> RequestContentScript::CreateForTest(
- DeclarativeUserScriptMaster* master,
+ DeclarativeUserScriptSet* script_set,
const Extension* extension,
const base::Value& json_action,
std::string* error) {
@@ -256,10 +256,10 @@ std::unique_ptr<ContentAction> RequestContentScript::CreateForTest(
if (!InitScriptData(action_dict, error, &script_data))
return std::unique_ptr<ContentAction>();
- // Inject provided DeclarativeUserScriptMaster, rather than looking it up
+ // Inject provided DeclarativeUserScriptSet, rather than looking it up
// using a BrowserContext.
return base::WrapUnique(
- new RequestContentScript(master, extension, script_data));
+ new RequestContentScript(script_set, extension, script_data));
}
// static
@@ -309,25 +309,24 @@ RequestContentScript::RequestContentScript(
HostID host_id(HostID::EXTENSIONS, extension->id());
InitScript(host_id, extension, script_data);
- master_ = DeclarativeUserScriptManager::Get(browser_context)
- ->GetDeclarativeUserScriptMasterByID(host_id);
+ script_set_ = DeclarativeUserScriptManager::Get(browser_context)
+ ->GetDeclarativeUserScriptSetByID(host_id);
AddScript();
}
-RequestContentScript::RequestContentScript(
- DeclarativeUserScriptMaster* master,
- const Extension* extension,
- const ScriptData& script_data) {
+RequestContentScript::RequestContentScript(DeclarativeUserScriptSet* script_set,
+ const Extension* extension,
+ const ScriptData& script_data) {
HostID host_id(HostID::EXTENSIONS, extension->id());
InitScript(host_id, extension, script_data);
- master_ = master;
+ script_set_ = script_set;
AddScript();
}
RequestContentScript::~RequestContentScript() {
- DCHECK(master_);
- master_->RemoveScript(UserScriptIDPair(script_.id(), script_.host_id()));
+ DCHECK(script_set_);
+ script_set_->RemoveScript(UserScriptIDPair(script_.id(), script_.host_id()));
}
void RequestContentScript::InitScript(const HostID& host_id,
@@ -355,8 +354,8 @@ void RequestContentScript::InitScript(const HostID& host_id,
}
void RequestContentScript::AddScript() {
- DCHECK(master_);
- master_->AddScript(UserScript::CopyMetadataFrom(script_));
+ DCHECK(script_set_);
+ script_set_->AddScript(UserScript::CopyMetadataFrom(script_));
}
void RequestContentScript::Apply(const ApplyInfo& apply_info) const {
@@ -394,7 +393,8 @@ std::unique_ptr<ContentAction> SetIcon::Create(
gfx::ImageSkia icon;
const base::DictionaryValue* canvas_set = NULL;
if (dict->GetDictionary("imageData", &canvas_set) &&
- !ExtensionAction::ParseIconFromCanvasDictionary(*canvas_set, &icon)) {
+ ExtensionAction::ParseIconFromCanvasDictionary(*canvas_set, &icon) !=
+ ExtensionAction::IconParseResult::kSuccess) {
*error = kInvalidIconDictionary;
return nullptr;
}
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/content_action.h b/chromium/chrome/browser/extensions/api/declarative_content/content_action.h
index c16e87cca97..ea28a5a863a 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/content_action.h
+++ b/chromium/chrome/browser/extensions/api/declarative_content/content_action.h
@@ -9,7 +9,7 @@
#include <string>
#include "base/macros.h"
-#include "extensions/browser/declarative_user_script_master.h"
+#include "extensions/browser/declarative_user_script_set.h"
#include "extensions/common/user_script.h"
namespace base {
@@ -74,7 +74,7 @@ class RequestContentScript : public ContentAction {
RequestContentScript(content::BrowserContext* browser_context,
const Extension* extension,
const ScriptData& script_data);
- RequestContentScript(DeclarativeUserScriptMaster* master,
+ RequestContentScript(DeclarativeUserScriptSet* script_set,
const Extension* extension,
const ScriptData& script_data);
@@ -87,7 +87,7 @@ class RequestContentScript : public ContentAction {
std::string* error);
static std::unique_ptr<ContentAction> CreateForTest(
- DeclarativeUserScriptMaster* master,
+ DeclarativeUserScriptSet* master,
const Extension* extension,
const base::Value& json_action,
std::string* error);
@@ -112,7 +112,7 @@ class RequestContentScript : public ContentAction {
const Extension* extension) const;
UserScript script_;
- DeclarativeUserScriptMaster* master_;
+ DeclarativeUserScriptSet* script_set_;
DISALLOW_COPY_AND_ASSIGN(RequestContentScript);
};
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 73650f930ac..dc7055aea74 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
@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/extensions/chrome_extension_test_notification_observer.h"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_action_test_util.h"
@@ -257,8 +258,7 @@ void DeclarativeContentApiTest::CheckBookmarkEvents(bool match_is_bookmarked) {
EXPECT_EQ(!match_is_bookmarked, action->GetIsVisible(tab_id));
}
-// Disabled due to flake. https://crbug.com/606574.
-IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, DISABLED_Overview) {
+IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, Overview) {
ext_dir_.WriteManifest(kDeclarativeContentManifest);
ext_dir_.WriteFile(
FILE_PATH_LITERAL("background.js"),
@@ -295,14 +295,20 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, DISABLED_Overview) {
browser()->tab_strip_model()->GetWebContentsAt(0);
const int tab_id = ExtensionTabUtil::GetTabId(tab);
- NavigateInRenderer(tab, GURL("http://test1/"));
+ // Observer to track page action visibility. This helps avoid
+ // flakes by waiting to check visibility until there is an
+ // actual update to the page action.
+ ChromeExtensionTestNotificationObserver test_observer(browser());
+ NavigateInRenderer(tab, GURL("http://test1/"));
// The declarative API should show the page action instantly, rather
// than waiting for the extension to run.
+ test_observer.WaitForPageActionVisibilityChangeTo(1);
EXPECT_TRUE(action->GetIsVisible(tab_id));
// Make sure leaving a matching page unshows the page action.
NavigateInRenderer(tab, GURL("http://not_checked/"));
+ test_observer.WaitForPageActionVisibilityChangeTo(0);
EXPECT_FALSE(action->GetIsVisible(tab_id));
// Insert a password field to make sure that's noticed.
@@ -311,10 +317,7 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, DISABLED_Overview) {
tab, "document.body.innerHTML = '<input type=\"password\">';"
"document.body.offsetTop;"));
- // Give the style match a chance to run and send back the matching-selector
- // update.
- ASSERT_TRUE(content::ExecuteScript(tab, std::string()));
-
+ test_observer.WaitForPageActionVisibilityChangeTo(1);
EXPECT_TRUE(action->GetIsVisible(tab_id))
<< "Adding a matching element should show the page action.";
@@ -324,10 +327,7 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, DISABLED_Overview) {
tab, "document.body.innerHTML = 'Hello world';"
"document.body.offsetTop;"));
- // Give the style match a chance to run and send back the matching-selector
- // update.
- ASSERT_TRUE(content::ExecuteScript(tab, std::string()));
-
+ test_observer.WaitForPageActionVisibilityChangeTo(0);
EXPECT_FALSE(action->GetIsVisible(tab_id))
<< "Removing the matching element should hide the page action again.";
}
@@ -643,11 +643,17 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
EXPECT_TRUE(incognito_action->GetIsVisible(incognito_tab_id));
}
+constexpr char kRulesExtensionName[] =
+ "Declarative content persistence apitest";
+
+// TODO(crbug.com/512431): Flaky on Windows release builds.
+#if defined(OS_WIN) && defined(NDEBUG)
+#define MAYBE_PRE_RulesPersistence DISABLED_PRE_RulesPersistence
+#else
+#define MAYBE_PRE_RulesPersistence PRE_RulesPersistence
+#endif
// Sets up rules matching http://test1/ in a normal and incognito browser.
-// Frequently times out on ChromiumOS, Linux ASan, and Windows:
-// https://crbug.com/512431.
-IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
- DISABLED_PRE_RulesPersistence) {
+IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, MAYBE_PRE_RulesPersistence) {
ExtensionTestMessageListener ready("ready", false);
ExtensionTestMessageListener ready_split("ready (split)", false);
// An on-disk extension is required so that it can be reloaded later in the
@@ -656,30 +662,36 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
LoadExtensionIncognito(test_data_dir_.AppendASCII("declarative_content")
.AppendASCII("persistence"));
ASSERT_TRUE(extension);
+ ASSERT_EQ(kRulesExtensionName, extension->name());
ASSERT_TRUE(ready.WaitUntilSatisfied());
CreateIncognitoBrowser();
ASSERT_TRUE(ready_split.WaitUntilSatisfied());
}
+// TODO(crbug.com/512431): Flaky on Windows release builds.
+#if defined(OS_WIN) && defined(NDEBUG)
+#define MAYBE_RulesPersistence DISABLED_RulesPersistence
+#else
+#define MAYBE_RulesPersistence RulesPersistence
+#endif
// Reloads the extension from PRE_RulesPersistence and checks that the rules
// continue to work as expected after being persisted and reloaded.
-IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, DISABLED_RulesPersistence) {
- ExtensionTestMessageListener ready("second run ready", false);
- ExtensionTestMessageListener ready_split("second run ready (split)", false);
- ASSERT_TRUE(ready.WaitUntilSatisfied());
-
- ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
- const Extension* extension =
- GetExtensionByPath(registry->enabled_extensions(),
- test_data_dir_.AppendASCII("declarative_content")
- .AppendASCII("persistence"));
+IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, MAYBE_RulesPersistence) {
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+ ASSERT_EQ(kRulesExtensionName, extension->name());
// Check non-incognito browser.
content::WebContents* const tab =
browser()->tab_strip_model()->GetWebContentsAt(0);
const int tab_id = ExtensionTabUtil::GetTabId(tab);
+ // Observer to track page action visibility. This helps avoid
+ // flakes by waiting to check visibility until there is an
+ // actual update to the page action.
+ ChromeExtensionTestNotificationObserver test_observer(browser());
+
const ExtensionAction* action =
ExtensionActionManager::Get(browser()->profile())
->GetExtensionAction(*extension);
@@ -687,11 +699,15 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, DISABLED_RulesPersistence) {
EXPECT_FALSE(action->GetIsVisible(tab_id));
NavigateInRenderer(tab, GURL("http://test_normal/"));
+ test_observer.WaitForPageActionVisibilityChangeTo(1);
EXPECT_TRUE(action->GetIsVisible(tab_id));
NavigateInRenderer(tab, GURL("http://test_split/"));
+ test_observer.WaitForPageActionVisibilityChangeTo(0);
EXPECT_FALSE(action->GetIsVisible(tab_id));
+ ExtensionTestMessageListener ready_split("second run ready (split)", false);
+
// Check incognito browser.
Browser* incognito_browser = CreateIncognitoBrowser();
ASSERT_TRUE(ready_split.WaitUntilSatisfied());
@@ -699,35 +715,35 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, DISABLED_RulesPersistence) {
incognito_browser->tab_strip_model()->GetWebContentsAt(0);
const int incognito_tab_id = ExtensionTabUtil::GetTabId(incognito_tab);
+ ChromeExtensionTestNotificationObserver incognito_test_observer(
+ incognito_browser);
+
const ExtensionAction* incognito_action =
ExtensionActionManager::Get(incognito_browser->profile())
->GetExtensionAction(*extension);
ASSERT_TRUE(incognito_action);
NavigateInRenderer(incognito_tab, GURL("http://test_split/"));
+ incognito_test_observer.WaitForPageActionVisibilityChangeTo(1);
EXPECT_TRUE(incognito_action->GetIsVisible(incognito_tab_id));
NavigateInRenderer(incognito_tab, GURL("http://test_normal/"));
+ incognito_test_observer.WaitForPageActionVisibilityChangeTo(0);
EXPECT_FALSE(incognito_action->GetIsVisible(incognito_tab_id));
}
// http://crbug.com/304373
-#if defined(OS_WIN)
-// Fails on XP: http://crbug.com/515717
-#define MAYBE_UninstallWhileActivePageAction \
- DISABLED_UninstallWhileActivePageAction
-#else
-#define MAYBE_UninstallWhileActivePageAction UninstallWhileActivePageAction
-#endif
IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
- MAYBE_UninstallWhileActivePageAction) {
+ UninstallWhileActivePageAction) {
ext_dir_.WriteManifest(kDeclarativeContentManifest);
- ext_dir_.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundHelpers);
+ std::string script =
+ kBackgroundHelpers + std::string("\nchrome.test.sendMessage('ready');");
+ ext_dir_.WriteFile(FILE_PATH_LITERAL("background.js"), script);
+ ExtensionTestMessageListener ready_listener("ready", false);
const Extension* extension = LoadExtension(ext_dir_.UnpackedPath());
ASSERT_TRUE(extension);
- // Wait for declarative rules to be set up.
- content::BrowserContext::GetDefaultStoragePartition(profile())
- ->FlushNetworkInterfaceForTesting();
+ ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
+
const std::string extension_id = extension->id();
const ExtensionAction* action =
ExtensionActionManager::Get(browser()->profile())
@@ -754,10 +770,10 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
EXPECT_EQ(1u, extension_action_test_util::GetVisiblePageActionCount(tab));
EXPECT_EQ(1u, extension_action_test_util::GetTotalPageActionCount(tab));
+ ExtensionTestMessageListener reload_ready_listener("ready", false);
ReloadExtension(extension_id); // Invalidates action and extension.
- // Wait for declarative rules to be removed.
- content::BrowserContext::GetDefaultStoragePartition(profile())
- ->FlushNetworkInterfaceForTesting();
+ ASSERT_TRUE(reload_ready_listener.WaitUntilSatisfied());
+
EXPECT_EQ("test_rule",
ExecuteScriptInBackgroundPage(extension_id, kTestRule));
// TODO(jyasskin): Apply new rules to existing tabs, without waiting for a
@@ -779,7 +795,7 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
// This tests against a renderer crash that was present during development.
IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
- DISABLED_AddExtensionMatchingExistingTabWithDeadFrames) {
+ AddExtensionMatchingExistingTabWithDeadFrames) {
ext_dir_.WriteManifest(kDeclarativeContentManifest);
ext_dir_.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundHelpers);
content::WebContents* const tab =
@@ -792,6 +808,10 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
ASSERT_TRUE(content::ExecuteScript(
tab, "document.body.innerHTML = '<span class=\"foo\">';"));
+ // Observer to track page action visibility. This helps avoid flakes by
+ // waiting to check visibility until there is an update to the page action.
+ ChromeExtensionTestNotificationObserver test_observer(browser());
+
const Extension* extension = LoadExtension(ext_dir_.UnpackedPath());
ASSERT_TRUE(extension);
const ExtensionAction* action =
@@ -807,13 +827,8 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
" css: [\"span[class=foo]\"]})],\n"
" actions: [new ShowAction()]\n"
"}], 'rule0');\n"));
- // Give the renderer a chance to apply the rules change and notify the
- // browser. This takes one time through the Blink message loop to receive
- // the rule change and apply the new stylesheet, and a second to dedupe the
- // update.
- ASSERT_TRUE(content::ExecuteScript(tab, std::string()));
- ASSERT_TRUE(content::ExecuteScript(tab, std::string()));
+ test_observer.WaitForPageActionVisibilityChangeTo(1);
EXPECT_FALSE(tab->IsCrashed());
EXPECT_TRUE(action->GetIsVisible(tab_id))
<< "Loading an extension when an open page matches its rules "
@@ -825,6 +840,7 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
"onPageChanged.removeRules(undefined, function() {\n"
" window.domAutomationController.send('removed');\n"
"});\n"));
+ test_observer.WaitForPageActionVisibilityChangeTo(0);
EXPECT_FALSE(action->GetIsVisible(tab_id));
}
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc b/chromium/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
index 65865c4235a..4a99b452a50 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
@@ -113,7 +113,7 @@ class RequestContentScriptAPITest : public ExtensionBrowserTest {
};
RequestContentScriptAPITest::RequestContentScriptAPITest()
- : extension_(NULL) {}
+ : extension_(nullptr) {}
testing::AssertionResult RequestContentScriptAPITest::RunTest(
PermissionOrMatcherType manifest_permission,
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 827ac893936..76c4987a474 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
@@ -10,13 +10,19 @@
#include "base/macros.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/test/browser_test.h"
+#include "extensions/common/scoped_worker_based_extensions_channel.h"
#include "net/dns/mock_host_resolver.h"
namespace {
-class DeclarativeNetRequestAPItest : public extensions::ExtensionApiTest {
+using ContextType = extensions::ExtensionApiTest::ContextType;
+using extensions::ScopedWorkerBasedExtensionsChannel;
+
+class DeclarativeNetRequestAPItest
+ : public extensions::ExtensionApiTest,
+ public testing::WithParamInterface<ContextType> {
public:
- DeclarativeNetRequestAPItest() {}
+ DeclarativeNetRequestAPItest() = default;
protected:
// ExtensionApiTest override.
@@ -40,28 +46,55 @@ class DeclarativeNetRequestAPItest : public extensions::ExtensionApiTest {
// Override the path used for loading the extension.
test_data_dir_ = temp_dir_.GetPath().AppendASCII("declarative_net_request");
+
+ // Service Workers are currently only available on certain channels, so set
+ // the channel for those tests.
+ if (GetParam() == ContextType::kServiceWorker)
+ current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>();
+ }
+
+ bool RunTest(const std::string& extension_path) {
+ if (GetParam() != ContextType::kServiceWorker) {
+ return RunExtensionTest(extension_path);
+ }
+ return RunExtensionTestWithFlags(
+ extension_path, kFlagRunAsServiceWorkerBasedExtension, kFlagNone);
}
private:
base::ScopedTempDir temp_dir_;
- DISALLOW_COPY_AND_ASSIGN(DeclarativeNetRequestAPItest);
+ std::unique_ptr<ScopedWorkerBasedExtensionsChannel> current_channel_;
};
-IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest, DynamicRules) {
- ASSERT_TRUE(RunExtensionTest("dynamic_rules")) << message_;
+using DeclarativeNetRequestLazyAPItest = DeclarativeNetRequestAPItest;
+
+INSTANTIATE_TEST_SUITE_P(PersistentBackground,
+ DeclarativeNetRequestAPItest,
+ ::testing::Values(ContextType::kPersistentBackground));
+INSTANTIATE_TEST_SUITE_P(EventPage,
+ DeclarativeNetRequestLazyAPItest,
+ ::testing::Values(ContextType::kEventPage));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ DeclarativeNetRequestLazyAPItest,
+ ::testing::Values(ContextType::kServiceWorker));
+
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestLazyAPItest, DynamicRules) {
+ ASSERT_TRUE(RunTest("dynamic_rules")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestLazyAPItest, OnRulesMatchedDebug) {
+ ASSERT_TRUE(RunTest("on_rules_matched_debug")) << message_;
}
-// TODO(crbug.com/1029233) Restore this test. This is disabled due to
-// flakiness.
-IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest,
- DISABLED_OnRulesMatchedDebug) {
- ASSERT_TRUE(RunExtensionTest("on_rules_matched_debug")) << message_;
+// This test uses webRequest/webRequestBlocking, so it's not currently
+// supported for service workers.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestAPItest, ModifyHeaders) {
+ ASSERT_TRUE(RunTest("modify_headers")) << message_;
}
-// TODO(crbug.com/1070344): Disabled due to flakiness.
-IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest, DISABLED_GetMatchedRules) {
- ASSERT_TRUE(RunExtensionTest("get_matched_rules")) << message_;
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestLazyAPItest, GetMatchedRules) {
+ ASSERT_TRUE(RunTest("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 a5d9df75278..26f4b57d2bc 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
@@ -546,6 +546,24 @@ class DeclarativeNetRequestBrowserTest
return results;
}
+ TestRule CreateModifyHeadersRule(
+ int id,
+ int priority,
+ const std::string& url_filter,
+ base::Optional<std::vector<TestHeaderInfo>> request_headers,
+ base::Optional<std::vector<TestHeaderInfo>> response_headers) {
+ TestRule rule = CreateGenericRule();
+ rule.id = id;
+ rule.priority = priority;
+ rule.condition->url_filter = url_filter;
+ rule.condition->resource_types = std::vector<std::string>({"sub_frame"});
+ rule.action->type = "modifyHeaders";
+ rule.action->request_headers = std::move(request_headers);
+ rule.action->response_headers = std::move(response_headers);
+
+ return rule;
+ }
+
private:
// Handler to monitor the requests which reach the EmbeddedTestServer. This
// will be run on the EmbeddedTestServer's IO thread.
@@ -650,10 +668,9 @@ class DeclarativeNetRequestBrowserTest
tester.ExpectTotalCount(
"Extensions.DeclarativeNetRequest.CreateVerifiedMatcherTime",
expected_enabled_rulesets_count);
- tester.ExpectUniqueSample(
- "Extensions.DeclarativeNetRequest.LoadRulesetResult",
- RulesetMatcher::kLoadSuccess /*sample*/,
- expected_enabled_rulesets_count);
+ tester.ExpectUniqueSample(kLoadRulesetResultHistogram,
+ LoadRulesetResult::kSuccess /*sample*/,
+ expected_enabled_rulesets_count);
EXPECT_TRUE(AreAllIndexedStaticRulesetsValid(*extension, profile()));
@@ -692,8 +709,9 @@ using DeclarativeNetRequestBrowserTest_Packed =
using DeclarativeNetRequestBrowserTest_Unpacked =
DeclarativeNetRequestBrowserTest;
-#if defined(OS_WIN) && !defined(NDEBUG)
+#if (defined(OS_WIN) || defined(OS_MACOSX)) && !defined(NDEBUG)
// TODO: test times out on win7-debug. http://crbug.com/900447.
+// Also times out on mac-debug: https://crbug.com/900447
#define MAYBE_BlockRequests_UrlFilter DISABLED_BlockRequests_UrlFilter
#else
#define MAYBE_BlockRequests_UrlFilter BlockRequests_UrlFilter
@@ -2091,8 +2109,6 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
EXPECT_FALSE(IsNavigationBlocked(unblocked_url));
};
- const char* kLoadRulesetResultHistogram =
- "Extensions.DeclarativeNetRequest.LoadRulesetResult";
const char* kReindexHistogram =
"Extensions.DeclarativeNetRequest.RulesetReindexSuccessful";
@@ -2104,19 +2120,13 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
base::HistogramTester tester;
test_extension_works_after_reload();
- // Loading the ruleset would have failed initially due to checksum mismatch
- // and later succeeded.
- tester.ExpectBucketCount(kLoadRulesetResultHistogram,
- RulesetMatcher::LoadRulesetResult::
- kLoadErrorChecksumMismatch /* sample */,
- 1 /* count */);
- // Count of 2 because we load both static and dynamic rulesets.
- tester.ExpectBucketCount(
- kLoadRulesetResultHistogram,
- RulesetMatcher::LoadRulesetResult::kLoadSuccess /* sample */,
- 2 /* count */);
- // Verify that reindexing of the static ruleset succeeded.
+ // Loading the static ruleset would fail initially due to checksum mismatch
+ // but will succeed on re-indexing.
tester.ExpectBucketCount(kReindexHistogram, true /*sample*/, 1 /*count*/);
+ // Count of 2 because we load both static and dynamic rulesets.
+ tester.ExpectBucketCount(kLoadRulesetResultHistogram,
+ LoadRulesetResult::kSuccess /* sample */,
+ 2 /* count */);
}
// Test dynamic ruleset re-indexing.
@@ -2127,19 +2137,14 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
base::HistogramTester tester;
test_extension_works_after_reload();
- // Loading the ruleset would have failed initially due to checksum mismatch
- // and later succeeded.
- tester.ExpectBucketCount(kLoadRulesetResultHistogram,
- RulesetMatcher::LoadRulesetResult::
- kLoadErrorChecksumMismatch /* sample */,
- 1 /* count */);
- // Count of 2 because we load both static and dynamic rulesets.
- tester.ExpectBucketCount(
- kLoadRulesetResultHistogram,
- RulesetMatcher::LoadRulesetResult::kLoadSuccess /* sample */,
- 2 /* count */);
- // Verify that reindexing of the dynamic ruleset succeeded.
+ // Loading the dynamic ruleset would have failed initially due to checksum
+ // mismatch and later succeeded on re-indexing.
tester.ExpectBucketCount(kReindexHistogram, true /*sample*/, 1 /*count*/);
+
+ // Count of 2 because we load both static and dynamic rulesets.
+ tester.ExpectBucketCount(kLoadRulesetResultHistogram,
+ LoadRulesetResult::kSuccess /* sample */,
+ 2 /* count */);
}
// Go crazy and corrupt both static and dynamic rulesets.
@@ -2153,17 +2158,11 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
// Loading the ruleset would have failed initially due to checksum mismatch
// and later succeeded.
+ tester.ExpectBucketCount(kReindexHistogram, true /*sample*/, 2 /*count*/);
+ // Count of 2 because we load both static and dynamic rulesets.
tester.ExpectBucketCount(kLoadRulesetResultHistogram,
- RulesetMatcher::LoadRulesetResult::
- kLoadErrorChecksumMismatch /* sample */,
+ LoadRulesetResult::kSuccess /* sample */,
2 /* count */);
- // Count of 2 because we load both static and dynamic rulesets.
- tester.ExpectBucketCount(
- kLoadRulesetResultHistogram,
- RulesetMatcher::LoadRulesetResult::kLoadSuccess /* sample */,
- 2 /* count */);
- // Verify that reindexing of both the rulesets succeeded.
- tester.ExpectBucketCount(kReindexHistogram, true /*sample*/, 2 /*count*/);
}
}
@@ -2228,17 +2227,15 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// Verify that loading the corrupted rulesets failed due to checksum mismatch.
// The non-corrupted rulesets should load fine.
- tester.ExpectTotalCount("Extensions.DeclarativeNetRequest.LoadRulesetResult",
- rulesets.size());
+ tester.ExpectTotalCount(kLoadRulesetResultHistogram, rulesets.size());
EXPECT_EQ(corrupted_ruleset_indices.size(),
static_cast<size_t>(tester.GetBucketCount(
- "Extensions.DeclarativeNetRequest.LoadRulesetResult",
- RulesetMatcher::LoadRulesetResult::
- kLoadErrorChecksumMismatch /*sample*/)));
+ kLoadRulesetResultHistogram,
+ LoadRulesetResult::kErrorChecksumMismatch /*sample*/)));
EXPECT_EQ(non_corrupted_ruleset_indices.size(),
- static_cast<size_t>(tester.GetBucketCount(
- "Extensions.DeclarativeNetRequest.LoadRulesetResult",
- RulesetMatcher::LoadRulesetResult::kLoadSuccess /*sample*/)));
+ static_cast<size_t>(
+ tester.GetBucketCount(kLoadRulesetResultHistogram,
+ LoadRulesetResult::kSuccess /*sample*/)));
// Verify that re-indexing the corrupted rulesets failed.
tester.ExpectUniqueSample(
@@ -2305,22 +2302,14 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
// We add 1 to include the dynamic ruleset.
const int kNumRulesets = kNumStaticRulesets + 1;
- // Verify that loading the static and dynamic rulesets would have failed
- // initially due to version header mismatch and later succeeded.
- EXPECT_EQ(kNumRulesets,
- tester.GetBucketCount(
- "Extensions.DeclarativeNetRequest.LoadRulesetResult",
- RulesetMatcher::LoadRulesetResult::
- kLoadErrorVersionMismatch /*sample*/));
- EXPECT_EQ(kNumRulesets,
- tester.GetBucketCount(
- "Extensions.DeclarativeNetRequest.LoadRulesetResult",
- RulesetMatcher::LoadRulesetResult::kLoadSuccess /*sample*/));
-
- // Verify that reindexing succeeded.
+ // Verify that loading the static and dynamic rulesets would cause reindexing
+ // due to version header mismatch and later succeeded.
tester.ExpectUniqueSample(
"Extensions.DeclarativeNetRequest.RulesetReindexSuccessful",
true /*sample*/, kNumRulesets /*count*/);
+ EXPECT_EQ(kNumRulesets,
+ tester.GetBucketCount(kLoadRulesetResultHistogram,
+ LoadRulesetResult::kSuccess /*sample*/));
// Ensure that the new checksum was correctly persisted in prefs.
const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
@@ -2762,11 +2751,15 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
int priority;
std::string action_type;
base::Optional<std::string> redirect_url;
+ base::Optional<std::vector<TestHeaderInfo>> request_headers;
} rules_data[] = {
- {"abc.com", 1, 1, "block", base::nullopt},
- {"def.com", 2, 1, "redirect", "http://zzz.com"},
- {"abcd.com", 4, 1, "block", base::nullopt},
- {"abcd", 5, 1, "allow", base::nullopt},
+ {"abc.com", 1, 1, "block", base::nullopt, base::nullopt},
+ {"def.com", 2, 1, "redirect", "http://zzz.com", base::nullopt},
+ {"jkl.com", 3, 1, "modifyHeaders", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("referer", "remove", base::nullopt)})},
+ {"abcd.com", 4, 1, "block", base::nullopt, base::nullopt},
+ {"abcd", 5, 1, "allow", base::nullopt, base::nullopt},
};
// Load the extension.
@@ -2781,6 +2774,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->request_headers = rule_data.request_headers;
rules.push_back(rule);
}
@@ -2810,10 +2804,17 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// def.com is redirected by a matching rule and should increment the badge
// text.
{"def.com", "2", false},
+ // jkl.com matches with a modifyHeaders rule which removes the referer
+ // header, but has no headers. Therefore no action is taken and the badge
+ // text stays the same.
+ {"jkl.com", "2", false},
+ // jkl.com matches with a modifyHeaders rule and has a referer header.
+ // Therefore the badge text should be incremented.
+ {"jkl.com", "3", true},
// abcd.com matches both a block rule and an allow rule. Since the allow
// rule overrides the block rule, no action is taken and the badge text
// stays the same,
- {"abcd.com", "2", false},
+ {"abcd.com", "3", false},
};
ui_test_utils::NavigateToURL(browser(), page_url);
@@ -2879,9 +2880,11 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// 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 modifyHeaders rule for jkl.com (ruleId = 3)
// - the allow rule for abcd.com (ruleId = 5)
- EXPECT_EQ(base::StringPrintf("1,%s|2,%s|5,%s", kDefaultRulesetID,
- kDefaultRulesetID, kDefaultRulesetID),
+ EXPECT_EQ(base::StringPrintf("1,%s|2,%s|3,%s|5,%s", kDefaultRulesetID,
+ kDefaultRulesetID, kDefaultRulesetID,
+ kDefaultRulesetID),
get_matched_rules(first_tab_id));
// No rule should be matched on the tab with |second_tab_id|.
@@ -3180,6 +3183,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;
@@ -3187,16 +3194,24 @@ 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<TestHeaderInfo>> response_headers;
} rules_data[] = {
{"abc.com", 1, 1, "block", std::vector<std::string>({"script"}),
- base::nullopt},
+ base::nullopt, base::nullopt},
{"||def.com", 2, 1, "redirect", std::vector<std::string>({"main_frame"}),
- get_url_for_host("abc.com").spec()},
+ 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()},
+ get_url_for_host("def.com").spec(), base::nullopt},
{"ghi.com", 4, 1, "block", std::vector<std::string>({"main_frame"}),
- base::nullopt},
+ 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, "modifyHeaders",
+ std::vector<std::string>({"main_frame"}), base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("set-cookie", "remove", base::nullopt)})},
};
// Load the extension.
@@ -3210,6 +3225,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->response_headers = rule_data.response_headers;
rules.push_back(rule);
}
@@ -3245,6 +3261,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// 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());
@@ -3258,6 +3278,160 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
}
}
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
+ ModifyHeadersBadgeText) {
+ auto get_referer_url = [this](const std::string& host) {
+ return embedded_test_server()->GetURL(host, "/set-header?referer: none");
+ };
+ auto get_set_cookie_url = [this](const std::string& host) {
+ return embedded_test_server()->GetURL(host, "/set-cookie?a=b");
+ };
+ auto get_no_headers_url = [this](const std::string& host) {
+ return embedded_test_server()->GetURL(host,
+ "/pages_with_script/index.html");
+ };
+
+ const std::string kFrameName1 = "frame1";
+ const GURL page_url = embedded_test_server()->GetURL(
+ "nomatch.com", "/page_with_two_frames.html");
+
+ // Create an extension with rules and get the ExtensionAction for it.
+ TestRule example_set_cookie_rule = CreateModifyHeadersRule(
+ kMinValidID, kMinValidPriority, "example.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("set-cookie", "remove", base::nullopt)}));
+
+ TestRule both_headers_rule = CreateModifyHeadersRule(
+ kMinValidID + 1, kMinValidPriority, "google.com",
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("referer", "remove", base::nullopt)}),
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("set-cookie", "remove", base::nullopt)}));
+
+ TestRule abc_set_cookie_rule = CreateModifyHeadersRule(
+ kMinValidID + 2, kMinValidPriority, "abc.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("set-cookie", "remove", base::nullopt)}));
+
+ TestRule abc_referer_rule = CreateModifyHeadersRule(
+ kMinValidID + 3, kMinValidPriority, "abc.com",
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("referer", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule ext1_set_custom_request_header_rule = CreateModifyHeadersRule(
+ kMinValidID + 4, kMinValidPriority, "def.com",
+ std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "set", "ext_1")}),
+ base::nullopt);
+
+ TestRule ext1_add_custom_response_header_rule = CreateModifyHeadersRule(
+ kMinValidID + 5, kMinValidPriority, "ghi.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header2", "append", "ext_1")}));
+
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(
+ {example_set_cookie_rule, both_headers_rule, abc_set_cookie_rule,
+ abc_referer_rule, ext1_set_custom_request_header_rule,
+ ext1_add_custom_response_header_rule},
+ "extension_1", {URLPattern::kAllUrlsPattern}));
+
+ const ExtensionId extension_1_id = last_loaded_extension_id();
+ ExtensionPrefs::Get(profile())->SetDNRUseActionCountAsBadgeText(
+ extension_1_id, true);
+
+ ExtensionAction* extension_1_action =
+ ExtensionActionManager::Get(web_contents()->GetBrowserContext())
+ ->GetExtensionAction(*extension_registry()->GetExtensionById(
+ extension_1_id, extensions::ExtensionRegistry::ENABLED));
+
+ // Create another extension which removes the referer header from example.com
+ // and get the ExtensionAction for it.
+ TestRule example_referer_rule = CreateModifyHeadersRule(
+ kMinValidID, kMinValidPriority, "example.com",
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("referer", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule ext2_set_custom_request_header_rule = CreateModifyHeadersRule(
+ kMinValidID + 4, kMinValidPriority, "def.com",
+ std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "set", "ext_2")}),
+ base::nullopt);
+
+ TestRule ext2_add_custom_response_header_rule = CreateModifyHeadersRule(
+ kMinValidID + 5, kMinValidPriority, "ghi.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header2", "append", "ext_2")}));
+
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(
+ {example_referer_rule, ext2_set_custom_request_header_rule,
+ ext2_add_custom_response_header_rule},
+ "extension_2", {URLPattern::kAllUrlsPattern}));
+
+ const ExtensionId extension_2_id = last_loaded_extension_id();
+ ExtensionPrefs::Get(profile())->SetDNRUseActionCountAsBadgeText(
+ extension_2_id, true);
+
+ ExtensionAction* extension_2_action =
+ ExtensionActionManager::Get(web_contents()->GetBrowserContext())
+ ->GetExtensionAction(*extension_registry()->GetExtensionById(
+ extension_2_id, extensions::ExtensionRegistry::ENABLED));
+
+ struct {
+ GURL url;
+ bool use_referrer;
+ std::string expected_ext_1_badge_text;
+ std::string expected_ext_2_badge_text;
+ } 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", ""},
+ // 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"},
+ // This request has both a Referer and a Set-Cookie header. The badge text
+ // for both extensions should be incremented.
+ {get_set_cookie_url("example.com"), true, "2", "2"},
+ // This request with a Referer and Set-Cookie header matches with one rule
+ // from |extension_1| and so the action count for |extension_1| should
+ // only increment by one,
+ {get_set_cookie_url("google.com"), true, "3", "2"},
+ // This request with a Referer and Set-Cookie header matches with two
+ // separate rules from |extension_1| and so the action count for
+ // |extension_1| should increment by two.
+ {get_set_cookie_url("abc.com"), true, "5", "2"},
+ // This request without headers matches rules to set the header1 request
+ // header from both extensions. Since |extension_2| was installed later
+ // than |extension_1|, only the rule from |extension_2| should take effect
+ // and so the action count for |extension_2| should increment by one.
+ {get_no_headers_url("def.com"), false, "5", "3"},
+ // This request without headers matches rules to append the header2
+ // response header from both extensions. Since each extension has a rule
+ // which has taken effect, the action count for both extensions should
+ // increment by one.
+ {get_no_headers_url("ghi.com"), false, "6", "4"},
+ };
+
+ ui_test_utils::NavigateToURL(browser(), page_url);
+ ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
+
+ int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
+ 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",
+ test_case.url.spec().c_str(),
+ test_case.use_referrer ? "true" : "false"));
+
+ NavigateFrame(kFrameName1, test_case.url, test_case.use_referrer);
+ EXPECT_EQ(test_case.expected_ext_1_badge_text,
+ extension_1_action->GetDisplayBadgeText(first_tab_id));
+
+ EXPECT_EQ(test_case.expected_ext_2_badge_text,
+ extension_2_action->GetDisplayBadgeText(first_tab_id));
+ }
+}
+
// Test that the onRuleMatchedDebug event is only available for unpacked
// extensions.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
@@ -3286,6 +3460,81 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
ASSERT_EQ(expected_event_availability, actual_event_availability);
}
+// Test that the onRuleMatchedDebug event returns the correct number of matched
+// rules for a request which is matched with multiple rules.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Unpacked,
+ OnRuleMatchedDebugMultipleRules) {
+ // This is only tested for unpacked extensions since the onRuleMatchedDebug
+ // event is only available for unpacked extensions.
+ ASSERT_EQ(ExtensionLoadType::UNPACKED, GetParam());
+
+ // 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 onRuleMatchedDebug event.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
+
+ const std::string kFrameName1 = "frame1";
+ const std::string sub_frame_host = "abc.com";
+ const GURL page_url = embedded_test_server()->GetURL(
+ "nomatch.com", "/page_with_two_frames.html");
+
+ TestRule abc_referer_rule = CreateModifyHeadersRule(
+ kMinValidID, kMinValidPriority, sub_frame_host,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("referer", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule abc_set_cookie_rule = CreateModifyHeadersRule(
+ kMinValidID + 1, kMinValidPriority, sub_frame_host, base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("set-cookie", "remove", base::nullopt)}));
+
+ // Load an extension with removeHeaders rules for the Referer and Set-Cookie
+ // headers.
+ ASSERT_NO_FATAL_FAILURE(
+ LoadExtensionWithRules({abc_set_cookie_rule, abc_referer_rule},
+ "extension_1", {URLPattern::kAllUrlsPattern}));
+
+ ui_test_utils::NavigateToURL(browser(), page_url);
+ ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
+
+ // Start the onRuleMatchedDebug observer.
+ const char kOnRuleMatchedDebugScript[] = R"(
+ var matchedRules = [];
+ var onRuleMatchedDebugCallback = (rule) => {
+ matchedRules.push(rule);
+ };
+
+ chrome.declarativeNetRequest.onRuleMatchedDebug.addListener(
+ onRuleMatchedDebugCallback);
+ window.domAutomationController.send('ready');
+ )";
+
+ ASSERT_EQ("ready", ExecuteScriptInBackgroundPage(last_loaded_extension_id(),
+ kOnRuleMatchedDebugScript));
+
+ auto set_cookie_and_referer_url =
+ embedded_test_server()->GetURL(sub_frame_host, "/set-cookie?a=b");
+
+ NavigateFrame(kFrameName1, set_cookie_and_referer_url);
+
+ // Now query the onRuleMatchedDebug results.
+ const char kQueryMatchedRulesScript[] = R"(
+ chrome.declarativeNetRequest.onRuleMatchedDebug.removeListener(
+ onRuleMatchedDebugCallback);
+ var ruleIds = matchedRules.map(matchedRule => matchedRule.rule.ruleId);
+ window.domAutomationController.send(ruleIds.sort().join());
+ )";
+
+ std::string matched_rule_ids = ExecuteScriptInBackgroundPage(
+ last_loaded_extension_id(), kQueryMatchedRulesScript);
+
+ // The request to |set_cookie_and_referer_url| should be matched with the
+ // Referer rule (ruleId 1) and the Set-Cookie rule (ruleId 2).
+ 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,
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
index e4b0f34e4ee..4e96958b66a 100644
--- a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
@@ -38,6 +38,7 @@
#include "extensions/browser/api/declarative_net_request/ruleset_manager.h"
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
#include "extensions/browser/api/declarative_net_request/test_utils.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/test_extension_registry_observer.h"
@@ -335,9 +336,9 @@ class SingleRulesetTest : public DeclarativeNetRequestUnittest {
else
rules_count = rules_list_.size();
- // We only index up to dnr_api::MAX_NUMBER_OF_RULES rules per ruleset.
- rules_count = std::min(rules_count,
- static_cast<size_t>(dnr_api::MAX_NUMBER_OF_RULES));
+ // We only index up to GetStaticRuleLimit() rules per ruleset.
+ rules_count =
+ std::min(rules_count, static_cast<size_t>(GetStaticRuleLimit()));
DeclarativeNetRequestUnittest::LoadAndExpectSuccess(rules_count,
rules_count, true);
@@ -652,10 +653,14 @@ TEST_P(SingleRulesetTest, InvalidJSONRules_Parsed) {
}
}
-// Ensure that we can add up to MAX_NUMBER_OF_RULES.
+// Ensure that we can add up to GetStaticRuleLimit() rules.
TEST_P(SingleRulesetTest, RuleCountLimitMatched) {
+ // Override the API rule limit to prevent a timeout on loading the extension.
+ base::AutoReset<int> rule_limit_override =
+ CreateScopedStaticRuleLimitOverrideForTesting(100);
+
TestRule rule = CreateGenericRule();
- for (int i = 0; i < dnr_api::MAX_NUMBER_OF_RULES; ++i) {
+ for (int i = 0; i < GetStaticRuleLimit(); ++i) {
rule.id = kMinValidID + i;
rule.condition->url_filter = std::to_string(i);
AddRule(rule);
@@ -665,8 +670,12 @@ TEST_P(SingleRulesetTest, RuleCountLimitMatched) {
// Ensure that we get an install warning on exceeding the rule count limit.
TEST_P(SingleRulesetTest, RuleCountLimitExceeded) {
+ // Override the API rule limit to prevent a timeout on loading the extension.
+ base::AutoReset<int> rule_limit_override =
+ CreateScopedStaticRuleLimitOverrideForTesting(100);
+
TestRule rule = CreateGenericRule();
- for (int i = 1; i <= dnr_api::MAX_NUMBER_OF_RULES + 1; ++i) {
+ for (int i = 1; i <= GetStaticRuleLimit() + 1; ++i) {
rule.id = kMinValidID + i;
rule.condition->url_filter = std::to_string(i);
AddRule(rule);
@@ -749,10 +758,14 @@ TEST_P(SingleRulesetTest, WarningAndError) {
// Ensure that we get an install warning on exceeding the regex rule count
// limit.
TEST_P(SingleRulesetTest, RegexRuleCountExceeded) {
+ // Override the API rule limit to prevent a timeout on loading the extension.
+ base::AutoReset<int> rule_limit_override =
+ CreateScopedRegexRuleLimitOverrideForTesting(100);
+
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) {
+ for (int i = 1; i <= GetRegexRuleLimit() + 5; ++i, ++rule_id) {
regex_rule.id = rule_id;
regex_rule.condition->regex_filter = std::to_string(i);
AddRule(regex_rule);
@@ -767,8 +780,7 @@ TEST_P(SingleRulesetTest, RegexRuleCountExceeded) {
}
extension_loader()->set_ignore_manifest_warnings(true);
- LoadAndExpectSuccess(dnr_api::MAX_NUMBER_OF_REGEX_RULES +
- kCountNonRegexRules);
+ LoadAndExpectSuccess(GetRegexRuleLimit() + 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) {
@@ -952,10 +964,9 @@ class MultipleRulesetsTest : public DeclarativeNetRequestUnittest {
for (const TestRulesetInfo& info : rulesets_) {
size_t count = info.rules_value.GetList().size();
- // We only index up to dnr_api::MAX_NUMBER_OF_RULES per ruleset, but may
+ // We only index up to GetStaticRuleLimit() rules per ruleset, but may
// index more rules than this limit across rulesets.
- count =
- std::min(count, static_cast<size_t>(dnr_api::MAX_NUMBER_OF_RULES));
+ count = std::min(count, static_cast<size_t>(GetStaticRuleLimit()));
rules_count += count;
if (info.enabled)
@@ -1017,6 +1028,12 @@ TEST_P(MultipleRulesetsTest, ListNotPassed) {
// Tests an extension with multiple static rulesets with each ruleset generating
// some install warnings.
TEST_P(MultipleRulesetsTest, InstallWarnings) {
+ // Override the API rule limit to prevent a timeout on loading the extension.
+ base::AutoReset<int> rule_limit_override =
+ CreateScopedStaticRuleLimitOverrideForTesting(100);
+ base::AutoReset<int> regex_rule_limit_override =
+ CreateScopedRegexRuleLimitOverrideForTesting(60);
+
size_t expected_rule_count = 0;
size_t enabled_rule_count = 0;
std::vector<std::string> expected_warnings;
@@ -1045,29 +1062,27 @@ TEST_P(MultipleRulesetsTest, InstallWarnings) {
{
// Persist a ruleset with an install warning for exceeding the rule count.
TestRulesetInfo info =
- CreateRuleset(kId2, dnr_api::MAX_NUMBER_OF_RULES + 1, 0, false);
+ CreateRuleset(kId2, GetStaticRuleLimit() + 1, 0, false);
AddRuleset(info);
expected_warnings.push_back(
GetErrorWithFilename(kRuleCountExceeded, info.relative_file_path));
- expected_rule_count += dnr_api::MAX_NUMBER_OF_RULES;
+ expected_rule_count += GetStaticRuleLimit();
}
{
// Persist a ruleset with an install warning for exceeding the regex rule
// count.
size_t kCountNonRegexRules = 5;
- TestRulesetInfo info =
- CreateRuleset(kId3, kCountNonRegexRules,
- dnr_api::MAX_NUMBER_OF_REGEX_RULES + 1, false);
+ TestRulesetInfo info = CreateRuleset(kId3, kCountNonRegexRules,
+ GetRegexRuleLimit() + 1, false);
AddRuleset(info);
expected_warnings.push_back(
GetErrorWithFilename(kRegexRuleCountExceeded, info.relative_file_path));
- expected_rule_count +=
- kCountNonRegexRules + dnr_api::MAX_NUMBER_OF_REGEX_RULES;
+ expected_rule_count += kCountNonRegexRules + GetRegexRuleLimit();
}
extension_loader()->set_ignore_manifest_warnings(true);
@@ -1111,12 +1126,16 @@ TEST_P(MultipleRulesetsTest, EnabledRulesCount) {
// Ensure that exceeding the rules count limit across rulesets raises an install
// warning.
TEST_P(MultipleRulesetsTest, StaticRuleCountExceeded) {
+ // Override the API rule limit to prevent a timeout on loading the extension.
+ base::AutoReset<int> rule_limit_override =
+ CreateScopedStaticRuleLimitOverrideForTesting(50);
+
// Enabled on load.
AddRuleset(CreateRuleset(kId1, 10, 0, true));
// Disabled by default.
AddRuleset(CreateRuleset(kId2, 20, 0, false));
// Not enabled on load since including it exceeds the static rules count.
- AddRuleset(CreateRuleset(kId3, dnr_api::MAX_NUMBER_OF_RULES + 10, 0, true));
+ AddRuleset(CreateRuleset(kId3, GetStaticRuleLimit() + 10, 0, true));
// Enabled on load.
AddRuleset(CreateRuleset(kId4, 30, 0, true));
@@ -1126,8 +1145,6 @@ TEST_P(MultipleRulesetsTest, StaticRuleCountExceeded) {
{
// To prevent timeouts in debug builds, increase the wait timeout to the
// test launcher's timeout. See crbug.com/1071403.
- // TODO(karandeepb): Provide a way to fake dnr_api::MAX_NUMBER_OF_RULES in
- // tests to decrease test runtime.
base::test::ScopedRunLoopTimeout specific_timeout(
FROM_HERE, TestTimeouts::test_launcher_timeout());
LoadAndExpectSuccess();
@@ -1167,7 +1184,7 @@ TEST_P(MultipleRulesetsTest, RegexRuleCountExceeded) {
AddRuleset(CreateRuleset(kId1, 10000, 100, true));
// Won't be enabled on load since including it will exceed the regex rule
// count.
- AddRuleset(CreateRuleset(kId2, 1, dnr_api::MAX_NUMBER_OF_REGEX_RULES, true));
+ AddRuleset(CreateRuleset(kId2, 1, GetRegexRuleLimit(), true));
// Won't be enabled on load since it is disabled by default.
AddRuleset(CreateRuleset(kId3, 10, 10, false));
// Enabled on load.
@@ -1225,8 +1242,12 @@ TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_InvalidRulesetID) {
}
TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_RuleCountExceeded) {
+ // Override the API rule limit to prevent a timeout on loading the extension.
+ base::AutoReset<int> rule_limit_override =
+ CreateScopedStaticRuleLimitOverrideForTesting(100);
+
AddRuleset(CreateRuleset(kId1, 10, 10, true));
- AddRuleset(CreateRuleset(kId2, dnr_api::MAX_NUMBER_OF_RULES, 0, false));
+ AddRuleset(CreateRuleset(kId2, GetStaticRuleLimit(), 0, false));
RulesetManagerObserver ruleset_waiter(manager());
LoadAndExpectSuccess();
@@ -1245,7 +1266,7 @@ TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_RuleCountExceeded) {
TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_RegexRuleCountExceeded) {
AddRuleset(CreateRuleset(kId1, 0, 10, false));
- AddRuleset(CreateRuleset(kId2, 0, dnr_api::MAX_NUMBER_OF_REGEX_RULES, true));
+ AddRuleset(CreateRuleset(kId2, 0, GetRegexRuleLimit(), true));
RulesetManagerObserver ruleset_waiter(manager());
LoadAndExpectSuccess();
@@ -1274,8 +1295,7 @@ TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_InternalError) {
// First delete the indexed ruleset file for the second ruleset. Enabling it
// should cause re-indexing and succeed in enabling the ruleset.
base::HistogramTester tester;
- ASSERT_TRUE(base::DeleteFile(static_sources[1].indexed_path(),
- false /* recursive */));
+ ASSERT_TRUE(base::DeleteFile(static_sources[1].indexed_path()));
RunUpdateEnabledRulesetsFunction(*extension(), {kId1}, {kId2},
base::nullopt);
@@ -1290,10 +1310,8 @@ TEST_P(MultipleRulesetsTest, UpdateEnabledRulesets_InternalError) {
// Now delete both the indexed and json ruleset file for the first ruleset.
// This will prevent enabling the first ruleset since re-indexing will fail.
base::HistogramTester tester;
- ASSERT_TRUE(base::DeleteFile(static_sources[0].indexed_path(),
- false /* recursive */));
- ASSERT_TRUE(
- base::DeleteFile(static_sources[0].json_path(), false /* recursive */));
+ ASSERT_TRUE(base::DeleteFile(static_sources[0].indexed_path()));
+ ASSERT_TRUE(base::DeleteFile(static_sources[0].json_path()));
RunUpdateEnabledRulesetsFunction(*extension(), {}, {kId1},
kInternalErrorUpdatingEnabledRulesets);
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 2c18c239b23..b1c2a521b2d 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
@@ -14,7 +14,6 @@
#include "chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/extension_util.h"
-#include "components/version_info/channel.h"
#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
#include "extensions/browser/api/declarative_net_request/request_action.h"
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
@@ -28,7 +27,6 @@
#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/features/feature_channel.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/url_pattern.h"
@@ -96,7 +94,7 @@ class RulesetManagerTest : public DNRTestBase {
&expected_checksum));
std::vector<std::unique_ptr<RulesetMatcher>> matchers(1);
- EXPECT_EQ(RulesetMatcher::kLoadSuccess,
+ EXPECT_EQ(LoadRulesetResult::kSuccess,
RulesetMatcher::CreateVerifiedMatcher(
std::move(sources[0]), expected_checksum, &matchers[0]));
@@ -458,22 +456,18 @@ TEST_P(RulesetManagerTest, ExtensionScheme) {
// Test that the correct modifyHeaders actions are returned for each extension.
TEST_P(RulesetManagerTest, ModifyHeaders) {
- // TODO(crbug.com/947591): Remove the channel override once implementation of
- // modifyHeaders action is complete.
- ScopedCurrentChannel channel(::version_info::Channel::UNKNOWN);
-
const Extension* extension_1 = nullptr;
const Extension* extension_2 = nullptr;
- // Add an extension which removes the "header1" and "header2" headers.
+ // Add an extension which removes "header1" and sets "header2".
{
std::unique_ptr<CompositeMatcher> matcher;
TestRule rule = CreateGenericRule();
rule.condition->url_filter = std::string("*");
rule.action->type = std::string("modifyHeaders");
- rule.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove"),
- TestHeaderInfo("header2", "remove")});
+ rule.action->request_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt),
+ TestHeaderInfo("header2", "set", "value2")});
ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
{rule}, "test extension", &matcher, {URLPattern::kAllUrlsPattern}));
@@ -481,16 +475,16 @@ TEST_P(RulesetManagerTest, ModifyHeaders) {
manager()->AddRuleset(extension_1->id(), std::move(matcher));
}
- // Add another extension which removes the "header1" and "header3" headers.
+ // Add another extension which removes "header1" and appends "header3".
{
std::unique_ptr<CompositeMatcher> matcher;
TestRule rule = CreateGenericRule();
rule.condition->url_filter = std::string("*");
rule.action->type = std::string("modifyHeaders");
- rule.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove")});
- rule.action->response_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header3", "remove")});
+ rule.action->request_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt)});
+ rule.action->response_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header3", "append", "value3")});
ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
{rule}, "test extension 2", &matcher, {URLPattern::kAllUrlsPattern}));
@@ -509,18 +503,20 @@ TEST_P(RulesetManagerTest, ModifyHeaders) {
RequestAction expected_action_1 = CreateRequestActionForTesting(
RequestActionType::MODIFY_HEADERS, kMinValidID, kDefaultPriority,
kMinValidStaticRulesetID, extension_2->id());
- expected_action_1.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE)};
- expected_action_1.response_headers_to_modify = {
- RequestAction::HeaderInfo("header3", dnr_api::HEADER_OPERATION_REMOVE)};
+ expected_action_1.request_headers_to_modify = {RequestAction::HeaderInfo(
+ "header1", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)};
+ expected_action_1.response_headers_to_modify = {RequestAction::HeaderInfo(
+ "header3", dnr_api::HEADER_OPERATION_APPEND, "value3")};
// Create the expected RequestAction for |extension_1|.
RequestAction expected_action_2 = CreateRequestActionForTesting(
RequestActionType::MODIFY_HEADERS, kMinValidID, kDefaultPriority,
kMinValidStaticRulesetID, extension_1->id());
expected_action_2.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE)};
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_SET,
+ "value2")};
// Verify that the list of actions is sorted in descending order of extension
// priority.
@@ -533,18 +529,14 @@ TEST_P(RulesetManagerTest, ModifyHeaders) {
// Test that an extension's modify header rules are applied on a request only if
// it has host permissions for the request.
TEST_P(RulesetManagerTest, ModifyHeaders_HostPermissions) {
- // TODO(crbug.com/947591): Remove the channel override once implementation of
- // modifyHeaders action is complete.
- ScopedCurrentChannel channel(::version_info::Channel::UNKNOWN);
-
// Add an extension which removes the "header1" header with host permissions
// for example.com.
std::unique_ptr<CompositeMatcher> matcher;
TestRule rule = CreateGenericRule();
rule.condition->url_filter = std::string("*");
rule.action->type = std::string("modifyHeaders");
- rule.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove")});
+ rule.action->request_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt)});
ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
{rule}, "test extension", &matcher, {"*://example.com/*"}));
@@ -561,8 +553,8 @@ TEST_P(RulesetManagerTest, ModifyHeaders_HostPermissions) {
RequestAction expected_action = CreateRequestActionForTesting(
RequestActionType::MODIFY_HEADERS, kMinValidID, kDefaultPriority,
kMinValidStaticRulesetID, extension->id());
- expected_action.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE)};
+ expected_action.request_headers_to_modify = {RequestAction::HeaderInfo(
+ "header1", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)};
EXPECT_THAT(actual_actions, ::testing::ElementsAre(::testing::Eq(
::testing::ByRef(expected_action))));
diff --git a/chromium/chrome/browser/extensions/api/developer_private/DEPS b/chromium/chrome/browser/extensions/api/developer_private/DEPS
index 5b9436cd654..96ba367d2e6 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/DEPS
+++ b/chromium/chrome/browser/extensions/api/developer_private/DEPS
@@ -7,4 +7,10 @@ specific_include_rules = {
# Allow the unittest to create a data_decoder service.
"+services/data_decoder"
],
+
+ # This DEPS violation snuck in while there was a bug in the checkdeps tool.
+ # https://crbug.com/1084826
+ "developer_private_api\.cc": [
+ "+chrome/browser/apps/app_service/app_launch_params.h",
+ ],
}
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 c496bd428c4..56c6abbd526 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
@@ -19,7 +19,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/devtools/devtools_window.h"
@@ -394,7 +393,8 @@ void DeveloperPrivateEventRouter::RemoveExtensionId(
void DeveloperPrivateEventRouter::OnExtensionLoaded(
content::BrowserContext* browser_context,
const Extension* extension) {
- DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context)));
+ DCHECK(
+ profile_->IsSameOrParent(Profile::FromBrowserContext(browser_context)));
BroadcastItemStateChanged(developer::EVENT_TYPE_LOADED, extension->id());
}
@@ -402,7 +402,8 @@ void DeveloperPrivateEventRouter::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) {
- DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context)));
+ DCHECK(
+ profile_->IsSameOrParent(Profile::FromBrowserContext(browser_context)));
BroadcastItemStateChanged(developer::EVENT_TYPE_UNLOADED, extension->id());
}
@@ -410,7 +411,8 @@ void DeveloperPrivateEventRouter::OnExtensionInstalled(
content::BrowserContext* browser_context,
const Extension* extension,
bool is_update) {
- DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context)));
+ DCHECK(
+ profile_->IsSameOrParent(Profile::FromBrowserContext(browser_context)));
BroadcastItemStateChanged(developer::EVENT_TYPE_INSTALLED, extension->id());
}
@@ -418,7 +420,8 @@ void DeveloperPrivateEventRouter::OnExtensionUninstalled(
content::BrowserContext* browser_context,
const Extension* extension,
extensions::UninstallReason reason) {
- DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context)));
+ DCHECK(
+ profile_->IsSameOrParent(Profile::FromBrowserContext(browser_context)));
BroadcastItemStateChanged(developer::EVENT_TYPE_UNINSTALLED, extension->id());
}
@@ -1486,8 +1489,8 @@ void DeveloperPrivateLoadDirectoryFunction::ClearExistingDirectoryContent(
pending_copy_operations_count_ = 1;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&DeveloperPrivateLoadDirectoryFunction::ReadDirectoryByFileSystemAPI,
this, project_path, project_path.BaseName()));
@@ -1555,8 +1558,8 @@ void DeveloperPrivateLoadDirectoryFunction::ReadDirectoryByFileSystemAPICb(
response = NoArguments();
else
response = Error(error_);
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&DeveloperPrivateLoadDirectoryFunction::Respond, this,
std::move(response)));
}
@@ -1597,8 +1600,8 @@ void DeveloperPrivateLoadDirectoryFunction::CopyFile(
pending_copy_operations_count_--;
if (!pending_copy_operations_count_) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&DeveloperPrivateLoadDirectoryFunction::Load, this));
}
}
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 42ae22ba000..79ba1f83ece 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
@@ -466,7 +466,7 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivatePackFunction) {
// Try to pack a final time when omitting (an existing) pem file. We should
// get an error.
- base::DeleteFile(crx_path, false);
+ base::DeleteFile(crx_path);
EXPECT_TRUE(pack_args.Remove(1u, nullptr)); // Remove the pem key argument.
EXPECT_TRUE(pack_args.Remove(1u, nullptr)); // Remove the flags argument.
EXPECT_TRUE(TestPackExtensionFunction(
diff --git a/chromium/chrome/browser/extensions/api/developer_private/entry_picker.cc b/chromium/chrome/browser/extensions/api/developer_private/entry_picker.cc
index afb404e5637..ad7d48b8c67 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/entry_picker.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/entry_picker.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
@@ -37,14 +36,14 @@ EntryPicker::EntryPicker(EntryPickerClient* client,
: client_(client) {
if (g_skip_picker_for_test) {
if (g_path_to_be_picked_for_test) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&EntryPicker::FileSelected, base::Unretained(this),
*g_path_to_be_picked_for_test, 1,
static_cast<void*>(nullptr)));
} else {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&EntryPicker::FileSelectionCanceled,
base::Unretained(this), static_cast<void*>(nullptr)));
}
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 6c4f2b9c43f..af6a8022a03 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
@@ -522,17 +522,10 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper(
// ControlledInfo.
bool is_policy_location = Manifest::IsPolicyLocation(extension.location());
if (is_policy_location) {
- info->controlled_info.reset(new developer::ControlledInfo());
- if (is_policy_location) {
- info->controlled_info->type = developer::CONTROLLER_TYPE_POLICY;
- info->controlled_info->text =
- l10n_util::GetStringUTF8(IDS_EXTENSIONS_INSTALL_LOCATION_ENTERPRISE);
- } else {
- info->controlled_info->type =
- developer::CONTROLLER_TYPE_SUPERVISED_USER_CUSTODIAN;
- info->controlled_info->text = l10n_util::GetStringUTF8(
- IDS_EXTENSIONS_INSTALLED_BY_SUPERVISED_USER_CUSTODIAN);
- }
+ info->controlled_info = std::make_unique<developer::ControlledInfo>();
+ info->controlled_info->type = developer::CONTROLLER_TYPE_POLICY;
+ info->controlled_info->text =
+ l10n_util::GetStringUTF8(IDS_EXTENSIONS_INSTALL_LOCATION_ENTERPRISE);
}
bool is_enabled = state == developer::EXTENSION_STATE_ENABLED;
@@ -578,6 +571,7 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper(
bool permissions_increase =
(disable_reasons & disable_reason::DISABLE_PERMISSIONS_INCREASE) != 0;
info->disable_reasons.parent_disabled_permissions =
+ supervised_user_service_->IsChild() &&
!supervised_user_service_
->GetSupervisedUserExtensionsMayRequestPermissionsPref() &&
(custodian_approval_required || permissions_increase);
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 c80a16f7e47..47d6e81852b 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
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
+#include "base/files/file_path.h"
#include "base/json/json_file_value_serializer.h"
#include "base/json/json_writer.h"
#include "base/macros.h"
@@ -22,12 +23,13 @@
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/error_console/error_console.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_service_test_base.h"
+#include "chrome/browser/extensions/extension_service_test_with_install.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/permissions_test_util.h"
#include "chrome/browser/extensions/permissions_updater.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/buildflags.h"
#include "chrome/common/extensions/api/developer_private.h"
#include "chrome/common/pref_names.h"
#include "components/crx_file/id_util.h"
@@ -44,6 +46,12 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.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/browser/supervised_user/supervised_user_test_util.h"
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
namespace extensions {
namespace developer = api::developer_private;
@@ -88,15 +96,20 @@ std::string SiteControlsToString(
} // namespace
-class ExtensionInfoGeneratorUnitTest : public ExtensionServiceTestBase {
+class ExtensionInfoGeneratorUnitTest : public ExtensionServiceTestWithInstall {
public:
ExtensionInfoGeneratorUnitTest() {}
~ExtensionInfoGeneratorUnitTest() override {}
protected:
void SetUp() override {
- ExtensionServiceTestBase::SetUp();
- InitializeEmptyExtensionService();
+ ExtensionServiceTestWithInstall::SetUp();
+ InitializeExtensionService(GetExtensionServiceInitParams());
+ }
+
+ // Returns the initialization parameters for the extension service.
+ virtual ExtensionServiceInitParams GetExtensionServiceInitParams() {
+ return CreateDefaultInitParams();
}
void OnInfoGenerated(std::unique_ptr<developer::ExtensionInfo>* info_out,
@@ -810,4 +823,128 @@ TEST_F(ExtensionInfoGeneratorUnitTest, Blacklisted) {
EXPECT_EQ(developer::EXTENSION_STATE_ENABLED, info2->state);
}
+// Tests that the parent_disabled_permissions disable reason is never set for
+// regular users. Prevents a regression to crbug/1100395.
+TEST_F(ExtensionInfoGeneratorUnitTest,
+ NoParentDisabledPermissionsForRegularUsers) {
+ // Preconditions.
+ ASSERT_FALSE(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_NEW);
+ // The extension must now be installed and enabled.
+ ASSERT_TRUE(extension);
+ ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
+
+ // Save the id, as |extension| will be destroyed during updating.
+ std::string extension_id = extension->id();
+
+ // 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 pending approval for permission increases.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
+
+ // Due to a permissions increase, prefs will contain escalation information.
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
+
+ std::unique_ptr<api::developer_private::ExtensionInfo> info =
+ GenerateExtensionInfo(extension_id);
+
+ // Verify that the kite icon error tooltip doesn't appear for regular users.
+ EXPECT_FALSE(info->disable_reasons.parent_disabled_permissions);
+}
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+// Tests for supervised users (child accounts). Supervised users are not allowed
+// to install apps or extensions unless their parent approves.
+class ExtensionInfoGeneratorUnitTestSupervised
+ : public ExtensionInfoGeneratorUnitTest {
+ public:
+ ExtensionInfoGeneratorUnitTestSupervised() = default;
+ ~ExtensionInfoGeneratorUnitTestSupervised() override = default;
+
+ SupervisedUserService* GetSupervisedUserService() {
+ return SupervisedUserServiceFactory::GetForProfile(profile());
+ }
+
+ // ExtensionInfoGeneratorUnitTest:
+ ExtensionServiceInitParams GetExtensionServiceInitParams() override {
+ ExtensionServiceInitParams params =
+ ExtensionInfoGeneratorUnitTest::GetExtensionServiceInitParams();
+ // Force a TestingPrefServiceSyncable to be created.
+ params.pref_file.clear();
+ params.profile_is_supervised = true;
+ return params;
+ }
+
+ void SetUp() override {
+ ExtensionInfoGeneratorUnitTest::SetUp();
+
+ // Set up custodians (parents) for the child.
+ supervised_user_test_util::AddCustodians(profile());
+
+ GetSupervisedUserService()->Init();
+ // Set the pref to allow the child to request extension install.
+ GetSupervisedUserService()
+ ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(true);
+ }
+};
+
+// Tests that when an extension is disabled pending permission updates, and the
+// parent has turned off the "Permissions for sites, apps and extensions"
+// toggle, then supervised users will see a kite error icon with a tooltip.
+TEST_F(ExtensionInfoGeneratorUnitTestSupervised,
+ ParentDisabledPermissionsForSupervisedUsers) {
+ // 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);
+ // The extension should be installed but disabled pending custodian approval.
+ ASSERT_TRUE(extension);
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
+
+ // Save the id, as |extension| will be destroyed during updating.
+ std::string extension_id = extension->id();
+
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
+
+ // Simulate parent approval for the extension installation.
+ GetSupervisedUserService()->AddExtensionApproval(*extension);
+ // The extension should be enabled now.
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
+
+ // 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 pending approval for permission increases.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
+
+ // Due to a permission increase, prefs will contain escalation information.
+ EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
+
+ // Simulate the parent disallowing the child from approving permission
+ // updates.
+ GetSupervisedUserService()
+ ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(false);
+
+ std::unique_ptr<api::developer_private::ExtensionInfo> info =
+ GenerateExtensionInfo(extension_id);
+
+ // Verify that the kite icon error tooltip appears for supervised users.
+ EXPECT_TRUE(info->disable_reasons.parent_disabled_permissions);
+}
+
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
index 2ae57ab4ddd..cd347b06c7b 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -1563,7 +1563,7 @@ ExtensionFunction::ResponseAction DownloadsSetShelfEnabledFunction::Run() {
(current_service == incognito_service)) &&
browser->window()->IsDownloadShelfVisible() &&
!current_service->IsShelfEnabled())
- browser->window()->GetDownloadShelf()->Close(DownloadShelf::AUTOMATIC);
+ browser->window()->GetDownloadShelf()->Close();
}
}
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 fc10f9ec110..fbf95144f6e 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -18,7 +18,6 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
@@ -68,12 +67,6 @@
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/url_request/url_request_slow_download_job.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_job_factory.h"
-#include "net/url_request/url_request_job_factory_impl.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_operation_runner.h"
#include "storage/browser/file_system/file_system_url.h"
@@ -114,8 +107,8 @@ void OnOpenPromptCreated(download::DownloadItem* item,
DownloadOpenPrompt* prompt) {
EXPECT_FALSE(item->GetOpened());
// Posts a task to accept the DownloadOpenPrompt.
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&DownloadOpenPrompt::AcceptConfirmationDialogForTesting,
base::Unretained(prompt)));
}
@@ -321,10 +314,9 @@ class DownloadOpenObserver : public download::DownloadItem::Observer {
class DownloadExtensionTest : public ExtensionApiTest {
public:
DownloadExtensionTest()
- : extension_(NULL),
- incognito_browser_(NULL),
- current_browser_(NULL) {
- }
+ : extension_(nullptr),
+ incognito_browser_(nullptr),
+ current_browser_(nullptr) {}
protected:
// Used with CreateHistoryDownloads
@@ -709,8 +701,8 @@ class MockIconExtractorImpl : public DownloadFileIconExtractor {
if (expected_path_ == path &&
expected_icon_size_ == icon_size) {
callback_ = callback;
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&MockIconExtractorImpl::RunCallback,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&MockIconExtractorImpl::RunCallback,
base::Unretained(this)));
return true;
} else {
@@ -793,14 +785,14 @@ class HTML5FileWriter {
// Invoke the fileapi to copy it into the sandboxed filesystem.
bool result = false;
base::RunLoop run_loop;
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&CreateFileForTestingOnIOThread,
base::Unretained(context), path, temp_file,
base::Unretained(&result), run_loop.QuitClosure()));
// Wait for that to finish.
run_loop.Run();
- base::DeleteFile(temp_file, false);
+ base::DeleteFile(temp_file);
return result;
}
@@ -810,7 +802,7 @@ class HTML5FileWriter {
base::File::Error error) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
*result = error == base::File::FILE_OK;
- base::PostTask(FROM_HERE, {BrowserThread::UI}, quit_closure);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, quit_closure);
}
static void CreateFileForTestingOnIOThread(
@@ -882,14 +874,7 @@ downloads::InterruptReason InterruptReasonContentToExtension(
} // namespace
-#if defined(OS_CHROMEOS)
-// http://crbug.com/396510
-#define MAYBE_DownloadExtensionTest_Open DISABLED_DownloadExtensionTest_Open
-#else
-#define MAYBE_DownloadExtensionTest_Open DownloadExtensionTest_Open
-#endif
-IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_Open) {
+IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadExtensionTest_Open) {
LoadExtension("downloads_split");
DownloadsOpenFunction* open_function = new DownloadsOpenFunction();
open_function->set_user_gesture(true);
@@ -1056,16 +1041,10 @@ scoped_refptr<ExtensionFunction> MockedGetFileIconFunction(
return function;
}
-// https://crbug.com/678967
-#if defined(OS_WIN) || defined(OS_LINUX)
-#define MAYBE_DownloadExtensionTest_FileIcon_Active DISABLED_DownloadExtensionTest_FileIcon_Active
-#else
-#define MAYBE_DownloadExtensionTest_FileIcon_Active DownloadExtensionTest_FileIcon_Active
-#endif
// Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted
// download items.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_FileIcon_Active) {
+ DownloadExtensionTest_FileIcon_Active) {
DownloadItem* download_item = CreateFirstSlowTestDownload();
ASSERT_TRUE(download_item);
ASSERT_FALSE(download_item->GetTargetFilePath().empty());
@@ -1202,7 +1181,7 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, FileExistenceCheckAfterSearch) {
// Finish the download and try again.
FinishFirstSlowDownloads();
- base::DeleteFile(download_item->GetTargetFilePath(), false);
+ base::DeleteFile(download_item->GetTargetFilePath());
ASSERT_FALSE(download_item->GetFileExternallyRemoved());
std::unique_ptr<base::Value> result(
@@ -1266,14 +1245,7 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
// Test the |id| parameter for search().
//
-// http://crbug.com/508949
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_DownloadExtensionTest_SearchId DISABLED_DownloadExtensionTest_SearchId
-#else
-#define MAYBE_DownloadExtensionTest_SearchId DownloadExtensionTest_SearchId
-#endif
-IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_SearchId) {
+IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadExtensionTest_SearchId) {
DownloadManager::DownloadVector items;
CreateTwoDownloads(&items);
ScopedItemVectorCanceller delete_items(&items);
@@ -1294,14 +1266,8 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
// Test specifying both the |id| and |filename| parameters for search().
//
-// http://crbug.com/508949
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_DownloadExtensionTest_SearchIdAndFilename DISABLED_DownloadExtensionTest_SearchIdAndFilename
-#else
-#define MAYBE_DownloadExtensionTest_SearchIdAndFilename DownloadExtensionTest_SearchIdAndFilename
-#endif
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_SearchIdAndFilename) {
+ DownloadExtensionTest_SearchIdAndFilename) {
DownloadManager::DownloadVector items;
CreateTwoDownloads(&items);
ScopedItemVectorCanceller delete_items(&items);
@@ -1400,15 +1366,8 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
}
// Test the |state| option for search().
-//
-// http://crbug.com/508949
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_DownloadExtensionTest_SearchState DISABLED_DownloadExtensionTest_SearchState
-#else
-#define MAYBE_DownloadExtensionTest_SearchState DownloadExtensionTest_SearchState
-#endif
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_SearchState) {
+ DownloadExtensionTest_SearchState) {
DownloadManager::DownloadVector items;
CreateTwoDownloads(&items);
ScopedItemVectorCanceller delete_items(&items);
@@ -1424,15 +1383,8 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
}
// Test the |limit| option for search().
-//
-// http://crbug.com/508949
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_DownloadExtensionTest_SearchLimit DISABLED_DownloadExtensionTest_SearchLimit
-#else
-#define MAYBE_DownloadExtensionTest_SearchLimit DownloadExtensionTest_SearchLimit
-#endif
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_SearchLimit) {
+ DownloadExtensionTest_SearchLimit) {
DownloadManager::DownloadVector items;
CreateTwoDownloads(&items);
ScopedItemVectorCanceller delete_items(&items);
@@ -1495,21 +1447,13 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
ASSERT_EQ(items[2]->GetTargetFilePath().value(), item_name);
}
-// https://crbug.com/874946, flaky on Win.
-#if defined(OS_WIN)
-#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \
- DISABLED_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
-#else
-#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \
- DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
-#endif
// Test that incognito downloads are only visible in incognito contexts, and
// test that on-record downloads are visible in both incognito and on-record
// contexts, for DownloadsSearchFunction, DownloadsPauseFunction,
// DownloadsResumeFunction, and DownloadsCancelFunction.
IN_PROC_BROWSER_TEST_F(
DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
+ DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
std::unique_ptr<base::Value> result_value;
base::ListValue* result_list = NULL;
base::DictionaryValue* result_dict = NULL;
@@ -1887,18 +1831,9 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
result_id)));
}
-#if defined(OS_WIN)
-// This test is very flaky on Win. http://crbug.com/248438
-#define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
- DISABLED_DownloadExtensionTest_Download_UnsafeHeaders
-#else
-#define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
- DownloadExtensionTest_Download_UnsafeHeaders
-#endif
-
// Test that we disallow certain headers case-insensitively.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_Download_UnsafeHeaders) {
+ DownloadExtensionTest_Download_UnsafeHeaders) {
LoadExtension("downloads_split");
ASSERT_TRUE(StartEmbeddedTestServer());
GoOnTheRecord();
@@ -1975,6 +1910,7 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
download_url.c_str())).c_str());
}
+// This test is very flaky on Win. http://crbug.com/248438
#if defined(OS_WIN)
#define MAYBE_DownloadExtensionTest_Download_Subdirectory\
DISABLED_DownloadExtensionTest_Download_Subdirectory
@@ -2043,19 +1979,10 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
download_url.c_str())).c_str());
}
-// flaky on mac: crbug.com/392288
-#if defined(OS_MACOSX)
-#define MAYBE_DownloadExtensionTest_Download_InvalidURLs \
- DISABLED_DownloadExtensionTest_Download_InvalidURLs
-#else
-#define MAYBE_DownloadExtensionTest_Download_InvalidURLs \
- DownloadExtensionTest_Download_InvalidURLs
-#endif
-
class DownloadExtensionTestWithFtp : public DownloadExtensionTest {
public:
DownloadExtensionTestWithFtp() {
- // DownloadExtensionTest_Download_InvalidURLs requires FTP support.
+ // DownloadExtensionTest_Download_InvalidURLs2 requires FTP support.
// TODO(https://crbug.com/333943): Remove FTP tests and FTP feature flags.
scoped_feature_list_.InitAndEnableFeature(features::kFtpProtocol);
}
@@ -2066,27 +1993,27 @@ class DownloadExtensionTestWithFtp : public DownloadExtensionTest {
// Test that downloading invalid URLs immediately returns kInvalidURLError.
IN_PROC_BROWSER_TEST_F(DownloadExtensionTestWithFtp,
- MAYBE_DownloadExtensionTest_Download_InvalidURLs) {
- LoadExtension("downloads_split");
- GoOnTheRecord();
-
- static const char* const kInvalidURLs[] = {
- "foo bar",
- "../hello",
- "/hello",
- "http://",
- "#frag",
- "foo/bar.html#frag",
- "google.com/",
+ DownloadExtensionTest_Download_InvalidURLs1) {
+ static constexpr const char* kInvalidURLs[] = {
+ "foo bar", "../hello", "/hello", "http://",
+ "#frag", "foo/bar.html#frag", "google.com/",
};
- for (size_t index = 0; index < base::size(kInvalidURLs); ++index) {
+ for (const char* url : kInvalidURLs) {
EXPECT_STREQ(errors::kInvalidURL,
- RunFunctionAndReturnError(new DownloadsDownloadFunction(),
- base::StringPrintf(
- "[{\"url\": \"%s\"}]", kInvalidURLs[index])).c_str())
- << kInvalidURLs[index];
+ RunFunctionAndReturnError(
+ new DownloadsDownloadFunction(),
+ base::StringPrintf("[{\"url\": \"%s\"}]", url))
+ .c_str())
+ << url;
}
+}
+
+// Test various failure modes for downloading invalid URLs.
+IN_PROC_BROWSER_TEST_F(DownloadExtensionTestWithFtp,
+ DownloadExtensionTest_Download_InvalidURLs2) {
+ LoadExtension("downloads_split");
+ GoOnTheRecord();
int result_id = -1;
std::unique_ptr<base::Value> result(RunFunctionAndReturnResult(
@@ -4255,8 +4182,11 @@ IN_PROC_BROWSER_TEST_F(
// resumed. http://crbug.com/225901
ui_test_utils::NavigateToURLWithDisposition(
current_browser(),
- GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl),
- WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
+ // This code used to use a mock class that no longer works, due to the
+ // NetworkService shipping.
+ // TODO(https://crbug.com/700382): Fix or delete this test.
+ GURL(), WindowOpenDisposition::CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_NONE);
observer->WaitForFinished();
EXPECT_EQ(1u, observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
DownloadManager::DownloadVector items;
@@ -4293,8 +4223,10 @@ IN_PROC_BROWSER_TEST_F(
ClearEvents();
ui_test_utils::NavigateToURLWithDisposition(
current_browser(),
- GURL(net::URLRequestSlowDownloadJob::kErrorDownloadUrl),
- WindowOpenDisposition::NEW_BACKGROUND_TAB,
+ // This code used to use a mock class that no longer works, due to the
+ // NetworkService shipping.
+ // TODO(https://crbug.com/700382): Fix or delete this test.
+ GURL(), WindowOpenDisposition::NEW_BACKGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Errors caught before filename determination are delayed until after
@@ -4393,12 +4325,14 @@ void OnDangerPromptCreated(DownloadDangerPrompt* prompt) {
prompt->InvokeActionForTesting(DownloadDangerPrompt::ACCEPT);
}
-#if defined(OS_MACOSX)
-// Flakily triggers and assert on Mac.
+#if defined(OS_MACOSX) && !defined(NDEBUG)
+// Flaky on Mac debug, failing with a timeout.
// http://crbug.com/180759
-#define MAYBE_DownloadExtensionTest_AcceptDanger DISABLED_DownloadExtensionTest_AcceptDanger
+#define MAYBE_DownloadExtensionTest_AcceptDanger \
+ DISABLED_DownloadExtensionTest_AcceptDanger
#else
-#define MAYBE_DownloadExtensionTest_AcceptDanger DownloadExtensionTest_AcceptDanger
+#define MAYBE_DownloadExtensionTest_AcceptDanger \
+ DownloadExtensionTest_AcceptDanger
#endif
IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
MAYBE_DownloadExtensionTest_AcceptDanger) {
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 d94b303a10b..1e25f6a94be 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
@@ -26,14 +26,17 @@ namespace {
// Checks for the current browser context if the user is affiliated or belongs
// to the sign-in profile.
-bool IsPermittedToGetDeviceAttributes(content::BrowserContext* context) {
- if (chromeos::ProfileHelper::IsSigninProfile(
- Profile::FromBrowserContext(context))) {
+bool CanGetDeviceAttributesForBrowserContext(content::BrowserContext* context) {
+ const Profile* profile = Profile::FromBrowserContext(context);
+
+ if (chromeos::ProfileHelper::IsSigninProfile(profile))
return true;
- }
+
+ if (!profile->IsRegularProfile())
+ return false;
+
const user_manager::User* user =
- chromeos::ProfileHelper::Get()->GetUserByProfile(
- Profile::FromBrowserContext(context));
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
return user->IsAffiliated();
}
@@ -48,7 +51,7 @@ EnterpriseDeviceAttributesGetDirectoryDeviceIdFunction::
ExtensionFunction::ResponseAction
EnterpriseDeviceAttributesGetDirectoryDeviceIdFunction::Run() {
std::string device_id;
- if (IsPermittedToGetDeviceAttributes(browser_context())) {
+ if (CanGetDeviceAttributesForBrowserContext(browser_context())) {
device_id = g_browser_process->platform_part()
->browser_policy_connector_chromeos()
->GetDirectoryApiID();
@@ -67,7 +70,7 @@ EnterpriseDeviceAttributesGetDeviceSerialNumberFunction::
ExtensionFunction::ResponseAction
EnterpriseDeviceAttributesGetDeviceSerialNumberFunction::Run() {
std::string serial_number;
- if (IsPermittedToGetDeviceAttributes(browser_context())) {
+ if (CanGetDeviceAttributesForBrowserContext(browser_context())) {
serial_number = chromeos::system::StatisticsProvider::GetInstance()
->GetEnterpriseMachineID();
}
@@ -85,7 +88,7 @@ EnterpriseDeviceAttributesGetDeviceAssetIdFunction::
ExtensionFunction::ResponseAction
EnterpriseDeviceAttributesGetDeviceAssetIdFunction::Run() {
std::string asset_id;
- if (IsPermittedToGetDeviceAttributes(browser_context())) {
+ if (CanGetDeviceAttributesForBrowserContext(browser_context())) {
asset_id = g_browser_process->platform_part()
->browser_policy_connector_chromeos()
->GetDeviceAssetID();
@@ -104,7 +107,7 @@ EnterpriseDeviceAttributesGetDeviceAnnotatedLocationFunction::
ExtensionFunction::ResponseAction
EnterpriseDeviceAttributesGetDeviceAnnotatedLocationFunction::Run() {
std::string annotated_location;
- if (IsPermittedToGetDeviceAttributes(browser_context())) {
+ if (CanGetDeviceAttributesForBrowserContext(browser_context())) {
annotated_location = g_browser_process->platform_part()
->browser_policy_connector_chromeos()
->GetDeviceAnnotatedLocation();
@@ -123,7 +126,7 @@ EnterpriseDeviceAttributesGetDeviceHostnameFunction::
ExtensionFunction::ResponseAction
EnterpriseDeviceAttributesGetDeviceHostnameFunction::Run() {
std::string hostname;
- if (IsPermittedToGetDeviceAttributes(browser_context())) {
+ if (CanGetDeviceAttributesForBrowserContext(browser_context())) {
hostname = g_browser_process->platform_part()
->browser_policy_connector_chromeos()
->GetHostnameHandler()
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 0974be24255..33d41d1169b 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
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_DEVICE_ATTRIBUTES_ENTERPRISE_DEVICE_ATTRIBUTES_API_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/enterprise_device_attributes/enterprise_device_attributes_apitest.cc b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
index 0309f441857..cfbdae447b1 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
@@ -2,38 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <memory>
-
-#include "base/bind.h"
-#include "base/json/json_writer.h"
-#include "base/path_service.h"
-#include "base/task/post_task.h"
+#include "base/files/file_path.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
-#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
-#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
+#include "chrome/browser/chromeos/policy/device_policy_builder.h"
+#include "chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h"
#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/policy_test_utils.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
#include "chromeos/system/fake_statistics_provider.h"
#include "chromeos/system/statistics_provider.h"
-#include "chromeos/tpm/stub_install_attributes.h"
-#include "components/account_id/account_id.h"
-#include "components/policy/core/common/cloud/device_management_service.h"
-#include "components/policy/core/common/mock_configuration_policy_provider.h"
-#include "components/prefs/pref_service.h"
#include "components/user_manager/user_manager.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
-#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/extension_registry.h"
-#include "extensions/test/result_catcher.h"
+#include "url/gurl.h"
namespace {
@@ -42,30 +25,10 @@ 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";
-constexpr char kAffiliatedUserEmail[] = "user@example.com";
-constexpr char kAffiliatedUserGaiaId[] = "1029384756";
-constexpr char kAffiliationID[] = "some-affiliation-id";
-constexpr char kAnotherAffiliationID[] = "another-affiliation-id";
-
-// The managed_storage extension has a key defined in its manifest, so that
-// its extension ID is well-known and the policy system can push policies for
-// the extension.
constexpr char kTestExtensionID[] = "nbiliclbejdndfpchgkbmfoppjplbdok";
-
-struct Params {
- explicit Params(bool affiliated) : affiliated(affiliated) {}
- bool affiliated;
-};
-
-// Must be a valid test name (no spaces etc.). Makes the test show up as e.g.
-// AffiliationCheck/U.A.B.T.Affiliated/NotAffiliated_NotActiveDirectory
-std::string PrintParam(testing::TestParamInfo<Params> param_info) {
- return base::StringPrintf("%sAffiliated",
- param_info.param.affiliated ? "" : "Not");
-}
+constexpr char kUpdateManifestPath[] =
+ "/extensions/api_test/enterprise_device_attributes/update_manifest.xml";
base::Value BuildCustomArg(const std::string& expected_directory_device_id,
const std::string& expected_serial_number,
@@ -89,49 +52,21 @@ base::Value BuildCustomArg(const std::string& expected_directory_device_id,
namespace extensions {
class EnterpriseDeviceAttributesTest
- : public ExtensionApiTest,
- public ::testing::WithParamInterface<Params> {
+ : public ForceInstalledAffiliatedExtensionApiTest,
+ public ::testing::WithParamInterface<bool> {
public:
- EnterpriseDeviceAttributesTest() {
+ EnterpriseDeviceAttributesTest()
+ : ForceInstalledAffiliatedExtensionApiTest(GetParam()) {
fake_statistics_provider_.SetMachineStatistic(
chromeos::system::kSerialNumberKeyForTest, kSerialNumber);
- set_exit_when_last_browser_closes(false);
- set_chromeos_user_ = false;
}
protected:
- // ExtensionApiTest
- void SetUpCommandLine(base::CommandLine* command_line) override {
- ExtensionApiTest::SetUpCommandLine(command_line);
- policy::AffiliationTestHelper::AppendCommandLineSwitchesForLoginManager(
- command_line);
- }
-
+ // ForceInstalledAffiliatedExtensionApiTest
void SetUpInProcessBrowserTestFixture() override {
- ExtensionApiTest::SetUpInProcessBrowserTestFixture();
-
- chromeos::SessionManagerClient::InitializeFakeInMemory();
- policy::AffiliationTestHelper affiliation_helper =
- policy::AffiliationTestHelper::CreateForCloud(
- chromeos::FakeSessionManagerClient::Get());
+ ForceInstalledAffiliatedExtensionApiTest::
+ SetUpInProcessBrowserTestFixture();
- std::set<std::string> device_affiliation_ids;
- device_affiliation_ids.insert(kAffiliationID);
- ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
- &test_helper_, device_affiliation_ids));
- test_helper_.InstallOwnerKey();
-
- std::set<std::string> user_affiliation_ids;
- if (GetParam().affiliated) {
- user_affiliation_ids.insert(kAffiliationID);
- } else {
- user_affiliation_ids.insert(kAnotherAffiliationID);
- }
- policy::UserPolicyBuilder user_policy;
- ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
- &user_policy, affiliated_account_id_, user_affiliation_ids));
-
- test_helper_.InstallOwnerKey();
// Init the device policy.
policy::DevicePolicyBuilder* device_policy = test_helper_.device_policy();
device_policy->SetDefaultSigningKey();
@@ -146,67 +81,9 @@ class EnterpriseDeviceAttributesTest
chromeos::FakeSessionManagerClient::Get()->set_device_policy(
device_policy->GetBlob());
chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
-
- // Init the user policy provider.
- EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
- .WillRepeatedly(testing::Return(true));
- policy_provider_.SetAutoRefresh();
- policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
- &policy_provider_);
-
- // Set retry delay to prevent timeouts.
- policy::DeviceManagementService::SetRetryDelayForTesting(0);
}
- void SetUpOnMainThread() override {
- const base::ListValue* users =
- g_browser_process->local_state()->GetList("LoggedInUsers");
- if (!users->empty())
- policy::AffiliationTestHelper::LoginUser(affiliated_account_id_);
-
- ExtensionApiTest::SetUpOnMainThread();
- }
-
- // Load |page_url| in |browser| and wait for PASSED or FAILED notification.
- // The functionality of this function is reduced functionality of
- // RunExtensionSubtest(), but we don't use it here because it requires
- // function InProcessBrowserTest::browser() to return non-NULL pointer.
- // Unfortunately it returns the value which is set in constructor and can't be
- // modified. Because on login flow there is no browser, the function
- // InProcessBrowserTest::browser() always returns NULL. Besides this we need
- // only very little functionality from RunExtensionSubtest(). Thus so that
- // don't make RunExtensionSubtest() to complex we just introduce a new
- // function.
- bool TestExtension(Browser* browser,
- const std::string& page_url,
- const base::Value& custom_arg_value) {
- DCHECK(!page_url.empty()) << "page_url cannot be empty";
-
- std::string custom_arg;
- base::JSONWriter::Write(custom_arg_value, &custom_arg);
- SetCustomArg(custom_arg);
-
- extensions::ResultCatcher catcher;
- ui_test_utils::NavigateToURL(browser, GURL(page_url));
-
- if (!catcher.GetNextResult()) {
- message_ = catcher.message();
- return false;
- }
- return true;
- }
-
- const AccountId affiliated_account_id_ =
- AccountId::FromUserEmailGaiaId(kAffiliatedUserEmail,
- kAffiliatedUserGaiaId);
-
- policy::MockConfigurationPolicyProvider policy_provider_;
-
private:
- chromeos::ScopedStubInstallAttributes test_install_attributes_{
- chromeos::StubInstallAttributes::CreateCloudManaged("fake-domain",
- "fake-id")};
- policy::DevicePolicyCrosTestHelper test_helper_;
chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
};
@@ -215,36 +92,33 @@ IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, PRE_Success) {
}
IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, Success) {
- policy_test_utils::SetUpEmbeddedTestServer(embedded_test_server());
- ASSERT_TRUE(embedded_test_server()->Start());
- policy_test_utils::SetExtensionInstallForcelistPolicy(
- kTestExtensionID, embedded_test_server()->GetURL(kUpdateManifestPath),
- profile(), &policy_provider_);
+ const bool is_affiliated = GetParam();
+ EXPECT_EQ(is_affiliated, user_manager::UserManager::Get()
+ ->FindUser(affiliated_account_id_)
+ ->IsAffiliated());
- EXPECT_EQ(GetParam().affiliated, user_manager::UserManager::Get()
- ->FindUser(affiliated_account_id_)
- ->IsAffiliated());
+ const Extension* extension =
+ ForceInstallExtension(kTestExtensionID, kUpdateManifestPath);
+ const GURL test_url = extension->GetResourceURL("basic.html");
// Device attributes are available only for affiliated user.
- std::string expected_directory_device_id =
- GetParam().affiliated ? kDeviceId : "";
- std::string expected_serial_number =
- GetParam().affiliated ? kSerialNumber : "";
- std::string expected_asset_id = GetParam().affiliated ? kAssetId : "";
+ std::string expected_directory_device_id = is_affiliated ? kDeviceId : "";
+ std::string expected_serial_number = is_affiliated ? kSerialNumber : "";
+ std::string expected_asset_id = is_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_hostname)))
- << message_;
+ is_affiliated ? kAnnotatedLocation : "";
+ std::string expected_hostname = is_affiliated ? kHostname : "";
+ TestExtension(CreateBrowser(profile()), test_url,
+ BuildCustomArg(expected_directory_device_id,
+ expected_serial_number, expected_asset_id,
+ expected_annotated_location, expected_hostname));
}
+// Both cases of affiliated and non-affiliated users are tested.
+INSTANTIATE_TEST_SUITE_P(AffiliationCheck,
+ EnterpriseDeviceAttributesTest,
+ ::testing::Bool());
+
// Ensure that extensions that are not pre-installed by policy throw an install
// warning if they request the enterprise.deviceAttributes permission in the
// manifest and that such extensions don't see the
@@ -258,10 +132,10 @@ IN_PROC_BROWSER_TEST_F(
base::FilePath extension_path =
test_data_dir_.AppendASCII("enterprise_device_attributes");
- extensions::ExtensionRegistry* registry =
- extensions::ExtensionRegistry::Get(profile());
const extensions::Extension* extension =
- GetExtensionByPath(registry->enabled_extensions(), extension_path);
+ extensions::ExtensionRegistry::Get(profile())
+ ->enabled_extensions()
+ .GetByID(kTestExtensionID);
ASSERT_FALSE(extension->install_warnings().empty());
EXPECT_EQ(
"'enterprise.deviceAttributes' is not allowed for specified install "
@@ -269,10 +143,4 @@ IN_PROC_BROWSER_TEST_F(
extension->install_warnings()[0].message);
}
-// Both cases of affiliated and non-affiliated on the device user are tested.
-INSTANTIATE_TEST_SUITE_P(AffiliationCheck,
- EnterpriseDeviceAttributesTest,
- ::testing::Values(Params(true /* affiliated */),
- Params(false /* affiliated */)),
- PrintParam);
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/OWNERS b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/OWNERS
new file mode 100644
index 00000000000..d11193dcf55
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/OWNERS
@@ -0,0 +1,3 @@
+hendrich@chromium.org
+
+# COMPONENT: Enterprise
diff --git a/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.cc b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.cc
new file mode 100644
index 00000000000..981d40da62b
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.cc
@@ -0,0 +1,90 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.h"
+
+#include "base/values.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/api/enterprise_networking_attributes.h"
+#include "chromeos/network/device_state.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_util.h"
+#include "components/user_manager/user.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+
+namespace extensions {
+
+namespace {
+
+const char kErrorUserNotAffiliated[] =
+ "Network attributes can only be read by an affiliated user.";
+const char kErrorNetworkNotConnected[] =
+ "Device is not connected to a network.";
+
+// Checks for the current browser context if the user is affiliated or belongs
+// to the sign-in profile.
+bool CanGetNetworkAttributesForBrowserContext(
+ content::BrowserContext* context) {
+ const Profile* profile = Profile::FromBrowserContext(context);
+
+ if (chromeos::ProfileHelper::IsSigninProfile(profile))
+ return true;
+
+ if (!profile->IsRegularProfile())
+ return false;
+
+ const user_manager::User* user =
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
+ return user->IsAffiliated();
+}
+
+} // namespace
+
+EnterpriseNetworkingAttributesGetNetworkDetailsFunction::
+ EnterpriseNetworkingAttributesGetNetworkDetailsFunction() = default;
+
+EnterpriseNetworkingAttributesGetNetworkDetailsFunction::
+ ~EnterpriseNetworkingAttributesGetNetworkDetailsFunction() = default;
+
+ExtensionFunction::ResponseAction
+EnterpriseNetworkingAttributesGetNetworkDetailsFunction::Run() {
+ if (!CanGetNetworkAttributesForBrowserContext(browser_context())) {
+ return RespondNow(Error(kErrorUserNotAffiliated));
+ }
+
+ chromeos::NetworkStateHandler* network_state_handler =
+ chromeos::NetworkHandler::Get()->network_state_handler();
+ const chromeos::NetworkState* network =
+ network_state_handler->DefaultNetwork();
+ if (!network) {
+ // Not connected to a network.
+ return RespondNow(Error(kErrorNetworkNotConnected));
+ }
+ const chromeos::DeviceState* device =
+ network_state_handler->GetDeviceState(network->device_path());
+ if (!device) {
+ return RespondNow(Error(kErrorNetworkNotConnected));
+ }
+
+ const std::string mac_address =
+ chromeos::network_util::FormattedMacAddress(device->mac_address());
+ const std::string ipv4_address = device->GetIpAddressByType(shill::kTypeIPv4);
+ const std::string ipv6_address = device->GetIpAddressByType(shill::kTypeIPv6);
+
+ api::enterprise_networking_attributes::NetworkDetails details;
+ details.mac_address = mac_address;
+ if (!ipv4_address.empty()) {
+ details.ipv4 = std::make_unique<std::string>(ipv4_address);
+ }
+ if (!ipv6_address.empty()) {
+ details.ipv6 = std::make_unique<std::string>(ipv6_address);
+ }
+
+ return RespondNow(OneArgument(details.ToValue()));
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.h b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.h
new file mode 100644
index 00000000000..85f23e82822
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_api.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_NETWORKING_ATTRIBUTES_ENTERPRISE_NETWORKING_ATTRIBUTES_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_NETWORKING_ATTRIBUTES_ENTERPRISE_NETWORKING_ATTRIBUTES_API_H_
+
+#include "extensions/browser/extension_function.h"
+#include "extensions/browser/extension_function_histogram_value.h"
+
+namespace extensions {
+
+class EnterpriseNetworkingAttributesGetNetworkDetailsFunction
+ : public ExtensionFunction {
+ public:
+ EnterpriseNetworkingAttributesGetNetworkDetailsFunction();
+
+ protected:
+ ~EnterpriseNetworkingAttributesGetNetworkDetailsFunction() override;
+
+ ResponseAction Run() override;
+
+ private:
+ DECLARE_EXTENSION_FUNCTION(
+ "enterprise.networkingAttributes.getNetworkDetails",
+ ENTERPRISE_NETWORKINGATTRIBUTES_GETNETWORKDETAILS)
+};
+
+} // namespace extensions
+#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_NETWORKING_ATTRIBUTES_ENTERPRISE_NETWORKING_ATTRIBUTES_API_H_
diff --git a/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc
new file mode 100644
index 00000000000..a3c7706efdc
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_networking_attributes/enterprise_networking_attributes_apitest.cc
@@ -0,0 +1,210 @@
+// 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 "base/values.h"
+#include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
+#include "chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
+#include "content/public/test/browser_test.h"
+#include "url/gurl.h"
+
+namespace {
+
+const char kErrorUserNotAffiliated[] =
+ "Network attributes can only be read by an affiliated user.";
+const char kErrorNetworkNotConnected[] =
+ "Device is not connected to a network.";
+
+constexpr char kTestExtensionID[] = "pkhdjpcjgonhlomdjmnddhbfpgkdhgle";
+constexpr char kUpdateManifestPath[] =
+ "/extensions/api_test/enterprise_networking_attributes/update_manifest.xml";
+
+constexpr char kMacAddress[] = "0123456789AB";
+constexpr char kFormattedMacAddress[] = "01:23:45:67:89:AB";
+constexpr char kIpv4Address[] = "192.168.0.42";
+constexpr char kIpv6Address[] = "fe80::1262:d0ff:fef5:e8a9";
+
+constexpr char kWifiDevicePath[] = "/device/stub_wifi";
+constexpr char kWifiServicePath[] = "/service/stub_wifi";
+constexpr char kWifiIPConfigV4Path[] = "/ipconfig/stub_wifi-ipv4";
+constexpr char kWifiIPConfigV6Path[] = "/ipconfig/stub_wifi-ipv6";
+
+base::Value BuildCustomArgForSuccess(const std::string& expected_mac_address,
+ const std::string& expected_ipv4_address,
+ const std::string& expected_ipv6_address) {
+ base::Value network_details(base::Value::Type::DICTIONARY);
+ network_details.SetKey("macAddress", base::Value(expected_mac_address));
+ network_details.SetKey("ipv4", base::Value(expected_ipv4_address));
+ network_details.SetKey("ipv6", base::Value(expected_ipv6_address));
+
+ base::Value custom_arg(base::Value::Type::DICTIONARY);
+ custom_arg.SetKey("testName", base::Value("success"));
+ custom_arg.SetKey("expectedResult", std::move(network_details));
+ return custom_arg;
+}
+
+base::Value BuildCustomArgForFailure(
+ const std::string& expected_error_message) {
+ base::Value custom_arg(base::Value::Type::DICTIONARY);
+ custom_arg.SetKey("testName", base::Value("failure"));
+ custom_arg.SetKey("expectedErrorMessage",
+ base::Value(expected_error_message));
+ return custom_arg;
+}
+
+} // namespace
+
+namespace extensions {
+
+class EnterpriseNetworkingAttributesTest
+ : public ForceInstalledAffiliatedExtensionApiTest,
+ public ::testing::WithParamInterface<bool> {
+ public:
+ EnterpriseNetworkingAttributesTest()
+ : ForceInstalledAffiliatedExtensionApiTest(GetParam()) {}
+
+ void SetupDisconnectedNetwork() {
+ chromeos::ShillDeviceClient::TestInterface* shill_device_client =
+ chromeos::DBusThreadManager::Get()
+ ->GetShillDeviceClient()
+ ->GetTestInterface();
+ chromeos::ShillIPConfigClient::TestInterface* shill_ipconfig_client =
+ chromeos::DBusThreadManager::Get()
+ ->GetShillIPConfigClient()
+ ->GetTestInterface();
+ chromeos::ShillServiceClient::TestInterface* shill_service_client =
+ chromeos::DBusThreadManager::Get()
+ ->GetShillServiceClient()
+ ->GetTestInterface();
+ chromeos::ShillProfileClient::TestInterface* shill_profile_client =
+ chromeos::DBusThreadManager::Get()
+ ->GetShillProfileClient()
+ ->GetTestInterface();
+
+ shill_service_client->ClearServices();
+ shill_device_client->ClearDevices();
+
+ shill_device_client->AddDevice(kWifiDevicePath, shill::kTypeWifi,
+ "stub_wifi_device");
+ shill_device_client->SetDeviceProperty(
+ kWifiDevicePath, shill::kAddressProperty, base::Value(kMacAddress),
+ /* notify_changed= */ false);
+
+ base::DictionaryValue ipconfig_v4_dictionary;
+ ipconfig_v4_dictionary.SetKey(shill::kAddressProperty,
+ base::Value(kIpv4Address));
+ ipconfig_v4_dictionary.SetKey(shill::kMethodProperty,
+ base::Value(shill::kTypeIPv4));
+ shill_ipconfig_client->AddIPConfig(kWifiIPConfigV4Path,
+ ipconfig_v4_dictionary);
+
+ base::DictionaryValue ipconfig_v6_dictionary;
+ ipconfig_v6_dictionary.SetKey(shill::kAddressProperty,
+ base::Value(kIpv6Address));
+ ipconfig_v6_dictionary.SetKey(shill::kMethodProperty,
+ base::Value(shill::kTypeIPv6));
+ shill_ipconfig_client->AddIPConfig(kWifiIPConfigV6Path,
+ ipconfig_v6_dictionary);
+
+ base::ListValue ip_configs;
+ ip_configs.AppendString(kWifiIPConfigV4Path);
+ ip_configs.AppendString(kWifiIPConfigV6Path);
+ shill_device_client->SetDeviceProperty(
+ kWifiDevicePath, shill::kIPConfigsProperty, ip_configs,
+ /*notify_changed=*/false);
+
+ shill_service_client->AddService(kWifiServicePath, "wifi_guid",
+ "wifi_network_name", shill::kTypeWifi,
+ shill::kStateIdle, /* visible= */ true);
+ shill_service_client->SetServiceProperty(
+ kWifiServicePath, shill::kConnectableProperty, base::Value(true));
+
+ shill_profile_client->AddService(
+ chromeos::ShillProfileClient::GetSharedProfilePath(), kWifiServicePath);
+
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void ConnectNetwork() {
+ chromeos::ShillServiceClient::TestInterface* shill_service_client =
+ chromeos::DBusThreadManager::Get()
+ ->GetShillServiceClient()
+ ->GetTestInterface();
+ shill_service_client->SetServiceProperty(kWifiServicePath,
+ shill::kStateProperty,
+ base::Value(shill::kStateOnline));
+ base::RunLoop().RunUntilIdle();
+ }
+};
+
+IN_PROC_BROWSER_TEST_P(EnterpriseNetworkingAttributesTest,
+ PRE_GetNetworkDetails) {
+ policy::AffiliationTestHelper::PreLoginUser(affiliated_account_id_);
+}
+
+IN_PROC_BROWSER_TEST_P(EnterpriseNetworkingAttributesTest, GetNetworkDetails) {
+ const bool is_affiliated = GetParam();
+ EXPECT_EQ(is_affiliated, user_manager::UserManager::Get()
+ ->FindUser(affiliated_account_id_)
+ ->IsAffiliated());
+
+ const Extension* extension =
+ ForceInstallExtension(kTestExtensionID, kUpdateManifestPath);
+ SetupDisconnectedNetwork();
+ const GURL test_url = extension->GetResourceURL("test.html");
+
+ // Run test without connected network.
+ base::Value custom_arg_disconnected =
+ is_affiliated ? BuildCustomArgForFailure(kErrorNetworkNotConnected)
+ : BuildCustomArgForFailure(kErrorUserNotAffiliated);
+ TestExtension(CreateBrowser(profile()), test_url,
+ std::move(custom_arg_disconnected));
+
+ // Run test with connected network.
+ ConnectNetwork();
+ base::Value custom_arg_connected =
+ is_affiliated ? BuildCustomArgForSuccess(kFormattedMacAddress,
+ kIpv4Address, kIpv6Address)
+ : BuildCustomArgForFailure(kErrorUserNotAffiliated);
+ TestExtension(CreateBrowser(profile()), test_url,
+ std::move(custom_arg_connected));
+}
+
+// Both cases of affiliated and non-affiliated users are tested.
+INSTANTIATE_TEST_SUITE_P(AffiliationCheck,
+ EnterpriseNetworkingAttributesTest,
+ ::testing::Bool());
+
+// Ensure that extensions that are not pre-installed by policy throw an install
+// warning if they request the enterprise.networkingAttributes permission in the
+// manifest and that such extensions don't see the
+// chrome.enterprise.networkingAttributes namespace.
+IN_PROC_BROWSER_TEST_F(
+ ExtensionApiTest,
+ EnterpriseNetworkingAttributesIsRestrictedToPolicyExtension) {
+ ASSERT_TRUE(RunExtensionSubtest("enterprise_networking_attributes",
+ "api_not_available.html",
+ kFlagIgnoreManifestWarnings, kFlagNone));
+
+ base::FilePath extension_path =
+ test_data_dir_.AppendASCII("enterprise_networking_attributes");
+ const extensions::Extension* extension =
+ extensions::ExtensionRegistry::Get(profile())
+ ->enabled_extensions()
+ .GetByID(kTestExtensionID);
+ ASSERT_FALSE(extension->install_warnings().empty());
+ EXPECT_EQ(
+ "'enterprise.networkingAttributes' is not allowed for specified install "
+ "location.",
+ extension->install_warnings()[0].message);
+}
+
+} // namespace extensions
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 f3a5cfa7d60..26dbef23d59 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
@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "base/values.h"
#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h"
#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h"
@@ -300,7 +299,7 @@ EnterprisePlatformKeysChallengeMachineKeyFunction::Run() {
chromeos::attestation::KEY_DEVICE, scoped_refptr<ExtensionFunction>(this),
std::move(callback), StringFromVector(params->challenge),
params->register_key ? *params->register_key : false);
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, std::move(task));
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(task));
return RespondLater();
}
@@ -334,7 +333,7 @@ EnterprisePlatformKeysChallengeUserKeyFunction::Run() {
chromeos::attestation::KEY_USER, scoped_refptr<ExtensionFunction>(this),
std::move(callback), StringFromVector(params->challenge),
params->register_key);
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, std::move(task));
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(task));
return RespondLater();
}
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 3f946e23d57..4cdb396d069 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
@@ -25,6 +25,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_nss_types.h"
#include "crypto/scoped_test_system_nss_key_slot.h"
#include "extensions/browser/extension_registry.h"
#include "net/cert/nss_cert_database.h"
@@ -117,17 +118,17 @@ void ImportPrivateKeyPKCS8ToSlot(const unsigned char* pkcs8_der,
const_cast<unsigned char*>(pkcs8_der),
pkcs8_der_size};
- SECKEYPrivateKey* seckey = NULL;
- ASSERT_EQ(SECSuccess,
- PK11_ImportDERPrivateKeyInfoAndReturnKey(slot,
- &pki_der_user,
- NULL, // nickname
- NULL, // publicValue
- true, // isPerm
- true, // isPrivate
- KU_ALL, // usage
- &seckey,
- NULL));
+ SECKEYPrivateKey* seckey_raw = nullptr;
+ ASSERT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey(
+ slot, &pki_der_user,
+ /*nickname=*/nullptr,
+ /*publicValue=*/nullptr,
+ /*isPerm=*/true,
+ /*isPrivate=*/true,
+ /*usage=*/KU_ALL, &seckey_raw, /*wincx=*/nullptr));
+
+ // Make sure that the memory allocated for the key gets freed.
+ crypto::ScopedSECKEYPrivateKey seckey(seckey_raw);
}
// The managed_storage extension has a key defined in its manifest, so that
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 275d148f325..6051e3a45ea 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
@@ -6,7 +6,6 @@
#include "base/base64.h"
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "base/values.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
@@ -116,7 +115,7 @@ EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::Run() {
chromeos::attestation::KEY_DEVICE, scoped_refptr<ExtensionFunction>(this),
std::move(callback), challenge,
/*register_key=*/false);
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, std::move(task));
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(task));
return RespondLater();
}
@@ -161,7 +160,7 @@ EnterprisePlatformKeysPrivateChallengeUserKeyFunction::Run() {
&EPKPChallengeKey::Run, base::Unretained(&impl_),
chromeos::attestation::KEY_USER, scoped_refptr<ExtensionFunction>(this),
std::move(callback), challenge, params->register_key);
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, std::move(task));
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(task));
return RespondLater();
}
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 36d3139b284..caa30811789 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
@@ -242,87 +242,91 @@ const wchar_t kDefaultRegistryPath[] =
L"SOFTWARE\\Google\\Endpoint Verification";
const wchar_t kValueName[] = L"Safe Storage";
-std::string ReadEncryptedSecret() {
+LONG ReadEncryptedSecret(std::string* encrypted_secret) {
base::win::RegKey key;
DWORD kMaxRawSize = 1024;
char raw_data[kMaxRawSize];
DWORD raw_data_size = kMaxRawSize;
DWORD raw_type;
- if (ERROR_SUCCESS !=
- key.Open(HKEY_CURRENT_USER, kDefaultRegistryPath, KEY_READ) ||
- ERROR_SUCCESS !=
- key.ReadValue(kValueName, raw_data, &raw_data_size, &raw_type) ||
- raw_type != REG_BINARY) {
- return std::string();
+ encrypted_secret->clear();
+ LONG result = key.Open(HKEY_CURRENT_USER, kDefaultRegistryPath, KEY_READ);
+ if (result != ERROR_SUCCESS)
+ return result;
+ result = key.ReadValue(kValueName, raw_data, &raw_data_size, &raw_type);
+ if (result != ERROR_SUCCESS)
+ return result;
+ if (raw_type != REG_BINARY) {
+ key.DeleteValue(kValueName);
+ return ERROR_INVALID_DATATYPE;
}
- std::string encrypted_secret;
- encrypted_secret.insert(0, raw_data, raw_data_size);
- return encrypted_secret;
+ encrypted_secret->insert(0, raw_data, raw_data_size);
+ return ERROR_SUCCESS;
}
// Encrypts the |plaintext| and write the result in |cyphertext|. This
// function was taken from os_crypt/os_crypt_win.cc (Chromium).
-bool EncryptString(const std::string& plaintext, std::string* ciphertext) {
+LONG EncryptString(const std::string& plaintext, std::string* ciphertext) {
DATA_BLOB input;
input.pbData =
const_cast<BYTE*>(reinterpret_cast<const BYTE*>(plaintext.data()));
input.cbData = static_cast<DWORD>(plaintext.length());
+ ciphertext->clear();
DATA_BLOB output;
BOOL result = ::CryptProtectData(&input, nullptr, nullptr, nullptr, nullptr,
0, &output);
if (!result)
- return false;
+ return ::GetLastError();
// this does a copy
ciphertext->assign(reinterpret_cast<std::string::value_type*>(output.pbData),
output.cbData);
LocalFree(output.pbData);
- return true;
+ return ERROR_SUCCESS;
}
// Decrypts the |cyphertext| and write the result in |plaintext|. This
// function was taken from os_crypt/os_crypt_win.cc (Chromium).
-bool DecryptString(const std::string& ciphertext, std::string* plaintext) {
+LONG DecryptString(const std::string& ciphertext, std::string* plaintext) {
DATA_BLOB input;
input.pbData =
const_cast<BYTE*>(reinterpret_cast<const BYTE*>(ciphertext.data()));
input.cbData = static_cast<DWORD>(ciphertext.length());
+ plaintext->clear();
DATA_BLOB output;
BOOL result =
::CryptUnprotectData(&input, nullptr, nullptr, nullptr, nullptr, 0,
&output);
if (!result)
- return false;
+ return ::GetLastError();
plaintext->assign(reinterpret_cast<char*>(output.pbData), output.cbData);
LocalFree(output.pbData);
- return true;
+ return ERROR_SUCCESS;
}
-std::string CreateRandomSecret() {
+LONG CreateRandomSecret(std::string* secret) {
// Generate a password with 128 bits of randomness.
const int kBytes = 128 / 8;
- std::string secret;
- base::Base64Encode(base::RandBytesAsString(kBytes), &secret);
+ std::string generated_secret;
+ base::Base64Encode(base::RandBytesAsString(kBytes), &generated_secret);
std::string encrypted_secret;
- if (!EncryptString(secret, &encrypted_secret)) {
- return std::string();
- }
+ LONG result = EncryptString(generated_secret, &encrypted_secret);
+ if (result != ERROR_SUCCESS)
+ return result;
base::win::RegKey key;
- if (ERROR_SUCCESS !=
- key.Create(HKEY_CURRENT_USER, kDefaultRegistryPath, KEY_WRITE)) {
- return std::string();
- }
- if (ERROR_SUCCESS != key.WriteValue(kValueName, encrypted_secret.data(),
- encrypted_secret.size(), REG_BINARY)) {
- return std::string();
- }
- return secret;
+ result = key.Create(HKEY_CURRENT_USER, kDefaultRegistryPath, KEY_WRITE);
+ if (result != ERROR_SUCCESS)
+ return result;
+ result = key.WriteValue(kValueName, encrypted_secret.data(),
+ encrypted_secret.size(), REG_BINARY);
+ if (result == ERROR_SUCCESS)
+ *secret = generated_secret;
+ return result;
}
#elif defined(OS_MACOSX) // defined(OS_WIN)
@@ -330,7 +334,8 @@ std::string CreateRandomSecret() {
constexpr char kServiceName[] = "Endpoint Verification Safe Storage";
constexpr char kAccountName[] = "Endpoint Verification";
-std::string AddRandomPasswordToKeychain(const crypto::AppleKeychain& keychain) {
+OSStatus AddRandomPasswordToKeychain(const crypto::AppleKeychain& keychain,
+ std::string* secret) {
// Generate a password with 128 bits of randomness.
const int kBytes = 128 / 8;
std::string password;
@@ -342,32 +347,29 @@ std::string AddRandomPasswordToKeychain(const crypto::AppleKeychain& keychain) {
strlen(kServiceName), kServiceName, strlen(kAccountName), kAccountName,
password.size(), password_data, nullptr);
- if (error != noErr)
- return std::string();
- return password;
+ if (error == noErr)
+ *secret = password;
+ else
+ secret->clear();
+ return error;
}
-std::string ReadEncryptedSecret() {
+OSStatus ReadEncryptedSecret(std::string* secret) {
UInt32 password_length = 0;
void* password_data = nullptr;
crypto::AppleKeychain keychain;
+ secret->clear();
OSStatus error = keychain.FindGenericPassword(
strlen(kServiceName), kServiceName, strlen(kAccountName), kAccountName,
&password_length, &password_data, nullptr);
if (error == noErr) {
- std::string password =
- std::string(static_cast<char*>(password_data), password_length);
+ *secret = std::string(static_cast<char*>(password_data), password_length);
keychain.ItemFreeContent(password_data);
- return password;
+ } else if (error == errSecItemNotFound) {
+ error = AddRandomPasswordToKeychain(keychain, secret);
}
-
- if (error == errSecItemNotFound) {
- std::string password = AddRandomPasswordToKeychain(keychain);
- return password;
- }
-
- return std::string();
+ return error;
}
#endif // defined(OS_MACOSX)
@@ -483,9 +485,9 @@ void StoreDeviceData(const std::string& id,
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);
+ success = base::DeleteFile(data_file);
if (base::IsDirectoryEmpty(data_file.DirName()))
- base::DeleteFile(data_file.DirName(), false);
+ base::DeleteFile(data_file.DirName());
}
std::move(callback).Run(success);
@@ -493,17 +495,19 @@ void StoreDeviceData(const std::string& id,
void RetrieveDeviceData(
const std::string& id,
- base::OnceCallback<void(const std::string&, bool)> callback) {
+ base::OnceCallback<void(const std::string&, RetrieveDeviceDataStatus)>
+ callback) {
base::FilePath data_file = GetEndpointVerificationDir();
if (data_file.empty()) {
- std::move(callback).Run("", false);
+ std::move(callback).Run("",
+ RetrieveDeviceDataStatus::kDataDirectoryUnknown);
return;
}
data_file = data_file.AppendASCII(id);
// 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);
+ std::move(callback).Run("", RetrieveDeviceDataStatus::kDataRecordNotFound);
return;
}
std::string data;
@@ -512,32 +516,27 @@ void RetrieveDeviceData(
// Chrome.
bool result = base::ReadFileToString(data_file, &data);
- std::move(callback).Run(data, result);
+ std::move(callback).Run(
+ data, result ? RetrieveDeviceDataStatus::kSuccess
+ : RetrieveDeviceDataStatus::kDataRecordRetrievalError);
}
void RetrieveDeviceSecret(
- base::OnceCallback<void(const std::string&, bool)> callback) {
+ base::OnceCallback<void(const std::string&, long int)> callback) {
std::string secret;
#if defined(OS_WIN)
- std::string encrypted_secret = ReadEncryptedSecret();
- if (encrypted_secret.empty()) {
- secret = CreateRandomSecret();
- std::move(callback).Run(secret, !secret.empty());
- return;
- }
- if (!DecryptString(encrypted_secret, &secret)) {
- std::move(callback).Run("", false);
- return;
- }
+ std::string encrypted_secret;
+ LONG result = ReadEncryptedSecret(&encrypted_secret);
+ if (result == ERROR_FILE_NOT_FOUND)
+ result = CreateRandomSecret(&secret);
+ else if (result == ERROR_SUCCESS)
+ result = DecryptString(encrypted_secret, &secret);
#elif defined(OS_MACOSX)
- secret = ReadEncryptedSecret();
- if (secret.empty()) {
- std::move(callback).Run(secret, false);
- return;
- }
-
+ OSStatus result = ReadEncryptedSecret(&secret);
+#else
+ long int result = -1; // Anything but 0 is a failure.
#endif
- std::move(callback).Run(secret, true);
+ std::move(callback).Run(secret, static_cast<long int>(result));
}
} // namespace extensions
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 fd6d229ea24..764db67ed36 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
@@ -21,6 +21,18 @@ class DictionaryValue;
namespace extensions {
+// Result of the retrieve operation
+enum class RetrieveDeviceDataStatus {
+ // The operation finished successfully.
+ kSuccess,
+ // The path for device data can not be identified.
+ kDataDirectoryUnknown,
+ // The requested device data record does not exist.
+ kDataRecordNotFound,
+ // The requested device data record can not be read.
+ kDataRecordRetrievalError,
+};
+
// Transfer the input from Json file to protobuf. Return nullptr if the input
// is not valid.
std::unique_ptr<enterprise_management::ChromeDesktopReportRequest>
@@ -40,7 +52,8 @@ void StoreDeviceData(const std::string& id,
// completion with the data retrieved if the second parameter is true.
void RetrieveDeviceData(
const std::string& id,
- base::OnceCallback<void(const std::string&, bool)> callback);
+ base::OnceCallback<void(const std::string&, RetrieveDeviceDataStatus)>
+ callback);
// Get the Endpoint Verification secret (symmetric key) for this system. If no
// password exists in the Registry then one is generated, stored in the
@@ -48,7 +61,7 @@ void RetrieveDeviceData(
// If one exists then it is fetched from the Registry and returned.
// If an error occurs then the second parameter is false.
void RetrieveDeviceSecret(
- base::OnceCallback<void(const std::string&, bool)> callback);
+ base::OnceCallback<void(const std::string&, long int)> callback);
} // namespace extensions
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 5ec66328e92..4594ebe731a 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
@@ -16,7 +16,6 @@
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h"
#include "chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/policy/browser_dm_token_storage.h"
@@ -35,6 +34,10 @@ namespace {
void LogReportError(const std::string& reason) {
VLOG(1) << "Enterprise report is not uploaded: " << reason;
}
+void LogReportErrorCode(const std::string& reason, long int code) {
+ VLOG(1) << "Enterprise report is not uploaded: " << reason
+ << " code: " << code;
+}
} // namespace
@@ -48,8 +51,7 @@ const char kEndpointVerificationRetrievalFailed[] =
"Failed to retrieve the endpoint verification data.";
const char kEndpointVerificationStoreFailed[] =
"Failed to store the endpoint verification data.";
-// const char kEndpointVerificationSecretRetrievalFailed[] = "Failed to retrieve
-// the endpoint verification secret.";
+const char kEndpointVerificationSecretRetrievalFailed[] = "%ld";
} // namespace enterprise_reporting
@@ -193,15 +195,17 @@ EnterpriseReportingPrivateGetPersistentSecretFunction::Run() {
void EnterpriseReportingPrivateGetPersistentSecretFunction::OnDataRetrieved(
const std::string& data,
- bool status) {
- if (status) {
+ long int status) {
+ if (status == 0) { // Success.
VLOG(1) << "The Endpoint Verification secret was retrieved.";
Respond(OneArgument(std::make_unique<base::Value>(base::Value::BlobStorage(
reinterpret_cast<const uint8_t*>(data.data()),
reinterpret_cast<const uint8_t*>(data.data() + data.size())))));
} else {
- LogReportError("Endpoint Verification secret retrieval error.");
- Respond(Error(enterprise_reporting::kEndpointVerificationRetrievalFailed));
+ LogReportErrorCode("Endpoint Verification secret retrieval error.", status);
+ Respond(Error(base::StringPrintf(
+ enterprise_reporting::kEndpointVerificationSecretRetrievalFailed,
+ static_cast<long int>(status))));
}
}
@@ -231,15 +235,24 @@ EnterpriseReportingPrivateGetDeviceDataFunction::Run() {
void EnterpriseReportingPrivateGetDeviceDataFunction::OnDataRetrieved(
const std::string& data,
- bool status) {
- if (status) {
- VLOG(1) << "The Endpoint Verification data was retrieved.";
- Respond(OneArgument(std::make_unique<base::Value>(base::Value::BlobStorage(
- reinterpret_cast<const uint8_t*>(data.data()),
- reinterpret_cast<const uint8_t*>(data.data() + data.size())))));
- } else {
- LogReportError("Endpoint Verification data retrieval error.");
- Respond(Error(enterprise_reporting::kEndpointVerificationRetrievalFailed));
+ RetrieveDeviceDataStatus status) {
+ switch (status) {
+ case RetrieveDeviceDataStatus::kSuccess:
+ VLOG(1) << "The Endpoint Verification data was retrieved.";
+ Respond(
+ OneArgument(std::make_unique<base::Value>(base::Value::BlobStorage(
+ reinterpret_cast<const uint8_t*>(data.data()),
+ reinterpret_cast<const uint8_t*>(data.data() + data.size())))));
+ return;
+ case RetrieveDeviceDataStatus::kDataRecordNotFound:
+ VLOG(1) << "The Endpoint Verification data is not present.";
+ Respond(NoArguments());
+ return;
+ default:
+ LogReportErrorCode("Endpoint Verification data retrieval error.",
+ static_cast<long int>(status));
+ Respond(
+ Error(enterprise_reporting::kEndpointVerificationRetrievalFailed));
}
}
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
index c33bfe43276..1778b6c6868 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h"
#include "chrome/common/extensions/api/enterprise_reporting_private.h"
#include "components/policy/core/common/cloud/dm_token.h"
#include "extensions/browser/extension_function.h"
@@ -104,7 +105,7 @@ class EnterpriseReportingPrivateGetPersistentSecretFunction
ExtensionFunction::ResponseAction Run() override;
// Callback once the data was retrieved from the file.
- void OnDataRetrieved(const std::string& data, bool status);
+ void OnDataRetrieved(const std::string& data, long int status);
};
class EnterpriseReportingPrivateGetDeviceDataFunction
@@ -126,7 +127,8 @@ class EnterpriseReportingPrivateGetDeviceDataFunction
ExtensionFunction::ResponseAction Run() override;
// Callback once the data was retrieved from the file.
- void OnDataRetrieved(const std::string& data, bool status);
+ void OnDataRetrieved(const std::string& data,
+ RetrieveDeviceDataStatus status);
};
class EnterpriseReportingPrivateSetDeviceDataFunction
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 325ef19e167..76dd8a810e4 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
@@ -81,6 +81,7 @@ class EnterpriseReportingPrivateUploadChromeDesktopReportTest
private:
network::TestURLLoaderFactory test_url_loader_factory_;
+ policy::FakeBrowserDMTokenStorage storage_;
DISALLOW_COPY_AND_ASSIGN(
EnterpriseReportingPrivateUploadChromeDesktopReportTest);
@@ -204,7 +205,7 @@ TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, DeviceDataMissing) {
browser(),
extensions::api_test_utils::NONE);
ASSERT_TRUE(function->GetResultList());
- EXPECT_EQ(1u, function->GetResultList()->GetSize());
+ EXPECT_EQ(0u, function->GetResultList()->GetSize());
EXPECT_TRUE(function->GetError().empty());
}
@@ -282,11 +283,8 @@ TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, RetrieveDeviceData) {
std::move(values2), browser(),
extensions::api_test_utils::NONE);
ASSERT_TRUE(get_function2->GetResultList());
- EXPECT_TRUE(get_function2->GetResultList()->Get(0, &single_result));
+ EXPECT_EQ(0u, get_function2->GetResultList()->GetSize());
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.
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 5b236b80e49..69618e22c88 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
@@ -806,13 +806,9 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, CloseBackgroundPage) {
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();
+ void OnExtensionHostDestroyed(ExtensionHost* host) override {
+ ASSERT_TRUE(host_observer_.IsObserving(host));
+ host_observer_.Remove(host);
run_loop_.QuitWhenIdle();
}
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 b2fa34c8b44..573ad4f32f0 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
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/location.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
@@ -240,11 +241,10 @@ void ExtensionActionAPI::Shutdown() {
//
ExtensionActionFunction::ExtensionActionFunction()
- : details_(NULL),
+ : details_(nullptr),
tab_id_(ExtensionAction::kDefaultTabId),
- contents_(NULL),
- extension_action_(NULL) {
-}
+ contents_(nullptr),
+ extension_action_(nullptr) {}
ExtensionActionFunction::~ExtensionActionFunction() {
}
@@ -356,7 +356,26 @@ void ExtensionActionSetIconFunction::SetReportErrorForInvisibleIconForTesting(
ExtensionFunction::ResponseAction
ExtensionActionSetIconFunction::RunExtensionAction() {
- EXTENSION_FUNCTION_VALIDATE(details_);
+ // TODO(devlin): Temporary logging to track down https://crbug.com/1087948.
+ // Remove this (and the redundant `if (!x) { VALIDATE(x); }`) checks after
+ // the bug is fixed.
+ // Don't reorder or remove values.
+ enum class FailureType {
+ kFailedToParseDetails = 0,
+ kFailedToDecodeCanvas = 1,
+ kFailedToUnpickleCanvas = 2,
+ kNoImageDataOrIconIndex = 3,
+ kMaxValue = kNoImageDataOrIconIndex,
+ };
+
+ auto log_set_icon_failure = [](FailureType type) {
+ base::UmaHistogramEnumeration("Extensions.ActionSetIconFailureType", type);
+ };
+
+ if (!details_) {
+ log_set_icon_failure(FailureType::kFailedToParseDetails);
+ EXTENSION_FUNCTION_VALIDATE(details_);
+ }
// setIcon can take a variant argument: either a dictionary of canvas
// ImageData, or an icon index.
@@ -365,8 +384,23 @@ ExtensionActionSetIconFunction::RunExtensionAction() {
if (details_->GetDictionary("imageData", &canvas_set)) {
gfx::ImageSkia icon;
- EXTENSION_FUNCTION_VALIDATE(
- ExtensionAction::ParseIconFromCanvasDictionary(*canvas_set, &icon));
+ ExtensionAction::IconParseResult parse_result =
+ ExtensionAction::ParseIconFromCanvasDictionary(*canvas_set, &icon);
+
+ if (parse_result != ExtensionAction::IconParseResult::kSuccess) {
+ switch (parse_result) {
+ case ExtensionAction::IconParseResult::kDecodeFailure:
+ log_set_icon_failure(FailureType::kFailedToDecodeCanvas);
+ break;
+ case ExtensionAction::IconParseResult::kUnpickleFailure:
+ log_set_icon_failure(FailureType::kFailedToUnpickleCanvas);
+ break;
+ case ExtensionAction::IconParseResult::kSuccess:
+ NOTREACHED();
+ break;
+ }
+ EXTENSION_FUNCTION_VALIDATE(false);
+ }
if (icon.isNull())
return RespondNow(Error("Icon invalid."));
@@ -391,6 +425,7 @@ ExtensionActionSetIconFunction::RunExtensionAction() {
// Obsolete argument: ignore it.
return RespondNow(NoArguments());
} else {
+ log_set_icon_failure(FailureType::kNoImageDataOrIconIndex);
EXTENSION_FUNCTION_VALIDATE(false);
}
NotifyChange();
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 1bddc30de58..1549e17b027 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
@@ -549,24 +549,16 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPICanvasTest, DynamicSetIcon) {
"background": { "scripts": ["background.js"] }
})";
- std::string blue_icon;
- std::string red_icon;
- {
- base::ScopedAllowBlockingForTesting allow_blocking;
- ASSERT_TRUE(base::ReadFileToString(
- test_data_dir_.AppendASCII("icon_rgb_0_0_255.png"), &blue_icon));
- ASSERT_TRUE(base::ReadFileToString(
- test_data_dir_.AppendASCII("icon_rgb_255_0_0.png"), &red_icon));
- }
-
TestExtensionDir test_dir;
test_dir.WriteManifest(base::StringPrintf(
kManifestTemplate, GetManifestKeyForActionType(GetParam())));
test_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
base::StringPrintf(kSetIconBackgroundJsTemplate,
GetAPINameForActionType(GetParam())));
- test_dir.WriteFile(FILE_PATH_LITERAL("blue_icon.png"), blue_icon);
- test_dir.WriteFile(FILE_PATH_LITERAL("red_icon.png"), red_icon);
+ test_dir.CopyFileTo(test_data_dir_.AppendASCII("icon_rgb_0_0_255.png"),
+ FILE_PATH_LITERAL("blue_icon.png"));
+ test_dir.CopyFileTo(test_data_dir_.AppendASCII("icon_rgb_255_0_0.png"),
+ FILE_PATH_LITERAL("red_icon.png"));
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
@@ -672,20 +664,14 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, SetIconWithJavascriptHooks) {
"background": { "scripts": ["background.js"] }
})";
- std::string blue_icon;
- {
- base::ScopedAllowBlockingForTesting allow_blocking;
- ASSERT_TRUE(base::ReadFileToString(
- test_data_dir_.AppendASCII("icon_rgb_0_0_255.png"), &blue_icon));
- }
-
TestExtensionDir test_dir;
test_dir.WriteManifest(base::StringPrintf(
kManifestTemplate, GetManifestKeyForActionType(GetParam())));
test_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
base::StringPrintf(kSetIconBackgroundJsTemplate,
GetAPINameForActionType(GetParam())));
- test_dir.WriteFile(FILE_PATH_LITERAL("blue_icon.png"), blue_icon);
+ test_dir.CopyFileTo(test_data_dir_.AppendASCII("icon_rgb_0_0_255.png"),
+ FILE_PATH_LITERAL("blue_icon.png"));
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
@@ -738,13 +724,6 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, SetIconWithSelfDefined) {
"background": { "scripts": ["background.js"] }
})";
- std::string blue_icon;
- {
- base::ScopedAllowBlockingForTesting allow_blocking;
- ASSERT_TRUE(base::ReadFileToString(
- test_data_dir_.AppendASCII("icon_rgb_0_0_255.png"), &blue_icon));
- }
-
TestExtensionDir test_dir;
test_dir.WriteManifest(base::StringPrintf(
kManifestTemplate, GetManifestKeyForActionType(GetParam())));
@@ -752,7 +731,8 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, SetIconWithSelfDefined) {
test_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
base::StringPrintf(kSetIconBackgroundJsTemplate,
GetAPINameForActionType(GetParam())));
- test_dir.WriteFile(FILE_PATH_LITERAL("blue_icon.png"), blue_icon);
+ test_dir.CopyFileTo(test_data_dir_.AppendASCII("icon_rgb_0_0_255.png"),
+ FILE_PATH_LITERAL("blue_icon.png"));
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
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 7c2a722b840..25dbaadb950 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
@@ -171,22 +171,6 @@ IN_PROC_BROWSER_TEST_F(PageActionApiTest, RemovePopup) {
<< "Page action popup should have been removed.";
}
-// Tests popups in page actions.
-// Flaky on the trybots. See http://crbug.com/96725.
-IN_PROC_BROWSER_TEST_F(PageActionApiTest, DISABLED_ShowPageActionPopup) {
- ASSERT_TRUE(RunExtensionTest("page_action/popup")) << message_;
- const Extension* extension = GetSingleLoadedExtension();
- ASSERT_TRUE(extension) << message_;
-
- ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
-
- {
- ResultCatcher catcher;
- ExtensionActionAPI::Get(browser()->profile())
- ->ShowExtensionActionPopupForAPICall(extension, browser());
- ASSERT_TRUE(catcher.GetNextResult());
- }
-}
// Test http://crbug.com/57333: that two page action extensions using the same
// icon for the page action icon and the extension icon do not crash.
diff --git a/chromium/chrome/browser/extensions/api/extension_action/page_action_interactive_test.cc b/chromium/chrome/browser/extensions/api/extension_action/page_action_interactive_test.cc
new file mode 100644
index 00000000000..09c8a9b7e61
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/extension_action/page_action_interactive_test.cc
@@ -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.
+
+#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/test/base/interactive_test_utils.h"
+#include "content/public/test/browser_test.h"
+#include "extensions/test/result_catcher.h"
+
+namespace extensions {
+namespace {
+
+using PageActionInteractiveTest = ExtensionApiTest;
+
+// Tests popups in page actions.
+IN_PROC_BROWSER_TEST_F(PageActionInteractiveTest, ShowPageActionPopup) {
+ ASSERT_TRUE(RunExtensionTest("page_action/popup")) << message_;
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+
+ ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
+
+ ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+ ASSERT_TRUE(browser()->window()->IsActive());
+
+ ResultCatcher catcher;
+ ASSERT_TRUE(ExtensionActionAPI::Get(browser()->profile())
+ ->ShowExtensionActionPopupForAPICall(extension, browser()));
+ ASSERT_TRUE(catcher.GetNextResult());
+}
+
+} // namespace
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/feedback_private/OWNERS b/chromium/chrome/browser/extensions/api/feedback_private/OWNERS
index bd30e9ff740..5c0b2c9fb1e 100644
--- a/chromium/chrome/browser/extensions/api/feedback_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/feedback_private/OWNERS
@@ -1,4 +1,5 @@
afakhry@chromium.org
jkardatzke@chromium.org
+iby@chromium.org
# COMPONENT: Platform>Apps>Feedback
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 cb3b85fb7b6..312a3838cda 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
@@ -70,9 +70,10 @@ ChromeFeedbackPrivateDelegate::GetStrings(
std::make_unique<base::DictionaryValue>();
#define SET_STRING(id, idr) dict->SetString(id, l10n_util::GetStringUTF16(idr))
- SET_STRING("page-title", from_crash
- ? IDS_FEEDBACK_REPORT_PAGE_TITLE_SAD_TAB_FLOW
- : IDS_FEEDBACK_REPORT_PAGE_TITLE);
+ SET_STRING("pageTitle", from_crash
+ ? IDS_FEEDBACK_REPORT_PAGE_TITLE_SAD_TAB_FLOW
+ : IDS_FEEDBACK_REPORT_PAGE_TITLE);
+ SET_STRING("appTitle", IDS_FEEDBACK_REPORT_APP_TITLE);
SET_STRING("additionalInfo", IDS_FEEDBACK_ADDITIONAL_INFO_LABEL);
SET_STRING("minimizeBtnLabel", IDS_FEEDBACK_MINIMIZE_BUTTON_LABEL);
SET_STRING("closeBtnLabel", IDS_FEEDBACK_CLOSE_BUTTON_LABEL);
@@ -117,7 +118,7 @@ ChromeFeedbackPrivateDelegate::GetStrings(
system_logs::SystemLogsFetcher*
ChromeFeedbackPrivateDelegate::CreateSystemLogsFetcher(
content::BrowserContext* context) const {
- return system_logs::BuildChromeSystemLogsFetcher();
+ return system_logs::BuildChromeSystemLogsFetcher(/*scrub_data=*/true);
}
#if defined(OS_CHROMEOS)
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 408f09d5342..f02f4eb82cd 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
@@ -165,7 +165,7 @@ class FileSystemApiTestForDrive : public PlatformAppBrowserTest {
SetUpTestFileHierarchy();
integration_service_ = new drive::DriveIntegrationService(
- profile, nullptr, "", test_cache_root_.GetPath(),
+ profile, "", test_cache_root_.GetPath(),
fake_drivefs_helper_->CreateFakeDriveFsListenerFactory());
return integration_service_;
}
@@ -312,7 +312,7 @@ class FileSystemApiTestForRequestFileSystem : public PlatformAppBrowserTest {
profile, drivefs_root_.GetPath().Append("drive-user"));
return new drive::DriveIntegrationService(
- profile, nullptr, "", {},
+ profile, "", {},
fake_drivefs_helper_->CreateFakeDriveFsListenerFactory());
}
diff --git a/chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc b/chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
new file mode 100644
index 00000000000..e1cfefca8a1
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.cc
@@ -0,0 +1,143 @@
+// 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/force_installed_affiliated_extension_apitest.h"
+
+#include "base/json/json_writer.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/extensions/policy_test_utils.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "components/prefs/pref_service.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/test/result_catcher.h"
+
+namespace {
+
+// If running with |is_affiliated|==true, the test will use the same
+// |kAffiliationID| as user and device affiliation ID, which makes the user
+// affiliated (affiliation IDs overlap).
+// If running with |is_affiliated|==false, the test will use |kAffiliationID| as
+// device and |kAnotherAffiliationID| as user affiliation ID, which makes the
+// user non-affiliated (affiliation IDs don't overlap).
+constexpr char kAffiliationID[] = "some-affiliation-id";
+constexpr char kAnotherAffiliationID[] = "another-affiliation-id";
+
+constexpr char kAffiliatedUserEmail[] = "user@example.com";
+constexpr char kAffiliatedUserGaiaId[] = "1029384756";
+
+} // namespace
+
+namespace extensions {
+
+ForceInstalledAffiliatedExtensionApiTest::
+ ForceInstalledAffiliatedExtensionApiTest(bool is_affiliated)
+ : is_affiliated_(is_affiliated),
+ affiliated_account_id_(
+ AccountId::FromUserEmailGaiaId(kAffiliatedUserEmail,
+ kAffiliatedUserGaiaId)),
+ test_install_attributes_(
+ chromeos::StubInstallAttributes::CreateCloudManaged("fake-domain",
+ "fake-id")) {
+ set_exit_when_last_browser_closes(false);
+ set_chromeos_user_ = false;
+}
+
+ForceInstalledAffiliatedExtensionApiTest::
+ ~ForceInstalledAffiliatedExtensionApiTest() = default;
+
+void ForceInstalledAffiliatedExtensionApiTest::SetUpCommandLine(
+ base::CommandLine* command_line) {
+ ExtensionApiTest::SetUpCommandLine(command_line);
+ policy::AffiliationTestHelper::AppendCommandLineSwitchesForLoginManager(
+ command_line);
+}
+
+void ForceInstalledAffiliatedExtensionApiTest::
+ SetUpInProcessBrowserTestFixture() {
+ ExtensionApiTest::SetUpInProcessBrowserTestFixture();
+
+ // Initialize clients here so they are available during setup. They will be
+ // shutdown in ChromeBrowserMain.
+ chromeos::SessionManagerClient::InitializeFakeInMemory();
+ policy::AffiliationTestHelper affiliation_helper =
+ policy::AffiliationTestHelper::CreateForCloud(
+ chromeos::FakeSessionManagerClient::Get());
+
+ std::set<std::string> device_affiliation_ids;
+ device_affiliation_ids.insert(kAffiliationID);
+ ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
+ &test_helper_, device_affiliation_ids));
+ test_helper_.InstallOwnerKey();
+
+ std::set<std::string> user_affiliation_ids;
+ if (is_affiliated_) {
+ user_affiliation_ids.insert(kAffiliationID);
+ } else {
+ user_affiliation_ids.insert(kAnotherAffiliationID);
+ }
+ policy::UserPolicyBuilder user_policy;
+ ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
+ &user_policy, affiliated_account_id_, user_affiliation_ids));
+ test_helper_.InstallOwnerKey();
+
+ // Init the user policy provider.
+ EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
+ .WillRepeatedly(testing::Return(true));
+ policy_provider_.SetAutoRefresh();
+ policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
+ &policy_provider_);
+
+ // Set retry delay to prevent timeouts.
+ policy::DeviceManagementService::SetRetryDelayForTesting(0);
+}
+
+void ForceInstalledAffiliatedExtensionApiTest::SetUpOnMainThread() {
+ // Log in user that was created with
+ // policy::AffiliationTestHelper::PreLoginUser() in the PRE_ test.
+ const base::ListValue* users =
+ g_browser_process->local_state()->GetList("LoggedInUsers");
+ if (!users->empty()) {
+ policy::AffiliationTestHelper::LoginUser(affiliated_account_id_);
+ }
+
+ policy_test_utils::SetUpEmbeddedTestServer(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ ExtensionApiTest::SetUpOnMainThread();
+}
+
+const extensions::Extension*
+ForceInstalledAffiliatedExtensionApiTest::ForceInstallExtension(
+ const extensions::ExtensionId& extension_id,
+ const std::string& update_manifest_path) {
+ policy_test_utils::SetExtensionInstallForcelistPolicy(
+ extension_id, embedded_test_server()->GetURL(update_manifest_path),
+ profile(), &policy_provider_);
+ const extensions::Extension* extension =
+ ExtensionRegistry::Get(profile())->enabled_extensions().GetByID(
+ extension_id);
+ DCHECK(extension);
+ return extension;
+}
+
+void ForceInstalledAffiliatedExtensionApiTest::TestExtension(
+ Browser* browser,
+ const GURL& page_url,
+ const base::Value& custom_arg_value) {
+ DCHECK(page_url.is_valid()) << "page_url must be valid";
+
+ std::string custom_arg;
+ base::JSONWriter::Write(custom_arg_value, &custom_arg);
+ SetCustomArg(custom_arg);
+
+ extensions::ResultCatcher catcher;
+ ui_test_utils::NavigateToURL(browser, GURL(page_url));
+
+ ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h b/chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h
new file mode 100644
index 00000000000..7707876e67b
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/force_installed_affiliated_extension_apitest.h
@@ -0,0 +1,67 @@
+// 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_FORCE_INSTALLED_AFFILIATED_EXTENSION_APITEST_H_
+#define CHROME_BROWSER_EXTENSIONS_API_FORCE_INSTALLED_AFFILIATED_EXTENSION_APITEST_H_
+
+#include <string>
+
+#include "base/values.h"
+#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chromeos/tpm/stub_install_attributes.h"
+#include "components/account_id/account_id.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "extensions/common/extension_id.h"
+#include "url/gurl.h"
+
+class Browser;
+
+namespace base {
+class CommandLine;
+} // namespace base
+
+namespace extensions {
+
+class Extension;
+
+// TODO(https://crbug.com/1082195) Create force-installed extension and user
+// affiliation test mixins to replace this class.
+
+// Helper class to test force-installed extensions in a
+// affiliated/non-affiliated user profile.
+class ForceInstalledAffiliatedExtensionApiTest : public ExtensionApiTest {
+ public:
+ explicit ForceInstalledAffiliatedExtensionApiTest(bool is_affiliated);
+ ~ForceInstalledAffiliatedExtensionApiTest() override;
+
+ protected:
+ // ExtensionApiTest
+ void SetUpCommandLine(base::CommandLine* command_line) override;
+ void SetUpInProcessBrowserTestFixture() override;
+ void SetUpOnMainThread() override;
+
+ const extensions::Extension* ForceInstallExtension(
+ const extensions::ExtensionId& extension_id,
+ const std::string& update_manifest_path);
+
+ // Sets |custom_arg_value|, loads |page_url| and waits for an extension API
+ // test pass/fail notification.
+ void TestExtension(Browser* browser,
+ const GURL& page_url,
+ const base::Value& custom_arg_value);
+
+ // Whether the user should be affiliated (= user and device affiliation IDs
+ // overlap).
+ const bool is_affiliated_;
+
+ const AccountId affiliated_account_id_;
+ policy::MockConfigurationPolicyProvider policy_provider_;
+ chromeos::ScopedStubInstallAttributes test_install_attributes_;
+ policy::DevicePolicyCrosTestHelper test_helper_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_FORCE_INSTALLED_AFFILIATED_EXTENSION_APITEST_H_
diff --git a/chromium/chrome/browser/extensions/api/gcm/gcm_apitest.cc b/chromium/chrome/browser/extensions/api/gcm/gcm_apitest.cc
index d9b189cf106..623b7a0697c 100644
--- a/chromium/chrome/browser/extensions/api/gcm/gcm_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/gcm/gcm_apitest.cc
@@ -60,7 +60,7 @@ namespace extensions {
class GcmApiTest : public ExtensionApiTest {
public:
- GcmApiTest() : fake_gcm_profile_service_(NULL) {}
+ GcmApiTest() : fake_gcm_profile_service_(nullptr) {}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override;
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
index e650e3f1ebb..bd091a6f0e2 100644
--- a/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h"
#include "base/bind.h"
+#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/api/identity/identity_api.h"
#include "chrome/browser/profiles/profile.h"
@@ -24,6 +25,15 @@
namespace extensions {
+namespace {
+
+void RecordResultHistogram(GaiaRemoteConsentFlow::Failure failure) {
+ base::UmaHistogramEnumeration("Signin.Extensions.GaiaRemoteConsentFlowResult",
+ failure);
+}
+
+} // namespace
+
GaiaRemoteConsentFlow::Delegate::~Delegate() = default;
GaiaRemoteConsentFlow::GaiaRemoteConsentFlow(
@@ -61,7 +71,7 @@ void GaiaRemoteConsentFlow::OnSetAccountsComplete(
}
if (result != signin::SetAccountsInCookieResult::kSuccess) {
- delegate_->OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED);
return;
}
@@ -100,16 +110,16 @@ void GaiaRemoteConsentFlow::OnConsentResultSet(
std::string gaia_id;
if (!gaia::ParseOAuth2MintTokenConsentResult(consent_result,
&consent_approved, &gaia_id)) {
- delegate_->OnGaiaRemoteConsentFlowFailed(
- GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT);
+ GaiaRemoteConsentFlowFailed(GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT);
return;
}
if (!consent_approved) {
- delegate_->OnGaiaRemoteConsentFlowFailed(GaiaRemoteConsentFlow::NO_GRANT);
+ GaiaRemoteConsentFlowFailed(GaiaRemoteConsentFlow::NO_GRANT);
return;
}
+ RecordResultHistogram(GaiaRemoteConsentFlow::NONE);
delegate_->OnGaiaRemoteConsentFlowApproved(consent_result, gaia_id);
}
@@ -129,7 +139,7 @@ void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
break;
}
- delegate_->OnGaiaRemoteConsentFlowFailed(gaia_failure);
+ GaiaRemoteConsentFlowFailed(gaia_failure);
}
std::unique_ptr<GaiaAuthFetcher>
@@ -146,7 +156,15 @@ GaiaRemoteConsentFlow::GetCookieManagerForPartition() {
}
void GaiaRemoteConsentFlow::OnEndBatchOfRefreshTokenStateChanges() {
+// On ChromeOS, new accounts are added through the account manager. They need to
+// be pushed to the partition used by this flow explicitly.
+// On Desktop, sign-in happens on the Web and a new account is directly added to
+// this partition's cookie jar. An extra update triggered from here might change
+// cookies order in the middle of the flow. This may lead to a bug like
+// https://crbug.com/1112343.
+#if defined(OS_CHROMEOS)
SetAccountsInCookie();
+#endif
}
void GaiaRemoteConsentFlow::SetWebAuthFlowForTesting(
@@ -196,4 +214,9 @@ void GaiaRemoteConsentFlow::SetAccountsInCookie() {
base::Unretained(this)));
}
+void GaiaRemoteConsentFlow::GaiaRemoteConsentFlowFailed(Failure failure) {
+ RecordResultHistogram(failure);
+ delegate_->OnGaiaRemoteConsentFlowFailed(failure);
+}
+
} // 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
index 433777bc7c0..0fd5cc8de97 100644
--- a/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
@@ -25,12 +25,16 @@ class GaiaRemoteConsentFlow
public signin::AccountsCookieMutator::PartitionDelegate,
public signin::IdentityManager::Observer {
public:
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
enum Failure {
- WINDOW_CLOSED,
- LOAD_FAILED,
- SET_ACCOUNTS_IN_COOKIE_FAILED,
- INVALID_CONSENT_RESULT,
- NO_GRANT
+ NONE = 0,
+ WINDOW_CLOSED = 1,
+ LOAD_FAILED = 2,
+ SET_ACCOUNTS_IN_COOKIE_FAILED = 3,
+ INVALID_CONSENT_RESULT = 4,
+ NO_GRANT = 5,
+ kMaxValue = NO_GRANT
};
class Delegate {
@@ -80,6 +84,8 @@ class GaiaRemoteConsentFlow
private:
void SetAccountsInCookie();
+ void GaiaRemoteConsentFlowFailed(Failure failure);
+
Delegate* delegate_;
Profile* profile_;
CoreAccountId account_id_;
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
index fa1a7c19ed7..bf65e8160b6 100644
--- 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
@@ -7,6 +7,7 @@
#include <vector>
#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.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"
@@ -17,6 +18,9 @@
namespace extensions {
+const char kResultHistogramName[] =
+ "Signin.Extensions.GaiaRemoteConsentFlowResult";
+
const char kWindowKey[] = "window_key";
const char kGaiaId[] = "fake_gaia_id";
const char kConsentResult[] = "CAESCUVOQ1JZUFRFRBoMZmFrZV9nYWlhX2lk";
@@ -98,8 +102,11 @@ class IdentityGaiaRemoteConsentFlowTest : public testing::Test {
window_key));
}
+ base::HistogramTester* histogram_tester() { return &histogram_tester_; }
+
protected:
base::test::TaskEnvironment task_env_;
+ base::HistogramTester histogram_tester_;
testing::StrictMock<MockGaiaRemoteConsentFlowDelegate> delegate_;
};
@@ -108,6 +115,8 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult) {
EXPECT_CALL(delegate_,
OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
flow->OnConsentResultSet(kConsentResult, kWindowKey);
+ histogram_tester()->ExpectUniqueSample(kResultHistogramName,
+ GaiaRemoteConsentFlow::NONE, 1);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_WrongWindowIgnored) {
@@ -130,6 +139,8 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_TwoWindows) {
EXPECT_CALL(delegate_,
OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
flow->OnConsentResultSet(kConsentResult, kWindowKey);
+ histogram_tester()->ExpectUniqueSample(kResultHistogramName,
+ GaiaRemoteConsentFlow::NONE, 2);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, InvalidConsentResult) {
@@ -139,6 +150,8 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, InvalidConsentResult) {
OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::INVALID_CONSENT_RESULT));
flow->OnConsentResultSet(kInvalidConsentResult, kWindowKey);
+ histogram_tester()->ExpectUniqueSample(
+ kResultHistogramName, GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT, 1);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, NoGrant) {
@@ -147,6 +160,8 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, NoGrant) {
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::NO_GRANT));
flow->OnConsentResultSet(kNoGrantConsentResult, kWindowKey);
+ histogram_tester()->ExpectUniqueSample(kResultHistogramName,
+ GaiaRemoteConsentFlow::NO_GRANT, 1);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, SetAccountsFailure) {
@@ -157,6 +172,9 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, SetAccountsFailure) {
GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED));
flow->OnSetAccountsComplete(
signin::SetAccountsInCookieResult::kPersistentError);
+ histogram_tester()->ExpectUniqueSample(
+ kResultHistogramName,
+ GaiaRemoteConsentFlow::SET_ACCOUNTS_IN_COOKIE_FAILED, 1);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_WindowClosed) {
@@ -164,6 +182,8 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_WindowClosed) {
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::WINDOW_CLOSED));
flow->OnAuthFlowFailure(WebAuthFlow::Failure::WINDOW_CLOSED);
+ histogram_tester()->ExpectUniqueSample(
+ kResultHistogramName, GaiaRemoteConsentFlow::WINDOW_CLOSED, 1);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_LoadFailed) {
@@ -171,6 +191,8 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_LoadFailed) {
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::LOAD_FAILED));
flow->OnAuthFlowFailure(WebAuthFlow::Failure::LOAD_FAILED);
+ histogram_tester()->ExpectUniqueSample(kResultHistogramName,
+ GaiaRemoteConsentFlow::LOAD_FAILED, 1);
}
} // 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 68327bb525c..71f36451b23 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -14,6 +14,7 @@
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/buildflag.h"
@@ -23,6 +24,7 @@
#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"
+#include "chrome/browser/extensions/api/identity/identity_get_auth_token_error.h"
#include "chrome/browser/extensions/api/identity/identity_get_auth_token_function.h"
#include "chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h"
#include "chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h"
@@ -91,8 +93,13 @@ namespace {
namespace errors = identity_constants;
namespace utils = extension_function_test_utils;
-static const char kAccessToken[] = "auth_token";
-static const char kExtensionId[] = "ext_id";
+const char kAccessToken[] = "auth_token";
+const char kExtensionId[] = "ext_id";
+
+const char kGetAuthTokenResultHistogramName[] =
+ "Signin.Extensions.GetAuthTokenResult";
+const char kGetAuthTokenResultAfterConsentApprovedHistogramName[] =
+ "Signin.Extensions.GetAuthTokenResult.RemoteConsentApproved";
#if defined(OS_CHROMEOS)
void InitNetwork() {
@@ -681,9 +688,9 @@ IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, NoPrimaryAccount) {
}
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,
- PrimaryAccountHasNoRefreshToken) {
+ PrimaryAccountHasInvalidRefreshToken) {
CoreAccountId primary_account_id = SignIn("primary@example.com");
- identity_test_env()->RemoveRefreshTokenForAccount(primary_account_id);
+ identity_test_env()->SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_TRUE(ExpectGetAccounts({}));
}
@@ -938,6 +945,8 @@ class GetAuthTokenFunctionTest
id_api()->mint_queue()->RequestComplete(type, key, request);
}
+ base::HistogramTester* histogram_tester() { return &histogram_tester_; }
+
base::OnceClosure on_access_token_requested_;
private:
@@ -950,6 +959,7 @@ class GetAuthTokenFunctionTest
std::move(on_access_token_requested_).Run();
}
+ base::HistogramTester histogram_tester_;
std::string extension_id_;
std::set<std::string> oauth_scopes_;
};
@@ -962,6 +972,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoClientId) {
EXPECT_EQ(std::string(errors::kInvalidClientId), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kInvalidClientId, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoScopes) {
@@ -972,6 +985,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoScopes) {
EXPECT_EQ(std::string(errors::kInvalidScopes), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kEmptyScopes, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveNotSignedIn) {
@@ -982,6 +998,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveNotSignedIn) {
EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kUserNotSignedIn, 1);
}
// The signin flow is simply not used on ChromeOS.
@@ -996,6 +1015,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
EXPECT_TRUE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kSignInFailed, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1018,6 +1040,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kBrowserSigninNotAllowed), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kBrowserSigninNotAllowed, 1);
}
#endif
@@ -1032,6 +1057,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveMintFailure) {
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1044,6 +1072,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure,
base::CompareCase::INSENSITIVE_ASCII));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1061,6 +1092,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
GetCachedToken(CoreAccountId()).status());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaConsentInteractionRequired, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1076,6 +1110,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1091,6 +1128,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1109,6 +1149,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
// in a valid state.
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
// The signin flow is simply not used on ChromeOS.
@@ -1129,6 +1172,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_TRUE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
#endif
@@ -1147,6 +1193,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoOptionsSuccess) {
EXPECT_FALSE(func->scope_ui_shown());
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(CoreAccountId()).status());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveSuccess) {
@@ -1164,6 +1213,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveSuccess) {
EXPECT_FALSE(func->scope_ui_shown());
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(CoreAccountId()).status());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveLoginCanceled) {
@@ -1179,6 +1231,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveLoginCanceled) {
EXPECT_TRUE(func->login_ui_shown());
#endif
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kSignInFailed, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1195,6 +1250,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
// The interactive login flow is always short-circuited out with failure on
@@ -1213,6 +1271,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_TRUE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1228,6 +1289,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_TRUE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1242,6 +1306,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_TRUE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1259,6 +1326,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_TRUE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1273,6 +1343,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kUserRejected), error);
EXPECT_TRUE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1290,6 +1363,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_TRUE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
#endif
@@ -1304,6 +1380,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveApprovalAborted) {
EXPECT_EQ(std::string(errors::kUserRejected), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1318,6 +1397,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kPageLoadFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1332,6 +1414,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kInvalidRedirect), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kInvalidRedirect, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1348,6 +1433,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1366,6 +1454,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
// The login UI should not be shown as the account is in a valid state.
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
}
// The signin flow is simply not used on ChromeOS.
@@ -1388,6 +1479,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_TRUE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
}
#endif
@@ -1396,15 +1490,24 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
- std::map<std::string, std::string> error_map;
- error_map.insert(std::make_pair("access_denied", errors::kUserRejected));
- error_map.insert(std::make_pair("invalid_scope", errors::kInvalidScopes));
- error_map.insert(std::make_pair(
- "unmapped_error", std::string(errors::kAuthFailure) + "unmapped_error"));
+ struct TestCase {
+ std::string oauth_error;
+ std::string error_message;
+ IdentityGetAuthTokenError::State error_state;
+ };
- for (std::map<std::string, std::string>::const_iterator it =
- error_map.begin();
- it != error_map.end(); ++it) {
+ std::vector<TestCase> test_cases;
+ test_cases.push_back({"access_denied", errors::kUserRejected,
+ IdentityGetAuthTokenError::State::kOAuth2AccessDenied});
+ test_cases.push_back(
+ {"invalid_scope", errors::kInvalidScopes,
+ IdentityGetAuthTokenError::State::kOAuth2InvalidScopes});
+ test_cases.push_back({"unmapped_error",
+ std::string(errors::kAuthFailure) + "unmapped_error",
+ IdentityGetAuthTokenError::State::kOAuth2Failure});
+
+ for (const auto& test_case : test_cases) {
+ base::HistogramTester histogram_tester;
scoped_refptr<FakeGetAuthTokenFunction> func(
new FakeGetAuthTokenFunction());
func->set_extension(extension.get());
@@ -1412,12 +1515,14 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
// flow to be leaked.
id_api()->EraseAllCachedTokens();
func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
- func->set_scope_ui_oauth_error(it->first);
+ func->set_scope_ui_oauth_error(test_case.oauth_error);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
- EXPECT_EQ(it->second, error);
+ EXPECT_EQ(test_case.error_message, error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester.ExpectUniqueSample(kGetAuthTokenResultHistogramName,
+ test_case.error_state, 1);
}
}
@@ -1438,6 +1543,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveApprovalSuccess) {
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(CoreAccountId()).status());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
#if !defined(OS_MACOSX)
@@ -1472,6 +1580,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
// The login screen should not be shown when the browser process is shutting
// down.
EXPECT_FALSE(func->login_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
}
#endif // !defined(OS_MACOSX)
@@ -1506,6 +1617,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveQueue) {
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
@@ -1540,6 +1654,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueueShutdown) {
@@ -1571,6 +1688,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueueShutdown) {
EXPECT_FALSE(func->scope_ui_shown());
QueueRequestComplete(type, &queued_request);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kCanceled, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveShutdown) {
@@ -1585,6 +1705,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveShutdown) {
// After the request is canceled, the function will complete.
func->OnIdentityAPIShutdown();
EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kCanceled, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1611,6 +1734,10 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_FALSE(func->scope_ui_shown());
QueueRequestComplete(type, &queued_request);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaConsentInteractionAlreadyRunning,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveCacheHit) {
@@ -1632,6 +1759,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveCacheHit) {
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
// Checks that the first account in Gaia cookie can be used when extensions are
@@ -1665,6 +1795,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
std::string error =
utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kUserNotSignedIn, 1);
} else {
// Use the account from Gaia cookies.
std::unique_ptr<base::Value> value(
@@ -1672,6 +1805,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
std::string access_token;
EXPECT_TRUE(value->GetAsString(&access_token));
EXPECT_EQ(std::string(kAccessToken), access_token);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kNone, 1);
}
EXPECT_FALSE(func->login_ui_shown());
@@ -1697,6 +1833,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kNoGrant), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaConsentInteractionRequired, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveCacheHit) {
@@ -1734,6 +1873,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveCacheHit) {
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
// The interactive login UI is never shown on ChromeOS, so tests of the
@@ -1763,6 +1905,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, LoginInvalidatesTokenCache) {
EXPECT_TRUE(func->scope_ui_shown());
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
GetCachedToken(CoreAccountId()).status());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
#endif
@@ -1789,6 +1934,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(kAccessToken, value->GetString());
EXPECT_TRUE(func->scope_ui_shown());
EXPECT_FALSE(GetCachedGaiaId().has_value());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1814,6 +1962,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kUserRejected), error);
EXPECT_TRUE(func->scope_ui_shown());
EXPECT_FALSE(GetCachedGaiaId().has_value());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithChromeClientId) {
@@ -1852,6 +2003,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, IdentityAPIShutdown) {
id_api()->Shutdown();
EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kCanceled, 1);
}
// Ensure that when there are multiple active function calls, IdentityAPI
@@ -1920,6 +2074,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueToken) {
GetCachedToken(CoreAccountId()).status());
EXPECT_THAT(func->login_access_tokens(),
testing::ElementsAre(primary_account_access_token));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) {
@@ -1947,6 +2104,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) {
GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)
.ToString(),
WaitForError(func.get()));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1976,6 +2136,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
GetCachedToken(CoreAccountId()).status());
EXPECT_THAT(func->login_access_tokens(),
testing::ElementsAre(primary_account_access_token));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2007,6 +2170,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
GetCachedToken(CoreAccountId()).status());
EXPECT_THAT(func->login_access_tokens(),
testing::ElementsAre(primary_account_access_token));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2033,6 +2199,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kUserNonPrimary), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kUserNonPrimary, 1);
return;
}
@@ -2052,6 +2221,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
GetCachedToken(secondary_account_id).status());
EXPECT_THAT(func->login_access_tokens(),
testing::ElementsAre(secondary_account_access_token));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2068,10 +2240,17 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
func.get(), "[{\"account\": { \"id\": \"unknown@example.com\" } }]",
browser());
std::string expected_error;
- if (id_api()->AreExtensionsRestrictedToPrimaryAccount())
+ if (id_api()->AreExtensionsRestrictedToPrimaryAccount()) {
EXPECT_EQ(errors::kUserNonPrimary, error);
- else
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kUserNonPrimary, 1);
+ } else {
EXPECT_EQ(errors::kUserNotSignedIn, error);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kUserNotSignedIn, 1);
+ }
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2094,6 +2273,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
base::CompareCase::INSENSITIVE_ASCII));
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2114,6 +2296,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
browser());
EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure,
base::CompareCase::INSENSITIVE_ASCII));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2137,6 +2322,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kUserRejected), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
}
// Tests that Chrome remembers user's choice of an account at the end of the
@@ -2172,6 +2360,12 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
if (id_api()->AreExtensionsRestrictedToPrimaryAccount()) {
EXPECT_EQ(std::string(errors::kUserNonPrimary), WaitForError(func.get()));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kRemoteConsentUserNonPrimary, 1);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultAfterConsentApprovedHistogramName,
+ IdentityGetAuthTokenError::State::kRemoteConsentUserNonPrimary, 1);
return;
}
@@ -2189,6 +2383,12 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_THAT(func->login_access_tokens(),
testing::ElementsAre(primary_account_access_token,
secondary_account_access_token));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kNone, 1);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultAfterConsentApprovedHistogramName,
+ IdentityGetAuthTokenError::State::kNone, 1);
}
{
@@ -2204,6 +2404,12 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kNone, 2);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultAfterConsentApprovedHistogramName,
+ IdentityGetAuthTokenError::State::kNone, 1);
}
}
@@ -2261,6 +2467,10 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(account.account_id).status());
+
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 2);
}
// Tests two concurrent remote consent flows. Both of them should succeed.
@@ -2325,6 +2535,10 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(account.account_id).status());
+
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 2);
}
// The signin flow is simply not used on ChromeOS.
@@ -2356,6 +2570,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(errors::kUserNonPrimary), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kUserNonPrimary, 1);
} else {
// Extensions can show the login UI for secondary accounts, and get the auth
// token.
@@ -2366,6 +2583,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_TRUE(func->login_ui_shown());
EXPECT_TRUE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kNone, 1);
}
}
#endif
@@ -2386,6 +2606,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesDefault) {
EXPECT_EQ(2ul, token_key->scopes.size());
EXPECT_TRUE(base::Contains(token_key->scopes, "scope1"));
EXPECT_TRUE(base::Contains(token_key->scopes, "scope2"));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmpty) {
@@ -2397,6 +2620,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmpty) {
func.get(), "[{\"scopes\": []}]", browser()));
EXPECT_EQ(errors::kInvalidScopes, error);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kEmptyScopes, 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmail) {
@@ -2414,6 +2640,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmail) {
const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
EXPECT_EQ(1ul, token_key->scopes.size());
EXPECT_TRUE(base::Contains(token_key->scopes, "email"));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmailFooBar) {
@@ -2433,6 +2662,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmailFooBar) {
EXPECT_TRUE(base::Contains(token_key->scopes, "email"));
EXPECT_TRUE(base::Contains(token_key->scopes, "foo"));
EXPECT_TRUE(base::Contains(token_key->scopes, "bar"));
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
#if defined(OS_CHROMEOS)
@@ -2488,11 +2720,12 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest, NonWhitelisted) {
EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
EXPECT_FALSE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName,
+ IdentityGetAuthTokenError::State::kNotWhitelistedInPublicSession, 1);
}
-// TODO(crbug.com/830052): This test is flaky.
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest,
- DISABLED_Whitelisted) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest, Whitelisted) {
// GetAuthToken() should return a token for whitelisted extensions.
user_manager::ScopedUserManager user_manager_enabler(
base::WrapUnique(user_manager_));
@@ -2504,6 +2737,9 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest,
std::string access_token;
EXPECT_TRUE(value->GetAsString(&access_token));
EXPECT_EQ(std::string(kAccessToken), access_token);
+ histogram_tester()->ExpectUniqueSample(
+ kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+ 1);
}
#endif
@@ -2829,19 +3065,19 @@ IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireOnPrimaryAccountSignOut) {
#endif // !defined(OS_CHROMEOS)
// Test that an event is fired when the primary account has a refresh token
-// revoked.
+// invalidated.
IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest,
- FireOnPrimaryAccountRefreshTokenRevoked) {
+ FireOnPrimaryAccountRefreshTokenInvalidated) {
api::identity::AccountInfo account_info;
account_info.id = "gaia_id_for_primary_example.com";
AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true));
CoreAccountId primary_account_id = SignIn("primary@example.com");
- AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, false));
+ AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true));
// Revoke the refresh token and verify that the callback fires.
- identity_test_env()->RemoveRefreshTokenForAccount(primary_account_id);
+ identity_test_env()->SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_FALSE(HasExpectedEvent());
}
@@ -2856,14 +3092,14 @@ IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest,
CoreAccountId primary_account_id = SignIn("primary@example.com");
- AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, false));
- identity_test_env()->RemoveRefreshTokenForAccount(primary_account_id);
+ AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true));
+ identity_test_env()->SetInvalidRefreshTokenForPrimaryAccount();
account_info.id = "gaia_id_for_primary_example.com";
AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true));
// Make the primary account available again and check that the callback fires.
- identity_test_env()->MakeAccountAvailable("primary@example.com");
+ identity_test_env()->SetRefreshTokenForPrimaryAccount();
EXPECT_FALSE(HasExpectedEvent());
}
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.cc b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.cc
new file mode 100644
index 00000000000..7f02651c90d
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.cc
@@ -0,0 +1,112 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/identity/identity_get_auth_token_error.h"
+
+#include "base/strings/string_piece.h"
+#include "chrome/browser/extensions/api/identity/identity_constants.h"
+
+namespace extensions {
+
+// static
+IdentityGetAuthTokenError IdentityGetAuthTokenError::FromGaiaFlowAuthError(
+ base::StringPiece error_message) {
+ return IdentityGetAuthTokenError(State::kGaiaFlowAuthFailure, error_message);
+}
+
+// static
+IdentityGetAuthTokenError IdentityGetAuthTokenError::FromMintTokenAuthError(
+ base::StringPiece error_message) {
+ return IdentityGetAuthTokenError(State::kMintTokenAuthFailure, error_message);
+}
+
+// static
+IdentityGetAuthTokenError
+IdentityGetAuthTokenError::FromGetAccessTokenAuthError(
+ base::StringPiece error_message) {
+ return IdentityGetAuthTokenError(State::kGetAccessTokenAuthFailure,
+ error_message);
+}
+
+// static
+IdentityGetAuthTokenError IdentityGetAuthTokenError::FromOAuth2Error(
+ base::StringPiece oauth2_error) {
+ const char kOAuth2ErrorAccessDenied[] = "access_denied";
+ const char kOAuth2ErrorInvalidScope[] = "invalid_scope";
+
+ if (oauth2_error == kOAuth2ErrorAccessDenied) {
+ return IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kOAuth2AccessDenied);
+ } else if (oauth2_error == kOAuth2ErrorInvalidScope) {
+ return IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kOAuth2InvalidScopes);
+ } else {
+ return IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kOAuth2Failure, oauth2_error);
+ }
+}
+
+IdentityGetAuthTokenError::IdentityGetAuthTokenError()
+ : IdentityGetAuthTokenError(State::kNone) {}
+
+IdentityGetAuthTokenError::IdentityGetAuthTokenError(State state)
+ : IdentityGetAuthTokenError(state, base::StringPiece()) {}
+
+IdentityGetAuthTokenError::State IdentityGetAuthTokenError::state() const {
+ return state_;
+}
+
+std::string IdentityGetAuthTokenError::ToString() const {
+ switch (state_) {
+ case State::kNone:
+ return std::string();
+ case State::kInvalidClientId:
+ return identity_constants::kInvalidClientId;
+ case State::kEmptyScopes:
+ case State::kOAuth2InvalidScopes:
+ return identity_constants::kInvalidScopes;
+ case State::kGaiaFlowAuthFailure:
+ case State::kMintTokenAuthFailure:
+ case State::kGetAccessTokenAuthFailure:
+ case State::kOAuth2Failure:
+ return identity_constants::kAuthFailure + error_message_;
+ case State::kNoGrant:
+ case State::kGaiaConsentInteractionRequired:
+ case State::kGaiaConsentInteractionAlreadyRunning:
+ return identity_constants::kNoGrant;
+ case State::kOAuth2AccessDenied:
+ case State::kGaiaFlowRejected:
+ case State::kRemoteConsentFlowRejected:
+ return identity_constants::kUserRejected;
+ case State::kUserNotSignedIn:
+ case State::kNotWhitelistedInPublicSession:
+ case State::kSignInFailed:
+ case State::kRemoteConsentUserNotSignedIn:
+ return identity_constants::kUserNotSignedIn;
+ case State::kUserNonPrimary:
+ case State::kRemoteConsentUserNonPrimary:
+ return identity_constants::kUserNonPrimary;
+ case State::kBrowserSigninNotAllowed:
+ return identity_constants::kBrowserSigninNotAllowed;
+ case State::kInvalidRedirect:
+ return identity_constants::kInvalidRedirect;
+ case State::kOffTheRecord:
+ return identity_constants::kOffTheRecord;
+ case State::kPageLoadFailure:
+ case State::kRemoteConsentPageLoadFailure:
+ return identity_constants::kPageLoadFailure;
+ case State::kSetAccountsInCookieFailure:
+ return identity_constants::kSetAccountsInCookieFailure;
+ case State::kInvalidConsentResult:
+ return identity_constants::kInvalidConsentResult;
+ case State::kCanceled:
+ return identity_constants::kCanceled;
+ }
+}
+
+IdentityGetAuthTokenError::IdentityGetAuthTokenError(State state,
+ base::StringPiece error)
+ : state_(state), error_message_(error) {}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.h b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.h
new file mode 100644
index 00000000000..e03a89cea0b
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_error.h
@@ -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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_AUTH_TOKEN_ERROR_H_
+#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_AUTH_TOKEN_ERROR_H_
+
+#include <string>
+
+#include "base/strings/string_piece_forward.h"
+
+namespace extensions {
+
+class IdentityGetAuthTokenError {
+ public:
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class State {
+ kNone = 0,
+ kInvalidClientId = 1,
+ kEmptyScopes = 2,
+ kOAuth2InvalidScopes = 3,
+ kGaiaFlowAuthFailure = 4,
+ kMintTokenAuthFailure = 5,
+ kGetAccessTokenAuthFailure = 6,
+ kOAuth2Failure = 7,
+ kNoGrant = 8,
+ kGaiaConsentInteractionRequired = 9,
+ kGaiaConsentInteractionAlreadyRunning = 10,
+ kOAuth2AccessDenied = 11,
+ kGaiaFlowRejected = 12,
+ kRemoteConsentFlowRejected = 13,
+ kUserNotSignedIn = 14,
+ kNotWhitelistedInPublicSession = 15,
+ kSignInFailed = 16,
+ kRemoteConsentUserNotSignedIn = 17,
+ kUserNonPrimary = 18,
+ kRemoteConsentUserNonPrimary = 19,
+ kBrowserSigninNotAllowed = 20,
+ kInvalidRedirect = 21,
+ kOffTheRecord = 22,
+ kPageLoadFailure = 23,
+ kRemoteConsentPageLoadFailure = 24,
+ kSetAccountsInCookieFailure = 25,
+ kInvalidConsentResult = 26,
+ kCanceled = 27,
+ kMaxValue = kCanceled,
+ };
+
+ // Constructs a |State::kGaiaFlowAuthFailure| error with an |error_message|.
+ static IdentityGetAuthTokenError FromGaiaFlowAuthError(
+ base::StringPiece error_message);
+
+ // Constructs a |State::kMintTokenAuthFailure| error with an
+ // |error_message|.
+ static IdentityGetAuthTokenError FromMintTokenAuthError(
+ base::StringPiece error_message);
+
+ // Constructs a |State::kGetAccessTokenAuthFailure| error with an
+ // |error_message|.
+ static IdentityGetAuthTokenError FromGetAccessTokenAuthError(
+ base::StringPiece error_message);
+
+ // Constructs an IdentityGetAuthTokenError from |oauth2_error|.
+ static IdentityGetAuthTokenError FromOAuth2Error(
+ base::StringPiece oauth2_error);
+
+ // Constructs a |State::kNone| error.
+ IdentityGetAuthTokenError();
+
+ // Constructs an IdentityGetAuthTokenError from |state| with no additional
+ // data.
+ explicit IdentityGetAuthTokenError(State state);
+
+ State state() const;
+
+ // Returns an error message that can be returned to the developer in
+ // chrome.runtime.lastError.
+ std::string ToString() const;
+
+ private:
+ IdentityGetAuthTokenError(State state, base::StringPiece error);
+
+ State state_;
+ std::string error_message_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_AUTH_TOKEN_ERROR_H_
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 39a89fd15be..4e52c3887e1 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
@@ -10,14 +10,16 @@
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/location.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/notreached.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.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_auth_token_error.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/chrome_device_id_helper.h"
#include "chrome/browser/signin/identity_manager_factory.h"
@@ -77,6 +79,17 @@ std::string GetOAuth2MintTokenFlowChannel() {
return version_info::GetChannelString(chrome::GetChannel());
}
+void RecordFunctionResult(const IdentityGetAuthTokenError& error,
+ bool remote_consent_approved) {
+ base::UmaHistogramEnumeration("Signin.Extensions.GetAuthTokenResult",
+ error.state());
+ if (remote_consent_approved) {
+ base::UmaHistogramEnumeration(
+ "Signin.Extensions.GetAuthTokenResult.RemoteConsentApproved",
+ error.state());
+ }
+}
+
} // namespace
IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
@@ -104,7 +117,10 @@ ExtensionFunction::ResponseAction IdentityGetAuthTokenFunction::Run() {
this, "extension", extension()->id());
if (GetProfile()->IsOffTheRecord()) {
- return RespondNow(Error(identity_constants::kOffTheRecord));
+ IdentityGetAuthTokenError error(
+ IdentityGetAuthTokenError::State::kOffTheRecord);
+ RecordFunctionResult(error, remote_consent_approved_);
+ return RespondNow(Error(error.ToString()));
}
std::unique_ptr<api::identity::GetAuthToken::Params> params(
@@ -122,7 +138,10 @@ ExtensionFunction::ResponseAction IdentityGetAuthTokenFunction::Run() {
// Check that the necessary information is present in the manifest.
oauth2_client_id_ = GetOAuth2ClientId();
if (oauth2_client_id_.empty()) {
- return RespondNow(Error(identity_constants::kInvalidClientId));
+ IdentityGetAuthTokenError error(
+ IdentityGetAuthTokenError::State::kInvalidClientId);
+ RecordFunctionResult(error, remote_consent_approved_);
+ return RespondNow(Error(error.ToString()));
}
std::set<std::string> scopes(oauth2_info.scopes.begin(),
@@ -140,7 +159,10 @@ ExtensionFunction::ResponseAction IdentityGetAuthTokenFunction::Run() {
}
if (scopes.empty()) {
- return RespondNow(Error(identity_constants::kInvalidScopes));
+ IdentityGetAuthTokenError error(
+ IdentityGetAuthTokenError::State::kEmptyScopes);
+ RecordFunctionResult(error, remote_consent_approved_);
+ return RespondNow(Error(error.ToString()));
}
token_key_.scopes = scopes;
@@ -159,15 +181,15 @@ ExtensionFunction::ResponseAction IdentityGetAuthTokenFunction::Run() {
if (gaia_id.empty() || IsPrimaryAccountOnly()) {
// Try the primary account.
// TODO(https://crbug.com/932400): collapse the asynchronicity
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&IdentityGetAuthTokenFunction::GetAuthTokenForPrimaryAccount,
weak_ptr_factory_.GetWeakPtr(), gaia_id));
} else {
// Get the AccountInfo for the account that the extension wishes to use.
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&IdentityGetAuthTokenFunction::FetchExtensionAccountInfo,
weak_ptr_factory_.GetWeakPtr(), gaia_id));
}
@@ -186,7 +208,8 @@ void IdentityGetAuthTokenFunction::GetAuthTokenForPrimaryAccount(
// than the primary account.
if (primary_account_only && !extension_gaia_id.empty() &&
extension_gaia_id != primary_account_info.gaia) {
- CompleteFunctionWithError(identity_constants::kUserNonPrimary);
+ CompleteFunctionWithError(IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kUserNonPrimary));
return;
}
@@ -230,7 +253,8 @@ void IdentityGetAuthTokenFunction::OnReceivedExtensionAccountInfo(
if (connector->IsEnterpriseManaged() && (is_kiosk || is_public_session)) {
if (is_public_session && !IsOriginWhitelistedInPublicSession()) {
- CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+ CompleteFunctionWithError(IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kNotWhitelistedInPublicSession));
return;
}
@@ -243,10 +267,11 @@ void IdentityGetAuthTokenFunction::OnReceivedExtensionAccountInfo(
!IdentityManagerFactory::GetForProfile(GetProfile())
->HasAccountWithRefreshToken(account_info->account_id)) {
if (!ShouldStartSigninFlow()) {
- CompleteFunctionWithError(
+ IdentityGetAuthTokenError error(
IsBrowserSigninAllowed(GetProfile())
- ? identity_constants::kUserNotSignedIn
- : identity_constants::kBrowserSigninNotAllowed);
+ ? IdentityGetAuthTokenError::State::kUserNotSignedIn
+ : IdentityGetAuthTokenError::State::kBrowserSigninNotAllowed);
+ CompleteFunctionWithError(error);
return;
}
// Display a login prompt.
@@ -303,14 +328,16 @@ void IdentityGetAuthTokenFunction::CompleteAsyncRun(ResponseValue response) {
void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
const std::string& access_token) {
+ RecordFunctionResult(IdentityGetAuthTokenError(), remote_consent_approved_);
CompleteAsyncRun(OneArgument(std::make_unique<base::Value>(access_token)));
}
void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
- const std::string& error) {
+ const IdentityGetAuthTokenError& error) {
TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("identity", "CompleteFunctionWithError",
- this, "error", error);
- CompleteAsyncRun(Error(error));
+ this, "error", error.ToString());
+ RecordFunctionResult(error, remote_consent_approved_);
+ CompleteAsyncRun(Error(error.ToString()));
}
bool IdentityGetAuthTokenFunction::ShouldStartSigninFlow() {
@@ -394,14 +421,17 @@ void IdentityGetAuthTokenFunction::StartMintTokenFlow(
if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
// GAIA told us to do a consent UI.
- CompleteFunctionWithError(identity_constants::kNoGrant);
+ CompleteFunctionWithError(IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kGaiaConsentInteractionRequired));
return;
}
if (!id_api->mint_queue()->empty(
IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, token_key_)) {
// Another call is going through a consent UI.
- CompleteFunctionWithError(identity_constants::kNoGrant);
+ CompleteFunctionWithError(
+ IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::
+ kGaiaConsentInteractionAlreadyRunning));
return;
}
}
@@ -437,7 +467,9 @@ void IdentityGetAuthTokenFunction::StartMintToken(
// Always force minting token for ChromeOS kiosk app and public session.
if (user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() &&
!IsOriginWhitelistedInPublicSession()) {
- CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+ CompleteFunctionWithError(
+ IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::
+ kNotWhitelistedInPublicSession));
return;
}
@@ -556,8 +588,8 @@ void IdentityGetAuthTokenFunction::OnMintTokenFailure(
break;
}
- CompleteFunctionWithError(std::string(identity_constants::kAuthFailure) +
- error.ToString());
+ CompleteFunctionWithError(
+ IdentityGetAuthTokenError::FromMintTokenAuthError(error.ToString()));
}
void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
@@ -614,6 +646,20 @@ void IdentityGetAuthTokenFunction::OnRefreshTokenUpdatedForAccount(
}
}
+bool IdentityGetAuthTokenFunction::TryRecoverFromServiceAuthError(
+ const GoogleServiceAuthError& error) {
+ // If this is really an authentication error and not just a transient
+ // network error, then we show signin UI if appropriate.
+ if (error.state() != GoogleServiceAuthError::CONNECTION_FAILED &&
+ error.state() != GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
+ if (ShouldStartSigninFlow()) {
+ StartSigninFlow();
+ return true;
+ }
+ }
+ return false;
+}
+
void IdentityGetAuthTokenFunction::OnPrimaryAccountSet(
const CoreAccountInfo& primary_account_info) {
if (account_listening_mode_ != AccountListeningMode::kListeningPrimaryAccount)
@@ -635,7 +681,8 @@ void IdentityGetAuthTokenFunction::OnPrimaryAccountSet(
void IdentityGetAuthTokenFunction::SigninFailed() {
TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "SigninFailed", this);
- CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+ CompleteFunctionWithError(IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kSignInFailed));
}
void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
@@ -643,43 +690,40 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
GoogleServiceAuthError service_error,
const std::string& oauth_error) {
CompleteMintTokenFlow();
- std::string error;
+ IdentityGetAuthTokenError error;
switch (failure) {
case GaiaWebAuthFlow::WINDOW_CLOSED:
- error = identity_constants::kUserRejected;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kGaiaFlowRejected);
break;
case GaiaWebAuthFlow::INVALID_REDIRECT:
- error = identity_constants::kInvalidRedirect;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kInvalidRedirect);
break;
case GaiaWebAuthFlow::SERVICE_AUTH_ERROR:
- // If this is really an authentication error and not just a transient
- // network error, then we show signin UI if appropriate.
- if (service_error.state() != GoogleServiceAuthError::CONNECTION_FAILED &&
- service_error.state() !=
- GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
- if (ShouldStartSigninFlow()) {
- StartSigninFlow();
- return;
- }
+ if (TryRecoverFromServiceAuthError(service_error)) {
+ return;
}
- error = std::string(identity_constants::kAuthFailure) +
- service_error.ToString();
+ error = IdentityGetAuthTokenError::FromGaiaFlowAuthError(
+ service_error.ToString());
break;
case GaiaWebAuthFlow::OAUTH_ERROR:
- error = MapOAuth2ErrorToDescription(oauth_error);
+ error = IdentityGetAuthTokenError::FromOAuth2Error(oauth_error);
break;
case GaiaWebAuthFlow::LOAD_FAILED:
- error = identity_constants::kPageLoadFailure;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kPageLoadFailure);
break;
default:
NOTREACHED() << "Unexpected error from gaia web auth flow: " << failure;
- error = identity_constants::kInvalidRedirect;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kInvalidRedirect);
break;
}
@@ -706,27 +750,36 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure failure) {
CompleteMintTokenFlow();
- std::string error;
+ IdentityGetAuthTokenError error;
switch (failure) {
case GaiaRemoteConsentFlow::WINDOW_CLOSED:
- error = identity_constants::kUserRejected;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kRemoteConsentFlowRejected);
break;
case GaiaRemoteConsentFlow::SET_ACCOUNTS_IN_COOKIE_FAILED:
- error = identity_constants::kSetAccountsInCookieFailure;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kSetAccountsInCookieFailure);
break;
case GaiaRemoteConsentFlow::LOAD_FAILED:
- error = identity_constants::kPageLoadFailure;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kRemoteConsentPageLoadFailure);
break;
case GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT:
- error = identity_constants::kInvalidConsentResult;
+ error = IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kInvalidConsentResult);
break;
case GaiaRemoteConsentFlow::NO_GRANT:
- error = identity_constants::kNoGrant;
+ error =
+ IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::kNoGrant);
+ break;
+
+ case GaiaRemoteConsentFlow::NONE:
+ NOTREACHED();
break;
}
@@ -739,13 +792,15 @@ void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowApproved(
TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
"identity", "OnGaiaRemoteConsentFlowApproved", this, "gaia_id", gaia_id);
DCHECK(!consent_result.empty());
+ remote_consent_approved_ = true;
base::Optional<AccountInfo> account =
IdentityManagerFactory::GetForProfile(GetProfile())
->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(gaia_id);
if (!account) {
CompleteMintTokenFlow();
- CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+ CompleteFunctionWithError(IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kRemoteConsentUserNotSignedIn));
return;
}
@@ -755,7 +810,8 @@ void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowApproved(
->GetPrimaryAccountId();
if (primary_account_id != account->account_id) {
CompleteMintTokenFlow();
- CompleteFunctionWithError(identity_constants::kUserNonPrimary);
+ CompleteFunctionWithError(IdentityGetAuthTokenError(
+ IdentityGetAuthTokenError::State::kRemoteConsentUserNonPrimary));
return;
}
}
@@ -795,8 +851,13 @@ void IdentityGetAuthTokenFunction::OnGetAccessTokenComplete(
TRACE_EVENT_NESTABLE_ASYNC_END1("identity", "GetAccessToken", this, "error",
error.ToString());
- OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error,
- std::string());
+ CompleteMintTokenFlow();
+ if (TryRecoverFromServiceAuthError(error)) {
+ return;
+ }
+ CompleteFunctionWithError(
+ IdentityGetAuthTokenError::FromGetAccessTokenAuthError(
+ error.ToString()));
}
}
@@ -841,7 +902,8 @@ void IdentityGetAuthTokenFunction::OnIdentityAPIShutdown() {
->mint_queue()
->RequestCancel(token_key_, this);
- CompleteFunctionWithError(identity_constants::kCanceled);
+ CompleteFunctionWithError(
+ IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::kCanceled));
}
#if defined(OS_CHROMEOS)
@@ -964,19 +1026,6 @@ bool IdentityGetAuthTokenFunction::HasRefreshTokenForTokenKeyAccount() const {
return identity_manager->HasAccountWithRefreshToken(token_key_.account_id);
}
-std::string IdentityGetAuthTokenFunction::MapOAuth2ErrorToDescription(
- const std::string& error) {
- const char kOAuth2ErrorAccessDenied[] = "access_denied";
- const char kOAuth2ErrorInvalidScope[] = "invalid_scope";
-
- if (error == kOAuth2ErrorAccessDenied)
- return std::string(identity_constants::kUserRejected);
- else if (error == kOAuth2ErrorInvalidScope)
- return std::string(identity_constants::kInvalidScopes);
- else
- return std::string(identity_constants::kAuthFailure) + error;
-}
-
std::string IdentityGetAuthTokenFunction::GetOAuth2ClientId() const {
const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
std::string client_id = oauth2_info.client_id;
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 77dae78c32d..48b802ef28c 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
@@ -28,6 +28,7 @@ struct AccessTokenInfo;
} // namespace signin
namespace extensions {
+class IdentityGetAuthTokenError;
// identity.getAuthToken fetches an OAuth 2 function for the
// caller. The request has three sub-flows: non-interactive,
@@ -155,6 +156,11 @@ class IdentityGetAuthTokenFunction : public ExtensionFunction,
void OnPrimaryAccountSet(
const CoreAccountInfo& primary_account_info) override;
+ // Attempts to show the signin UI after the service auth error if this error
+ // isn't transient.
+ // Returns true iff the signin flow was triggered.
+ bool TryRecoverFromServiceAuthError(const GoogleServiceAuthError& error);
+
// ExtensionFunction:
ResponseAction Run() override;
@@ -162,7 +168,7 @@ class IdentityGetAuthTokenFunction : public ExtensionFunction,
void StartAsyncRun();
void CompleteAsyncRun(ResponseValue response);
void CompleteFunctionWithResult(const std::string& access_token);
- void CompleteFunctionWithError(const std::string& error);
+ void CompleteFunctionWithError(const IdentityGetAuthTokenError& error);
// Whether a signin flow should be initiated in the user's current state.
bool ShouldStartSigninFlow();
@@ -202,10 +208,6 @@ class IdentityGetAuthTokenFunction : public ExtensionFunction,
// Checks if there is a master login token to mint tokens for the extension.
bool HasRefreshTokenForTokenKeyAccount() const;
- // Maps OAuth2 protocol errors to an error message returned to the
- // developer in chrome.runtime.lastError.
- std::string MapOAuth2ErrorToDescription(const std::string& error);
-
std::string GetOAuth2ClientId() const;
// Returns true if extensions are restricted to the primary account.
@@ -231,6 +233,8 @@ class IdentityGetAuthTokenFunction : public ExtensionFunction,
RemoteConsentResolutionData resolution_data_;
std::unique_ptr<GaiaRemoteConsentFlow> gaia_remote_consent_flow_;
std::string consent_result_;
+ // Added for debugging https://crbug.com/1091423.
+ bool remote_consent_approved_ = false;
// Invoked when IdentityAPI is shut down.
std::unique_ptr<base::CallbackList<void()>::Subscription>
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 de1e3443c03..c3c748e6d98 100644
--- a/chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -80,7 +80,7 @@ WebAuthFlow::WebAuthFlow(Delegate* delegate,
}
WebAuthFlow::~WebAuthFlow() {
- DCHECK(delegate_ == NULL);
+ DCHECK(!delegate_);
// Stop listening to notifications first since some of the code
// below may generate notifications.
@@ -134,7 +134,7 @@ void WebAuthFlow::Start() {
}
void WebAuthFlow::DetachDelegateAndDelete() {
- delegate_ = NULL;
+ delegate_ = nullptr;
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
@@ -170,7 +170,7 @@ void WebAuthFlow::OnAppWindowAdded(AppWindow* app_window) {
void WebAuthFlow::OnAppWindowRemoved(AppWindow* app_window) {
if (app_window->window_key() == app_window_key_ &&
app_window->extension_id() == extension_misc::kIdentityApiUiAppId) {
- app_window_ = NULL;
+ app_window_ = nullptr;
registrar_.RemoveAll();
WebContentsObserver::Observe(nullptr);
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 1d58c0f6f7e..60b1c97a814 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
@@ -12,7 +12,6 @@
#include "base/macros.h"
#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"
@@ -201,7 +200,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
success_ = cancel_;
quit_called_ = true;
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, quit_closure_);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, quit_closure_);
}
void Shutdown() {
@@ -210,7 +209,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
image_writer_utility_client_->Shutdown();
quit_called_ = true;
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, quit_closure_);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, quit_closure_);
}
static void FillFile(const base::FilePath& path, char pattern) {
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 608842bfe5d..582b050d487 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -8,7 +8,6 @@
#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"
@@ -20,8 +19,6 @@
namespace extensions {
namespace image_writer {
-using content::BrowserThread;
-
namespace {
const int kMD5BufferSize = 1024;
@@ -129,16 +126,16 @@ void Operation::Finish() {
CleanUp();
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&OperationManager::OnComplete, manager_, extension_id_));
}
void Operation::Error(const std::string& error_message) {
DCHECK(IsRunningInCorrectSequence());
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&OperationManager::OnError, manager_, extension_id_,
stage_, progress_, error_message));
@@ -158,8 +155,8 @@ void Operation::SetProgress(int progress) {
progress_ = progress;
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&OperationManager::OnProgress, manager_,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&OperationManager::OnProgress, manager_,
extension_id_, stage_, progress_));
}
@@ -172,8 +169,8 @@ void Operation::SetStage(image_writer_api::Stage stage) {
stage_ = stage;
progress_ = 0;
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&OperationManager::OnProgress, manager_,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&OperationManager::OnProgress, manager_,
extension_id_, stage_, progress_));
}
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 5140db323c9..746ca29eacf 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
@@ -5,7 +5,6 @@
#include <stdint.h>
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "chrome/browser/extensions/api/image_writer_private/operation.h"
#include "chromeos/dbus/dbus_thread_manager.h"
@@ -26,8 +25,8 @@ namespace {
void ClearImageBurner() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&ClearImageBurner));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ClearImageBurner));
return;
}
@@ -45,8 +44,8 @@ void Operation::Write(const base::Closure& continuation) {
// Note this has to be run on the FILE thread to avoid concurrent access.
AddCleanUpFunction(base::BindOnce(&ClearImageBurner));
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&Operation::UnmountVolumes, this, continuation));
}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc
index e069f5f485a..bb46532fd22 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc
@@ -15,6 +15,7 @@
#include <memory>
+#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc
index cc3d4473c73..fe3d9928022 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc
@@ -45,7 +45,7 @@ TEST_F(ImageWriterFromFileTest, InvalidFile) {
test_utils_.GetDevicePath().AsUTF8Unsafe(),
base::FilePath(FILE_PATH_LITERAL("/var/tmp")));
- base::DeleteFile(test_utils_.GetImagePath(), false);
+ base::DeleteFile(test_utils_.GetImagePath());
EXPECT_CALL(manager_, OnProgress(kDummyExtensionId, _, _)).Times(0);
EXPECT_CALL(manager_, OnComplete(kDummyExtensionId)).Times(0);
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
index 942e3587a50..6b78d3f8de1 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "chrome/browser/extensions/api/image_writer_private/test_utils.h"
#include "chrome/test/base/testing_profile.h"
@@ -137,15 +136,7 @@ class ImageWriterWriteFromUrlOperationTest : public ImageWriterUnitTestBase {
MockOperationManager manager_;
};
-// Crashes on Tsan. http://crbug.com/859317
-#if defined(THREAD_SANITIZER)
-#define MAYBE_SelectTargetWithoutExtension DISABLED_SelectTargetWithoutExtension
-#define MAYBE_SelectTargetWithExtension DISABLED_SelectTargetWithExtension
-#else
-#define MAYBE_SelectTargetWithoutExtension SelectTargetWithoutExtension
-#define MAYBE_SelectTargetWithExtension SelectTargetWithExtension
-#endif
-TEST_F(ImageWriterWriteFromUrlOperationTest, MAYBE_SelectTargetWithoutExtension) {
+TEST_F(ImageWriterWriteFromUrlOperationTest, SelectTargetWithoutExtension) {
scoped_refptr<WriteFromUrlOperationForTest> operation =
CreateOperation(GURL("http://localhost/foo/bar"), "");
@@ -160,7 +151,7 @@ TEST_F(ImageWriterWriteFromUrlOperationTest, MAYBE_SelectTargetWithoutExtension)
content::RunAllTasksUntilIdle();
}
-TEST_F(ImageWriterWriteFromUrlOperationTest, MAYBE_SelectTargetWithExtension) {
+TEST_F(ImageWriterWriteFromUrlOperationTest, SelectTargetWithExtension) {
scoped_refptr<WriteFromUrlOperationForTest> operation =
CreateOperation(GURL("http://localhost/foo/bar.zip"), "");
@@ -173,9 +164,6 @@ TEST_F(ImageWriterWriteFromUrlOperationTest, MAYBE_SelectTargetWithExtension) {
operation->Cancel();
}
-#undef MAYBE_SelectTargetWithoutExtension
-#undef MAYBE_SelectTargetWithExtension
-
TEST_F(ImageWriterWriteFromUrlOperationTest, DownloadFile) {
// This test actually triggers the URL fetch code, which will drain the
@@ -242,10 +230,8 @@ TEST_F(ImageWriterWriteFromUrlOperationTest, VerifyFile) {
// soon.
operation->VerifyDownload(base::Bind(
[](base::OnceClosure quit_closure) {
- base::PostTask(
- FROM_HERE,
- {content::BrowserThread::UI, base::TaskPriority::USER_VISIBLE},
- std::move(quit_closure));
+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_VISIBLE})
+ ->PostTask(FROM_HERE, std::move(quit_closure));
},
run_loop.QuitClosure()));
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 62d7d390b82..37ea54f92ab 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
@@ -10,14 +10,14 @@
#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"
+#include "ui/base/ime/chromeos/ime_bridge.h"
namespace input_ime = extensions::api::input_ime;
namespace KeyEventHandled = extensions::api::input_ime::KeyEventHandled;
namespace SetComposition = extensions::api::input_ime::SetComposition;
namespace CommitText = extensions::api::input_ime::CommitText;
namespace SendKeyEvents = extensions::api::input_ime::SendKeyEvents;
-using input_method::InputMethodEngineBase;
+using chromeos::InputMethodEngineBase;
namespace {
const char kErrorRouterNotAvailable[] = "The router is not available.";
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 0c4eaac6687..934a51efa74 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
@@ -14,8 +14,8 @@
#include "base/scoped_observer.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "chrome/browser/chromeos/input_method/input_method_engine_base.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/input_method/input_method_engine_base.h"
#include "chrome/common/extensions/api/input_ime.h"
#include "components/keyed_service/core/keyed_service.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
@@ -31,8 +31,6 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h"
-#elif defined(OS_LINUX) || defined(OS_WIN)
-#include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h"
#endif // defined(OS_CHROMEOS)
class Profile;
@@ -40,19 +38,21 @@ class Profile;
namespace ui {
class IMEEngineHandlerInterface;
-class ImeObserver : public input_method::InputMethodEngineBase::Observer {
+using chromeos::InputMethodEngineBase;
+
+class ImeObserver : public InputMethodEngineBase::Observer {
public:
ImeObserver(const std::string& extension_id, Profile* profile);
~ImeObserver() override = default;
- // input_method::InputMethodEngineBase::Observer overrides.
+ // InputMethodEngineBase::Observer overrides.
void OnActivate(const std::string& component_id) override;
void OnFocus(const IMEEngineHandlerInterface::InputContext& context) override;
void OnBlur(int context_id) override;
void OnKeyEvent(
const std::string& component_id,
- const input_method::InputMethodEngineBase::KeyboardEvent& event,
+ const InputMethodEngineBase::KeyboardEvent& event,
IMEEngineHandlerInterface::KeyEventDoneCallback key_data) override;
void OnReset(const std::string& component_id) override;
void OnDeactivated(const std::string& component_id) 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 b9dfada4e67..e58f51d6e4f 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
@@ -13,6 +13,7 @@
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/input_method/assistive_window_properties.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"
@@ -43,6 +44,8 @@ namespace SetCursorPosition = extensions::api::input_ime::SetCursorPosition;
namespace SetCandidates = extensions::api::input_ime::SetCandidates;
namespace SetCandidateWindowProperties =
extensions::api::input_ime::SetCandidateWindowProperties;
+namespace SetAssistiveWindowProperties =
+ extensions::api::input_ime::SetAssistiveWindowProperties;
namespace ClearComposition = extensions::api::input_ime::ClearComposition;
namespace OnCompositionBoundsChanged =
extensions::api::input_method_private::OnCompositionBoundsChanged;
@@ -54,9 +57,9 @@ namespace SetSelectionRange =
extensions::api::input_method_private::SetSelectionRange;
namespace FinishComposingText =
extensions::api::input_method_private::FinishComposingText;
-using ui::IMEEngineHandlerInterface;
-using input_method::InputMethodEngineBase;
using chromeos::InputMethodEngine;
+using chromeos::InputMethodEngineBase;
+using ui::IMEEngineHandlerInterface;
namespace {
const char kErrorEngineNotAvailable[] = "The engine is not available.";
@@ -99,6 +102,43 @@ keyboard::KeyboardConfig GetKeyboardConfig() {
return ChromeKeyboardControllerClient::Get()->GetKeyboardConfig();
}
+ui::ime::AssistiveWindowType ConvertAssistiveWindowType(
+ input_ime::AssistiveWindowType type) {
+ switch (type) {
+ case input_ime::ASSISTIVE_WINDOW_TYPE_NONE:
+ return ui::ime::AssistiveWindowType::kNone;
+ case input_ime::ASSISTIVE_WINDOW_TYPE_UNDO:
+ return ui::ime::AssistiveWindowType::kUndoWindow;
+ }
+}
+
+input_ime::AssistiveWindowButton ConvertAssistiveWindowButton(
+ const ui::ime::ButtonId id) {
+ switch (id) {
+ case ui::ime::ButtonId::kNone:
+ case ui::ime::ButtonId::kSmartInputsSettingLink:
+ case ui::ime::ButtonId::kSuggestion:
+ case ui::ime::ButtonId::kLearnMore:
+ return input_ime::ASSISTIVE_WINDOW_BUTTON_NONE;
+ case ui::ime::ButtonId::kUndo:
+ return input_ime::ASSISTIVE_WINDOW_BUTTON_UNDO;
+ case ui::ime::ButtonId::kAddToDictionary:
+ return input_ime::ASSISTIVE_WINDOW_BUTTON_ADDTODICTIONARY;
+ }
+}
+
+input_ime::AssistiveWindowType ConvertAssistiveWindowType(
+ const ui::ime::AssistiveWindowType& type) {
+ switch (type) {
+ case ui::ime::AssistiveWindowType::kNone:
+ case ui::ime::AssistiveWindowType::kEmojiSuggestion:
+ case ui::ime::AssistiveWindowType::kPersonalInfoSuggestion:
+ return input_ime::AssistiveWindowType::ASSISTIVE_WINDOW_TYPE_NONE;
+ case ui::ime::AssistiveWindowType::kUndoWindow:
+ return input_ime::AssistiveWindowType::ASSISTIVE_WINDOW_TYPE_UNDO;
+ }
+}
+
class ImeObserverChromeOS : public ui::ImeObserver {
public:
ImeObserverChromeOS(const std::string& extension_id, Profile* profile)
@@ -106,7 +146,7 @@ class ImeObserverChromeOS : public ui::ImeObserver {
~ImeObserverChromeOS() override = default;
- // input_method::InputMethodEngineBase::Observer overrides.
+ // chromeos::InputMethodEngineBase::Observer overrides.
void OnInputContextUpdate(
const IMEEngineHandlerInterface::InputContext& context) override {
if (extension_id_.empty() ||
@@ -257,6 +297,33 @@ class ImeObserverChromeOS : public ui::ImeObserver {
ImeObserver::OnFocus(context);
}
+ void OnAssistiveWindowButtonClicked(
+ const ui::ime::AssistiveWindowButton& button) override {
+ if (extension_id_.empty() ||
+ !HasListener(input_ime::OnAssistiveWindowButtonClicked::kEventName)) {
+ return;
+ }
+ input_ime::OnAssistiveWindowButtonClicked::Details details;
+ details.button_id = ConvertAssistiveWindowButton(button.id);
+ details.window_type = ConvertAssistiveWindowType(button.window_type);
+
+ std::unique_ptr<base::ListValue> args(
+ input_ime::OnAssistiveWindowButtonClicked::Create(details));
+ DispatchEventToExtension(
+ extensions::events::INPUT_IME_ON_ASSISTIVE_WINDOW_BUTTON_CLICKED,
+ input_ime::OnAssistiveWindowButtonClicked::kEventName, std::move(args));
+ }
+
+ void OnSuggestionsChanged(
+ const std::vector<std::string>& suggestions) override {
+ std::unique_ptr<base::ListValue> args(
+ input_method_private::OnSuggestionsChanged::Create(suggestions));
+ DispatchEventToExtension(
+ extensions::events::INPUT_IME_ON_SUGGESTIONS_CHANGED,
+ input_method_private::OnSuggestionsChanged::kEventName,
+ std::move(args));
+ }
+
private:
// ui::ImeObserver overrides.
void DispatchEventToExtension(
@@ -588,6 +655,33 @@ ExtensionFunction::ResponseAction InputImeHideInputViewFunction::Run() {
}
ExtensionFunction::ResponseAction
+InputImeSetAssistiveWindowPropertiesFunction::Run() {
+ std::string error;
+ InputMethodEngine* engine = GetEngineIfActive(
+ Profile::FromBrowserContext(browser_context()), extension_id(), &error);
+ if (!engine) {
+ return RespondNow(Error(InformativeError(error, function_name())));
+ }
+ std::unique_ptr<SetAssistiveWindowProperties::Params> parent_params(
+ SetAssistiveWindowProperties::Params::Create(*args_));
+ const SetAssistiveWindowProperties::Params::Parameters& params =
+ parent_params->parameters;
+ const input_ime::AssistiveWindowProperties& window = params.properties;
+ chromeos::AssistiveWindowProperties assistive_window;
+
+ assistive_window.visible = window.visible;
+ assistive_window.type = ConvertAssistiveWindowType(window.type);
+ if (window.announce_string)
+ assistive_window.announce_string = *window.announce_string;
+
+ engine->SetAssistiveWindowProperties(params.context_id, assistive_window,
+ &error);
+ if (!error.empty())
+ return RespondNow(Error(InformativeError(error, function_name())));
+ return RespondNow(OneArgument(std::make_unique<base::Value>(true)));
+}
+
+ExtensionFunction::ResponseAction
InputImeSetCandidateWindowPropertiesFunction::Run() {
std::unique_ptr<SetCandidateWindowProperties::Params> parent_params(
SetCandidateWindowProperties::Params::Create(*args_));
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
index 36c279aba15..aa03b45186b 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
@@ -68,6 +68,18 @@ class InputImeSetCursorPositionFunction : public ExtensionFunction {
ResponseAction Run() override;
};
+class InputImeSetAssistiveWindowPropertiesFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("input.ime.setAssistiveWindowProperties",
+ INPUT_IME_SETASSISTIVEWINDOWPROPERTIES)
+
+ protected:
+ ~InputImeSetAssistiveWindowPropertiesFunction() override = default;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+};
+
class InputImeSetMenuItemsFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("input.ime.setMenuItems", INPUT_IME_SETMENUITEMS)
@@ -176,7 +188,7 @@ class InputImeEventRouter : public InputImeEventRouterBase {
void UnregisterAllImes(const std::string& extension_id);
chromeos::InputMethodEngine* GetEngine(const std::string& extension_id);
- input_method::InputMethodEngineBase* GetEngineIfActive(
+ chromeos::InputMethodEngineBase* GetEngineIfActive(
const std::string& extension_id,
std::string* error) override;
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
deleted file mode 100644
index 64c0f13ffe2..00000000000
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
+++ /dev/null
@@ -1,416 +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.
-
-// This file is for non-chromeos (win & linux) functions, such as
-// chrome.input.ime.activate, chrome.input.ime.createWindow and
-// chrome.input.ime.onSelectionChanged.
-// TODO(azurewei): May refactor the code structure by using delegate or
-// redesign the API to remove this platform-specific file in the future.
-
-#include "chrome/browser/extensions/api/input_ime/input_ime_api.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/values.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/input_method/input_method_engine.h"
-#include "chrome/common/extensions/api/input_ime.h"
-#include "extensions/browser/extension_prefs.h"
-#include "ui/base/ime/ime_bridge.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace input_ime = extensions::api::input_ime;
-namespace OnCompositionBoundsChanged =
- extensions::api::input_ime::OnCompositionBoundsChanged;
-using ui::IMEEngineHandlerInterface;
-using input_method::InputMethodEngine;
-using input_method::InputMethodEngineBase;
-
-namespace input_ime = extensions::api::input_ime;
-
-namespace {
-
-const char kErrorEngineNotActive[] = "The engine is not active.";
-const char kErrorRouterNotAvailable[] = "The router is not available.";
-const char kErrorPermissionDenied[] = "User denied permission.";
-const char kErrorCouldNotFindActiveBrowser[] =
- "Cannot find the active browser.";
-const char kErrorNotCalledFromUserAction[] =
- "This API is only allowed to be called from a user action.";
-
-// A preference determining whether to hide the warning bubble next time.
-// Not used for now.
-const char kPrefWarningBubbleNeverShow[] = "skip_ime_warning_bubble";
-
-// A preference to see whether the API has never been called, or it's the first
-// time to call since loaded the extension.
-// This is used from make an exception for user_gesture checking: no need the
-// check when restarting chrome.
-const char kPrefNeverActivatedSinceLoaded[] = "never_activated_since_loaded";
-
-// A preference to see whether the extension is the last active extension.
-const char kPrefLastActiveEngine[] = "last_activated_ime_engine";
-
-class ImeBridgeObserver : public ui::IMEBridgeObserver {
- public:
- void OnRequestSwitchEngine() override {
- Browser* browser = chrome::FindLastActive();
- if (!browser)
- return;
- extensions::InputImeEventRouter* router =
- extensions::GetInputImeEventRouter(browser->profile());
- if (!router)
- return;
- ui::IMEBridge::Get()->SetCurrentEngineHandler(router->active_engine());
- }
- void OnInputContextHandlerChanged() override {}
-};
-
-class ImeObserverNonChromeOS : public ui::ImeObserver {
- public:
- ImeObserverNonChromeOS(const std::string& extension_id, Profile* profile)
- : ImeObserver(extension_id, profile) {}
-
- ~ImeObserverNonChromeOS() override = default;
-
- void OnCompositionBoundsChanged(
- const std::vector<gfx::Rect>& bounds) override {
- if (extension_id_.empty() || bounds.empty() ||
- !HasListener(OnCompositionBoundsChanged::kEventName))
- return;
-
- std::vector<input_ime::Bounds> bounds_list;
- for (const auto& bound : bounds) {
- input_ime::Bounds bounds_value;
- bounds_value.left = bound.x();
- bounds_value.top = bound.y();
- bounds_value.width = bound.width();
- bounds_value.height = bound.height();
- bounds_list.push_back(std::move(bounds_value));
- }
-
- std::unique_ptr<base::ListValue> args(
- OnCompositionBoundsChanged::Create(bounds_list));
-
- DispatchEventToExtension(
- extensions::events::INPUT_IME_ON_COMPOSITION_BOUNDS_CHANGED,
- OnCompositionBoundsChanged::kEventName, std::move(args));
- }
-
- private:
- // ImeObserver overrides.
- void DispatchEventToExtension(
- extensions::events::HistogramValue histogram_value,
- const std::string& event_name,
- std::unique_ptr<base::ListValue> args) override {
- auto event = std::make_unique<extensions::Event>(
- histogram_value, event_name, std::move(args), profile_);
- extensions::EventRouter::Get(profile_)
- ->DispatchEventToExtension(extension_id_, std::move(event));
- }
-
- std::string GetCurrentScreenType() override { return "normal"; }
-
- DISALLOW_COPY_AND_ASSIGN(ImeObserverNonChromeOS);
-};
-
-} // namespace
-
-namespace extensions {
-
-InputMethodEngine* GetEngineIfActive(content::BrowserContext* browser_context,
- const std::string& extension_id,
- std::string* error) {
- Profile* profile = Profile::FromBrowserContext(browser_context);
- InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
- DCHECK(event_router) << kErrorRouterNotAvailable;
- InputMethodEngine* engine = static_cast<InputMethodEngine*>(
- event_router->GetEngineIfActive(extension_id, error));
- return engine;
-}
-
-void InputImeAPI::OnExtensionLoaded(content::BrowserContext* browser_context,
- const Extension* extension) {
- // No-op if called multiple times.
- ui::IMEBridge::Initialize();
- if (!observer_) {
- observer_ = std::make_unique<ImeBridgeObserver>();
- ui::IMEBridge::Get()->AddObserver(observer_.get());
- }
-
- // Set the preference kPrefNeverActivatedSinceLoaded true to indicate
- // input.ime.activate API has been never called since loaded.
- Profile* profile = Profile::FromBrowserContext(browser_context);
- ExtensionPrefs::Get(profile)->UpdateExtensionPref(
- extension->id(), kPrefNeverActivatedSinceLoaded,
- std::make_unique<base::Value>(true));
-}
-
-void InputImeAPI::OnExtensionUnloaded(content::BrowserContext* browser_context,
- const Extension* extension,
- UnloadedExtensionReason reason) {
- InputImeEventRouter* event_router =
- GetInputImeEventRouter(Profile::FromBrowserContext(browser_context));
- if (event_router) {
- // Records the extension is not the last active IME engine.
- ExtensionPrefs::Get(Profile::FromBrowserContext(browser_context))
- ->UpdateExtensionPref(extension->id(), kPrefLastActiveEngine,
- std::make_unique<base::Value>(false));
- event_router->DeleteInputMethodEngine(extension->id());
- }
-}
-
-void InputImeAPI::OnListenerAdded(const EventListenerInfo& details) {}
-
-InputImeEventRouter::InputImeEventRouter(Profile* profile)
- : InputImeEventRouterBase(profile), active_engine_(nullptr) {}
-
-InputImeEventRouter::~InputImeEventRouter() {
- if (active_engine_)
- DeleteInputMethodEngine(active_engine_->GetExtensionId());
-}
-
-InputMethodEngineBase* InputImeEventRouter::GetEngineIfActive(
- const std::string& extension_id,
- std::string* error) {
- if (ui::IMEBridge::Get()->GetCurrentEngineHandler() && active_engine_ &&
- active_engine_->GetExtensionId() == extension_id) {
- return active_engine_;
- } else {
- LOG(WARNING) << kErrorEngineNotActive << " extension id: " << extension_id;
- *error = kErrorEngineNotActive;
- return nullptr;
- }
-}
-
-void InputImeEventRouter::SetActiveEngine(const std::string& extension_id) {
- // Records the extension is the last active IME engine.
- ExtensionPrefs::Get(GetProfile())
- ->UpdateExtensionPref(extension_id, kPrefLastActiveEngine,
- std::make_unique<base::Value>(true));
- if (active_engine_) {
- if (active_engine_->GetExtensionId() == extension_id) {
- active_engine_->Enable(std::string());
- ui::IMEBridge::Get()->SetCurrentEngineHandler(active_engine_);
- return;
- }
- // Records the extension is not the last active IME engine.
- ExtensionPrefs::Get(GetProfile())
- ->UpdateExtensionPref(active_engine_->GetExtensionId(),
- kPrefLastActiveEngine,
- std::make_unique<base::Value>(false));
- DeleteInputMethodEngine(active_engine_->GetExtensionId());
- }
-
- std::unique_ptr<input_method::InputMethodEngine> engine(
- new input_method::InputMethodEngine());
- std::unique_ptr<InputMethodEngineBase::Observer> observer(
- new ImeObserverNonChromeOS(extension_id, GetProfile()));
- engine->Initialize(std::move(observer), extension_id.c_str(), GetProfile());
- engine->Enable(std::string());
- active_engine_ = engine.release();
- ui::IMEBridge::Get()->SetCurrentEngineHandler(active_engine_);
-}
-
-void InputImeEventRouter::DeleteInputMethodEngine(
- const std::string& extension_id) {
- if (active_engine_ && active_engine_->GetExtensionId() == extension_id) {
- active_engine_->Disable();
- ui::IMEBridge::Get()->SetCurrentEngineHandler(nullptr);
- delete active_engine_;
- active_engine_ = nullptr;
- }
-}
-
-// static
-bool InputImeActivateFunction::disable_bubble_for_testing_ = false;
-
-ExtensionFunction::ResponseAction InputImeActivateFunction::Run() {
- Profile* profile = Profile::FromBrowserContext(browser_context());
- InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
- if (!event_router)
- return RespondNow(
- Error(InformativeError(kErrorEngineNotActive, function_name())));
-
- ExtensionPrefs* prefs = ExtensionPrefs::Get(profile);
-
- bool never_activated_since_loaded = false;
- bool last_active_ime_engine = false;
-
- if (prefs->ReadPrefAsBoolean(extension_id(), kPrefNeverActivatedSinceLoaded,
- &never_activated_since_loaded) &&
- never_activated_since_loaded &&
- prefs->ReadPrefAsBoolean(extension_id(), kPrefLastActiveEngine,
- &last_active_ime_engine) &&
- last_active_ime_engine) {
- // If the extension is the last active IME engine, and the API is called at
- // loading the extension, we can tell the API is called from restarting
- // chrome. No need for user gesture checking.
- event_router->SetActiveEngine(extension_id());
- ExtensionPrefs::Get(profile)->UpdateExtensionPref(
- extension_id(), kPrefNeverActivatedSinceLoaded,
- std::make_unique<base::Value>(false));
- return RespondNow(NoArguments());
- }
- // The API has already been called at least once.
- ExtensionPrefs::Get(profile)->UpdateExtensionPref(
- extension_id(), kPrefNeverActivatedSinceLoaded,
- std::make_unique<base::Value>(false));
-
- // Otherwise, this API is only allowed to be called from a user action.
- if (!user_gesture())
- return RespondNow(Error(
- InformativeError(kErrorNotCalledFromUserAction, function_name())));
-
- // Disable using the warning bubble for testing.
- if (disable_bubble_for_testing_) {
- event_router->SetActiveEngine(extension_id());
- return RespondNow(NoArguments());
- }
-
- // Disables the warning bubble since we don't need run-time checking anymore.
- bool warning_bubble_never_show = true;
- if (warning_bubble_never_show) {
- // If user allows to activate the extension without showing the warning
- // bubble, sets the active engine directly.
- // Otherwise, the extension will be activated when the user presses the 'OK'
- // button on the warning bubble.
- event_router->SetActiveEngine(extension_id());
- return RespondNow(NoArguments());
- }
-
- // TODO(azurewei): Remove the warning bubble related codes.
- Browser* browser = chrome::FindLastActiveWithProfile(profile);
- if (!browser)
- return RespondNow(Error(
- InformativeError(kErrorCouldNotFindActiveBrowser, function_name())));
-
- // Creates and shows the warning bubble. The ImeWarningBubble is self-owned,
- // it deletes itself when closed.
- browser->window()->ShowImeWarningBubble(
- extension(),
- base::Bind(&InputImeActivateFunction::OnPermissionBubbleFinished, this));
- return RespondLater();
-}
-
-void InputImeActivateFunction::OnPermissionBubbleFinished(
- ImeWarningBubblePermissionStatus status) {
- if (status == ImeWarningBubblePermissionStatus::DENIED ||
- status == ImeWarningBubblePermissionStatus::ABORTED) {
- // Fails to activate the extension.
- Respond(Error(InformativeError(kErrorPermissionDenied, function_name())));
- return;
- }
-
- DCHECK(status == ImeWarningBubblePermissionStatus::GRANTED ||
- status == ImeWarningBubblePermissionStatus::GRANTED_AND_NEVER_SHOW);
-
- // Activates this extension if user presses the 'OK' button.
- Profile* profile = Profile::FromBrowserContext(browser_context());
- InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
- if (!event_router) {
- Respond(Error(InformativeError(kErrorEngineNotActive, function_name())));
- return;
- }
- event_router->SetActiveEngine(extension_id());
-
- if (status == ImeWarningBubblePermissionStatus::GRANTED_AND_NEVER_SHOW) {
- // Updates the extension preference if user checks the 'Never show this
- // again' check box. So we can activate the extension directly next time.
- ExtensionPrefs::Get(profile)->UpdateExtensionPref(
- extension_id(), kPrefWarningBubbleNeverShow,
- std::make_unique<base::Value>(true));
- }
-
- Respond(NoArguments());
-}
-
-ExtensionFunction::ResponseAction InputImeDeactivateFunction::Run() {
- std::string error;
- InputMethodEngine* engine =
- GetEngineIfActive(browser_context(), extension_id(), &error);
- if (!engine) {
- return RespondNow(Error(InformativeError(error, function_name())));
- }
- ui::IMEBridge::Get()->SetCurrentEngineHandler(nullptr);
- if (engine)
- engine->CloseImeWindows();
- return RespondNow(NoArguments());
-}
-
-ExtensionFunction::ResponseAction InputImeCreateWindowFunction::Run() {
- // Using input_ime::CreateWindow::Params::Create() causes the link errors on
- // Windows, only if the method name is 'createWindow'.
- // So doing the by-hand parameter unpacking here.
- // TODO(shuchen,rdevlin.cronin): investigate the root cause for the link
- // errors.
- const base::DictionaryValue* params = nullptr;
- args_->GetDictionary(0, &params);
- EXTENSION_FUNCTION_VALIDATE(params);
- input_ime::CreateWindowOptions options;
- input_ime::CreateWindowOptions::Populate(*params, &options);
-
- gfx::Rect bounds(0, 0, 100, 100); // Default bounds.
- if (options.bounds.get()) {
- bounds.set_x(options.bounds->left);
- bounds.set_y(options.bounds->top);
- bounds.set_width(options.bounds->width);
- bounds.set_height(options.bounds->height);
- }
-
- std::string error;
- InputMethodEngine* engine =
- GetEngineIfActive(browser_context(), extension_id(), &error);
- if (!engine)
- return RespondNow(Error(InformativeError(error, function_name())));
-
- int frame_id = engine->CreateImeWindow(
- extension(), render_frame_host(),
- options.url.get() ? *options.url : url::kAboutBlankURL,
- options.window_type == input_ime::WINDOW_TYPE_FOLLOWCURSOR
- ? ui::ImeWindow::FOLLOW_CURSOR
- : ui::ImeWindow::NORMAL,
- bounds, &error);
- if (!frame_id)
- return RespondNow(Error(InformativeError(error, function_name())));
-
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->Set("frameId", std::make_unique<base::Value>(frame_id));
-
- return RespondNow(OneArgument(std::move(result)));
-}
-
-ExtensionFunction::ResponseAction InputImeShowWindowFunction::Run() {
- std::string error;
- InputMethodEngine* engine =
- GetEngineIfActive(browser_context(), extension_id(), &error);
- if (!engine)
- return RespondNow(Error(InformativeError(error, function_name())));
-
- std::unique_ptr<api::input_ime::ShowWindow::Params> params(
- api::input_ime::ShowWindow::Params::Create(*args_));
- EXTENSION_FUNCTION_VALIDATE(params.get());
- engine->ShowImeWindow(params->window_id);
- return RespondNow(NoArguments());
-}
-
-ExtensionFunction::ResponseAction InputImeHideWindowFunction::Run() {
- std::string error;
- InputMethodEngine* engine =
- GetEngineIfActive(browser_context(), extension_id(), &error);
- if (!engine)
- return RespondNow(Error(InformativeError(error, function_name())));
-
- std::unique_ptr<api::input_ime::HideWindow::Params> params(
- api::input_ime::HideWindow::Params::Create(*args_));
- EXTENSION_FUNCTION_VALIDATE(params.get());
- engine->HideImeWindow(params->window_id);
- return RespondNow(NoArguments());
-}
-
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
deleted file mode 100644
index ff9a920c06b..00000000000
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_NONCHROMEOS_H_
-#define CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_NONCHROMEOS_H_
-
-#include "chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h"
-#include "chrome/browser/profiles/profile.h"
-#include "extensions/browser/extension_function.h"
-
-class Profile;
-
-namespace input_method {
-class InputMethodEngine;
-} // namespace input_method
-
-// The status indicates whether the permission has been granted or denied when
-// the IME warning bubble has been closed.
-enum class ImeWarningBubblePermissionStatus {
- GRANTED,
- GRANTED_AND_NEVER_SHOW,
- DENIED,
- ABORTED
-};
-
-namespace extensions {
-
-class InputImeEventRouterBase;
-
-class InputImeEventRouter : public InputImeEventRouterBase {
- public:
- explicit InputImeEventRouter(Profile* profile);
- ~InputImeEventRouter() override;
-
- // Gets the input method engine if the extension is active.
- input_method::InputMethodEngineBase* GetEngineIfActive(
- const std::string& extension_id,
- std::string* error) override;
-
- // Actives the extension with new input method engine, and deletes the
- // previous engine if another extension was active.
- void SetActiveEngine(const std::string& extension_id);
-
- input_method::InputMethodEngine* active_engine() {
- return active_engine_;
- }
-
- // Deletes the current input method engine of the specific extension.
- void DeleteInputMethodEngine(const std::string& extension_id);
-
- private:
- // The active input method engine.
- input_method::InputMethodEngine* active_engine_;
-
- DISALLOW_COPY_AND_ASSIGN(InputImeEventRouter);
-};
-
-class InputImeCreateWindowFunction : public ExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("input.ime.createWindow", INPUT_IME_CREATEWINDOW)
-
- protected:
- ~InputImeCreateWindowFunction() override = default;
-
- // ExtensionFunction:
- ExtensionFunction::ResponseAction Run() override;
-};
-
-class InputImeShowWindowFunction : public ExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("input.ime.showWindow", INPUT_IME_SHOWWINDOW)
-
- protected:
- ~InputImeShowWindowFunction() override = default;
-
- // ExtensionFunction:
- ExtensionFunction::ResponseAction Run() override;
-};
-
-class InputImeHideWindowFunction : public ExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("input.ime.hideWindow", INPUT_IME_HIDEWINDOW)
-
- protected:
- ~InputImeHideWindowFunction() override = default;
-
- // ExtensionFunction:
- ExtensionFunction::ResponseAction Run() override;
-};
-
-class InputImeActivateFunction : public ExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("input.ime.activate", INPUT_IME_ACTIVATE)
-
- // During testing we can disable showing a warning bubble by setting this flag
- // to true, so that the extension can be activated directly.
- static bool disable_bubble_for_testing_;
-
- protected:
- ~InputImeActivateFunction() override = default;
-
- // ExtensionFunction:
- ResponseAction Run() override;
-
- private:
- // Called when the user finishes interacting with the warning bubble.
- // |status| indicates whether the user allows or denies to activate the
- // extension.
- void OnPermissionBubbleFinished(ImeWarningBubblePermissionStatus status);
-};
-
-class InputImeDeactivateFunction : public ExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("input.ime.deactivate", INPUT_IME_DEACTIVATE)
-
- protected:
- ~InputImeDeactivateFunction() override = default;
-
- // ExtensionFunction:
- ResponseAction Run() override;
-};
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_NONCHROMEOS_H_
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h b/chromium/chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h
index 3d832e8e3a9..6d3edec518b 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h
@@ -10,8 +10,8 @@
#include <utility>
#include "base/macros.h"
+#include "chrome/browser/chromeos/input_method/input_method_engine_base.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/input_method/input_method_engine_base.h"
#include "ui/base/ime/ime_engine_handler_interface.h"
namespace extensions {
@@ -22,7 +22,7 @@ class InputImeEventRouterBase {
virtual ~InputImeEventRouterBase();
// Gets the input method engine if the extension is active.
- virtual input_method::InputMethodEngineBase* GetEngineIfActive(
+ virtual chromeos::InputMethodEngineBase* GetEngineIfActive(
const std::string& extension_id,
std::string* error) = 0;
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 340c2c0f3c6..5cc290e45f8 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
@@ -188,7 +188,8 @@ std::vector<std::string> GetSortedThirdPartyIMEs(
LanguageSettingsPrivateGetLanguageListFunction::
LanguageSettingsPrivateGetLanguageListFunction()
- : chrome_details_(this) {}
+ : chrome_details_(this),
+ language_list_(std::make_unique<base::ListValue>()) {}
LanguageSettingsPrivateGetLanguageListFunction::
~LanguageSettingsPrivateGetLanguageListFunction() = default;
@@ -212,7 +213,7 @@ LanguageSettingsPrivateGetLanguageListFunction::Run() {
std::move(spellcheck_languages));
// Build the language list.
- std::unique_ptr<base::ListValue> language_list(new base::ListValue);
+ language_list_->Clear();
#if defined(OS_CHROMEOS)
const std::unordered_set<std::string> allowed_ui_locales(
GetAllowedLanguages(chrome_details_.GetProfile()->GetPrefs()));
@@ -243,7 +244,7 @@ LanguageSettingsPrivateGetLanguageListFunction::Run() {
}
#endif // defined(OS_CHROMEOS)
- language_list->Append(language.ToValue());
+ language_list_->Append(language.ToValue());
}
#if defined(OS_CHROMEOS)
@@ -255,13 +256,54 @@ LanguageSettingsPrivateGetLanguageListFunction::Run() {
language.code = chromeos::extension_ime_util::kArcImeLanguage;
language.display_name =
l10n_util::GetStringUTF8(IDS_SETTINGS_LANGUAGES_KEYBOARD_APPS);
- language_list->Append(language.ToValue());
+ language_list_->Append(language.ToValue());
}
#endif // defined(OS_CHROMEOS)
- return RespondNow(OneArgument(std::move(language_list)));
+#if defined(OS_WIN)
+ if (spellcheck::UseBrowserSpellChecker()) {
+ if (!base::FeatureList::IsEnabled(
+ spellcheck::kWinDelaySpellcheckServiceInit)) {
+ // Platform dictionary support already determined at browser startup.
+ UpdateSupportedPlatformDictionaries();
+ } else {
+ // Asynchronously load the dictionaries to determine platform support.
+ SpellcheckService* service =
+ SpellcheckServiceFactory::GetForContext(browser_context());
+ AddRef(); // Balanced in OnDictionariesInitialized
+ service->InitializeDictionaries(
+ base::BindOnce(&LanguageSettingsPrivateGetLanguageListFunction::
+ OnDictionariesInitialized,
+ base::Unretained(this)));
+ return RespondLater();
+ }
+ }
+#endif // defined(OS_WIN)
+
+ return RespondNow(OneArgument(std::move(language_list_)));
}
+#if defined(OS_WIN)
+void LanguageSettingsPrivateGetLanguageListFunction::
+ OnDictionariesInitialized() {
+ UpdateSupportedPlatformDictionaries();
+ Respond(OneArgument(std::move(language_list_)));
+ // Matches the AddRef in Run().
+ Release();
+}
+
+void LanguageSettingsPrivateGetLanguageListFunction::
+ UpdateSupportedPlatformDictionaries() {
+ SpellcheckService* service =
+ SpellcheckServiceFactory::GetForContext(browser_context());
+ for (auto& language_val : language_list_->GetList()) {
+ if (service->UsesWindowsDictionary(*language_val.FindStringKey("code"))) {
+ language_val.SetBoolKey("supportsSpellcheck", new bool(true));
+ }
+ }
+}
+#endif // defined(OS_WIN)
+
LanguageSettingsPrivateEnableLanguageFunction::
LanguageSettingsPrivateEnableLanguageFunction()
: chrome_details_(this) {}
@@ -291,7 +333,6 @@ LanguageSettingsPrivateEnableLanguageFunction::Run() {
}
translate_prefs->AddToLanguageList(language_code, /*force_blocked=*/false);
- translate_prefs->ResetRecentTargetLanguage();
return RespondNow(NoArguments());
}
@@ -325,7 +366,9 @@ LanguageSettingsPrivateDisableLanguageFunction::Run() {
}
translate_prefs->RemoveFromLanguageList(language_code);
- translate_prefs->ResetRecentTargetLanguage();
+ if (language_code == translate_prefs->GetRecentTargetLanguage()) {
+ translate_prefs->ResetRecentTargetLanguage();
+ }
return RespondNow(NoArguments());
}
@@ -355,7 +398,6 @@ LanguageSettingsPrivateSetEnableTranslationForLanguageFunction::Run() {
} else {
translate_prefs->BlockLanguage(language_code);
}
- translate_prefs->ResetRecentTargetLanguage();
return RespondNow(NoArguments());
}
@@ -408,7 +450,6 @@ LanguageSettingsPrivateMoveLanguageFunction::Run() {
const int offset = 1;
translate_prefs->RearrangeLanguage(language_code, where, offset,
supported_language_codes);
- translate_prefs->ResetRecentTargetLanguage();
return RespondNow(NoArguments());
}
@@ -450,8 +491,8 @@ LanguageSettingsPrivateGetSpellcheckWordsFunction::Run() {
return RespondLater();
}
-void
-LanguageSettingsPrivateGetSpellcheckWordsFunction::OnCustomDictionaryLoaded() {
+void LanguageSettingsPrivateGetSpellcheckWordsFunction::
+ OnCustomDictionaryLoaded() {
SpellcheckService* service =
SpellcheckServiceFactory::GetForContext(browser_context());
service->GetCustomDictionary()->RemoveObserver(this);
@@ -459,9 +500,9 @@ LanguageSettingsPrivateGetSpellcheckWordsFunction::OnCustomDictionaryLoaded() {
Release();
}
-void
-LanguageSettingsPrivateGetSpellcheckWordsFunction::OnCustomDictionaryChanged(
- const SpellcheckCustomDictionary::Change& dictionary_change) {
+void LanguageSettingsPrivateGetSpellcheckWordsFunction::
+ OnCustomDictionaryChanged(
+ const SpellcheckCustomDictionary::Change& dictionary_change) {
NOTREACHED() << "SpellcheckCustomDictionary::Observer: "
"OnCustomDictionaryChanged() called before "
"OnCustomDictionaryLoaded()";
@@ -536,8 +577,7 @@ LanguageSettingsPrivateRemoveSpellcheckWordFunction::Run() {
LanguageSettingsPrivateGetTranslateTargetLanguageFunction::
LanguageSettingsPrivateGetTranslateTargetLanguageFunction()
- : chrome_details_(this) {
-}
+ : chrome_details_(this) {}
LanguageSettingsPrivateGetTranslateTargetLanguageFunction::
~LanguageSettingsPrivateGetTranslateTargetLanguageFunction() = default;
@@ -615,8 +655,7 @@ LanguageSettingsPrivateGetInputMethodListsFunction::Run() {
InputMethodDescriptors ext_ime_descriptors;
ime_state->GetInputMethodExtensions(&ext_ime_descriptors);
PopulateInputMethodListFromDescriptors(
- ext_ime_descriptors,
- &input_method_lists.third_party_extension_imes);
+ ext_ime_descriptors, &input_method_lists.third_party_extension_imes);
}
return RespondNow(OneArgument(input_method_lists.ToValue()));
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h
index 2e745eb503b..4a8a64b7004 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_EXTENSIONS_API_LANGUAGE_SETTINGS_PRIVATE_LANGUAGE_SETTINGS_PRIVATE_API_H_
#include "base/macros.h"
+#include "build/build_config.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
#include "extensions/browser/extension_function.h"
@@ -26,9 +27,16 @@ class LanguageSettingsPrivateGetLanguageListFunction
// ExtensionFunction overrides.
ResponseAction Run() override;
+#if defined(OS_WIN)
+ void OnDictionariesInitialized();
+ void UpdateSupportedPlatformDictionaries();
+#endif // defined(OS_WIN)
+
private:
ChromeExtensionFunctionDetails chrome_details_;
+ std::unique_ptr<base::ListValue> language_list_;
+
DISALLOW_COPY_AND_ASSIGN(LanguageSettingsPrivateGetLanguageListFunction);
};
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
index 6ba4543a9a5..e073c83c7ba 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api_unittest.cc
@@ -9,16 +9,21 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
#include "chrome/browser/extensions/api/language_settings_private/language_settings_private_api.h"
#include "chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h"
#include "chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
+#include "chrome/browser/spellchecker/spellcheck_factory.h"
+#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_profile.h"
#include "components/crx_file/id_util.h"
#include "components/language/core/browser/pref_names.h"
+#include "components/spellcheck/common/spellcheck_features.h"
#include "extensions/browser/event_router_factory.h"
#include "extensions/browser/extension_prefs.h"
@@ -82,6 +87,11 @@ std::unique_ptr<KeyedService> BuildLanguageSettingsPrivateDelegate(
return std::make_unique<MockLanguageSettingsPrivateDelegate>(profile);
}
+std::unique_ptr<KeyedService> BuildSpellcheckService(
+ content::BrowserContext* profile) {
+ return std::make_unique<SpellcheckService>(static_cast<Profile*>(profile));
+}
+
} // namespace
class LanguageSettingsPrivateApiTest : public ExtensionServiceTestBase {
@@ -89,6 +99,27 @@ class LanguageSettingsPrivateApiTest : public ExtensionServiceTestBase {
LanguageSettingsPrivateApiTest() = default;
~LanguageSettingsPrivateApiTest() override = default;
+ protected:
+ void RunGetLanguageListTest();
+
+ virtual void InitFeatures() {
+#if defined(OS_WIN)
+ // Force Windows hybrid spellcheck to be enabled.
+ feature_list_.InitAndEnableFeature(spellcheck::kWinUseBrowserSpellChecker);
+#endif // defined(OS_WIN)
+ }
+
+#if defined(OS_WIN)
+ virtual void AddSpellcheckLanguagesForTesting(
+ const std::vector<std::string>& spellcheck_languages_for_testing) {
+ SpellcheckServiceFactory::GetInstance()
+ ->GetForContext(profile())
+ ->InitWindowsDictionaryLanguages(spellcheck_languages_for_testing);
+ }
+
+ base::test::ScopedFeatureList feature_list_;
+#endif // defined(OS_WIN)
+
private:
void SetUp() override {
ExtensionServiceTestBase::SetUp();
@@ -96,8 +127,14 @@ class LanguageSettingsPrivateApiTest : public ExtensionServiceTestBase {
EventRouterFactory::GetInstance()->SetTestingFactory(
profile(), base::BindRepeating(&BuildEventRouter));
+ InitFeatures();
+
LanguageSettingsPrivateDelegateFactory::GetInstance()->SetTestingFactory(
profile(), base::BindRepeating(&BuildLanguageSettingsPrivateDelegate));
+
+ // Use SetTestingFactoryAndUse to force creation and initialization.
+ SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile(), base::BindRepeating(&BuildSpellcheckService));
}
std::unique_ptr<TestBrowserWindow> browser_window_;
@@ -146,6 +183,121 @@ TEST_F(LanguageSettingsPrivateApiTest, GetSpellcheckDictionaryStatusesTest) {
EXPECT_EQ(expected, *actual);
}
+TEST_F(LanguageSettingsPrivateApiTest, GetLanguageListTest) {
+ RunGetLanguageListTest();
+}
+
+void LanguageSettingsPrivateApiTest::RunGetLanguageListTest() {
+ struct LanguageToTest {
+ std::string accept_language;
+ std::string windows_dictionary_name; // Empty string indicates to not use
+ // fake Windows dictionary
+ bool is_preferred_language;
+ bool is_spellcheck_support_expected;
+ };
+
+ std::vector<LanguageToTest> languages_to_test = {
+ // Languages with both Windows and Hunspell spellcheck support.
+ // GetLanguageList should always report spellchecking to be supported for
+ // these languages, regardless of whether a language pack is installed or
+ // if it is a preferred language.
+ {"fr", "fr-FR", true, true},
+ {"de", "de-DE", false, true},
+ {"es-MX", "", true, true},
+ {"fa", "", false, true},
+ {"gl", "", true, false},
+ {"zu", "", false, false},
+ // Finnish with Filipino language pack (string in string).
+ {"fi", "fil", true, false},
+ // Sesotho with Asturian language pack (string in string).
+ {"st", "ast", true, false},
+ };
+
+ // A few more test cases for non-Hunspell languages. These languages do have
+ // Windows spellcheck support depending on the OS version. GetLanguageList
+ // only reports spellchecking is supported for these languages if the language
+ // pack is installed.
+#if defined(OS_WIN)
+ if (spellcheck::WindowsVersionSupportsSpellchecker()) {
+ languages_to_test.push_back({"ar", "ar-SA", true, true});
+ languages_to_test.push_back({"bn", "bn-IN", false, true});
+ } else {
+ languages_to_test.push_back({"ar", "ar-SA", true, false});
+ languages_to_test.push_back({"bn", "bn-IN", false, false});
+ }
+#else
+ languages_to_test.push_back({"ar", "ar-SA", true, false});
+ languages_to_test.push_back({"bn", "bn-IN", false, false});
+#endif // defined(OS_WIN)
+
+ // Initialize accept languages prefs.
+ std::vector<std::string> accept_languages;
+ for (auto& language_to_test : languages_to_test) {
+ if (language_to_test.is_preferred_language) {
+ accept_languages.push_back(language_to_test.accept_language);
+ }
+ }
+
+ std::string accept_languages_string = base::JoinString(accept_languages, ",");
+ DVLOG(2) << "Setting accept languages preferences to: "
+ << accept_languages_string;
+ profile()->GetPrefs()->SetString(language::prefs::kAcceptLanguages,
+ accept_languages_string);
+
+#if defined(OS_WIN)
+ // Add fake Windows dictionaries using InitWindowsDictionaryLanguages.
+ std::vector<std::string> windows_spellcheck_languages_for_testing;
+ for (auto& language_to_test : languages_to_test) {
+ if (!language_to_test.windows_dictionary_name.empty()) {
+ windows_spellcheck_languages_for_testing.push_back(
+ language_to_test.windows_dictionary_name);
+ DVLOG(2) << "Will set fake Windows spellcheck dictionary for testing: "
+ << language_to_test.windows_dictionary_name;
+ }
+ }
+
+ AddSpellcheckLanguagesForTesting(windows_spellcheck_languages_for_testing);
+#endif // defined(OS_WIN)
+
+ auto function =
+ base::MakeRefCounted<LanguageSettingsPrivateGetLanguageListFunction>();
+
+ std::unique_ptr<base::Value> result =
+ api_test_utils::RunFunctionAndReturnSingleResult(function.get(), "[]",
+ profile());
+
+ ASSERT_NE(nullptr, result) << function->GetError();
+ EXPECT_TRUE(result->is_list());
+
+ size_t languages_to_test_found_count = 0;
+ for (auto& language_val : result->GetList()) {
+ EXPECT_TRUE(language_val.is_dict());
+ std::string* language_code_ptr = language_val.FindStringKey("code");
+ ASSERT_NE(nullptr, language_code_ptr);
+ std::string language_code = *language_code_ptr;
+ EXPECT_FALSE(language_code.empty());
+
+ const base::Optional<bool> maybe_supports_spellcheck =
+ language_val.FindBoolKey("supportsSpellcheck");
+ const bool supports_spellcheck = maybe_supports_spellcheck.has_value()
+ ? maybe_supports_spellcheck.value()
+ : false;
+
+ for (auto& language_to_test : languages_to_test) {
+ if (language_to_test.accept_language == language_code) {
+ DVLOG(2) << "*** Found language code being tested=" << language_code
+ << ", supportsSpellcheck=" << supports_spellcheck << " ***";
+ EXPECT_EQ(language_to_test.is_spellcheck_support_expected,
+ supports_spellcheck);
+ languages_to_test_found_count++;
+ break;
+ }
+ }
+ }
+
+ EXPECT_EQ(languages_to_test.size(), languages_to_test_found_count);
+}
+
#if defined(OS_CHROMEOS)
namespace {
@@ -337,4 +489,34 @@ TEST_F(LanguageSettingsPrivateApiTest, RemoveInputMethodTest) {
#endif // OS_CHROMEOS
+#if defined(OS_WIN)
+class LanguageSettingsPrivateApiTestDelayInit
+ : public LanguageSettingsPrivateApiTest {
+ public:
+ LanguageSettingsPrivateApiTestDelayInit() = default;
+
+ protected:
+ void InitFeatures() override {
+ // Force Windows hybrid spellcheck and delayed initialization of the
+ // spellcheck service to be enabled.
+ feature_list_.InitWithFeatures(
+ /*enabled_features=*/{spellcheck::kWinUseBrowserSpellChecker,
+ spellcheck::kWinDelaySpellcheckServiceInit},
+ /*disabled_features=*/{});
+ }
+
+ void AddSpellcheckLanguagesForTesting(
+ const std::vector<std::string>& spellcheck_languages_for_testing)
+ override {
+ SpellcheckServiceFactory::GetInstance()
+ ->GetForContext(profile())
+ ->AddSpellcheckLanguagesForTesting(spellcheck_languages_for_testing);
+ }
+};
+
+TEST_F(LanguageSettingsPrivateApiTestDelayInit, GetLanguageListTest) {
+ RunGetLanguageListTest();
+}
+#endif // defined(OS_WIN)
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
index a35e419d0e0..5a581df3758 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
@@ -5,12 +5,15 @@
#include "chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h"
#include "base/bind.h"
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/test/base/testing_profile.h"
#include "components/spellcheck/browser/pref_names.h"
+#include "components/spellcheck/common/spellcheck_features.h"
#include "components/spellcheck/spellcheck_buildflags.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/event_router_factory.h"
@@ -45,6 +48,12 @@ class LanguageSettingsPrivateDelegateTest
EventRouterFactory::GetInstance()->SetTestingFactory(
profile(), base::BindRepeating(&BuildEventRouter));
+#if defined(OS_WIN)
+ // Tests were designed assuming Hunspell dictionary used and may fail when
+ // Windows spellcheck is enabled by default.
+ feature_list_.InitAndDisableFeature(spellcheck::kWinUseBrowserSpellChecker);
+#endif // defined(OS_WIN)
+
base::ListValue language_codes;
language_codes.AppendString("fr");
profile()->GetPrefs()->Set(spellcheck::prefs::kSpellCheckDictionaries,
@@ -89,6 +98,9 @@ class LanguageSettingsPrivateDelegateTest
run_loop_->Quit();
}
+#if defined(OS_WIN)
+ base::test::ScopedFeatureList feature_list_;
+#endif // defined(OS_WIN)
std::unique_ptr<LanguageSettingsPrivateDelegate> delegate_;
std::unique_ptr<base::RunLoop> run_loop_;
};
diff --git a/chromium/chrome/browser/extensions/api/management/DEPS b/chromium/chrome/browser/extensions/api/management/DEPS
new file mode 100644
index 00000000000..bd0ce11d35b
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/management/DEPS
@@ -0,0 +1,10 @@
+specific_include_rules = {
+ # This DEPS violation snuck in while there was a bug in the checkdeps tool.
+ # https://crbug.com/1084826
+ "chrome_management_api_delegate\.cc": [
+ "+chrome/browser/apps/app_service/app_launch_params.h",
+ "+chrome/browser/apps/app_service/app_service_proxy.h",
+ "+chrome/browser/apps/app_service/app_service_proxy_factory.h",
+ "+chrome/browser/apps/app_service/browser_app_launcher.h",
+ ],
+}
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 b5b0ab58441..75ecb26f2e2 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
@@ -282,7 +282,8 @@ class ChromeAppForLinkDelegate : public extensions::AppForLinkDelegate {
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;
+ if (web_app_icon_info.square_size_px)
+ 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));
}
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 c3f1fe7ff40..05567b35bde 100644
--- a/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc
@@ -45,7 +45,6 @@
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_test_util.h"
-#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/browser/gpu_data_manager.h"
#endif
@@ -843,64 +842,87 @@ class TestManagementAPIDelegate : public ManagementAPIDelegate {
// 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 {
+class TestSupervisedUserExtensionsDelegate
+ : public SupervisedUserExtensionsDelegate {
public:
- TestSupervisedUserServiceDelegate() = default;
- ~TestSupervisedUserServiceDelegate() override = default;
+ TestSupervisedUserExtensionsDelegate() = default;
+ ~TestSupervisedUserExtensionsDelegate() override = default;
- // SupervisedUserServiceDelegate:
+ // SupervisedUserExtensionsDelegate:
bool IsChild(content::BrowserContext* context) const override { return true; }
- bool IsSupervisedChildWhoMayInstallExtensions(
- content::BrowserContext* context) const override {
- return is_supervised_child_who_may_install_extensions_;
- }
bool IsExtensionAllowedByParent(
const extensions::Extension& extension,
content::BrowserContext* context) const override {
- return false;
+ SupervisedUserService* supervised_user_service =
+ SupervisedUserServiceFactory::GetForBrowserContext(context);
+ return supervised_user_service->IsExtensionAllowed(extension);
+ }
+
+ void PromptForParentPermissionOrShowError(
+ const extensions::Extension& extension,
+ content::BrowserContext* context,
+ content::WebContents* contents,
+ ParentPermissionDialogDoneCallback parent_permission_callback,
+ base::OnceClosure error_callback) override {
+ // Preconditions.
+ DCHECK(IsChild(context));
+ DCHECK(!IsExtensionAllowedByParent(extension, context));
+
+ if (CanInstallExtensions(context)) {
+ ShowParentPermissionDialogForExtension(
+ extension, context, contents, std::move(parent_permission_callback));
+ } else {
+ ShowExtensionEnableBlockedByParentDialogForExtension(
+ extension, contents, std::move(error_callback));
+ }
+ }
+
+ void set_next_parent_permission_dialog_result(
+ ParentPermissionDialogResult result) {
+ dialog_result_ = result;
}
+
+ int show_dialog_count() const { return show_dialog_count_; }
+ int show_block_dialog_count() const { return show_block_dialog_count_; }
+
+ private:
+ // Returns true if |context| represents a supervised child account who may
+ // install extensions with parent permission.
+ bool CanInstallExtensions(content::BrowserContext* context) const {
+ SupervisedUserService* supervised_user_service =
+ SupervisedUserServiceFactory::GetForBrowserContext(context);
+ return supervised_user_service->CanInstallExtensions();
+ }
+
+ // Shows a parent permission dialog for |extension| and call |done_callback|
+ // when it completes.
void ShowParentPermissionDialogForExtension(
const extensions::Extension& extension,
content::BrowserContext* context,
content::WebContents* contents,
- ParentPermissionDialogDoneCallback done_callback) override {
+ ParentPermissionDialogDoneCallback done_callback) {
++show_dialog_count_;
std::move(done_callback).Run(dialog_result_);
}
+ // Shows a dialog indicating that |extension| has been blocked and call
+ // |done_callback| when it completes.
void ShowExtensionEnableBlockedByParentDialogForExtension(
- const extensions::Extension* extension,
+ const extensions::Extension& extension,
content::WebContents* contents,
- base::OnceClosure done_callback) override {
+ base::OnceClosure done_callback) {
show_block_dialog_count_++;
- std::move(done_callback).Run();
- }
-
- void RecordExtensionEnableBlockedByParentDialogUmaMetric() override {
SupervisedUserExtensionsMetricsRecorder::RecordEnablementUmaMetrics(
SupervisedUserExtensionsMetricsRecorder::EnablementState::
kFailedToEnable);
+ std::move(done_callback).Run();
}
- void set_next_parent_permission_dialog_result(
- ParentPermissionDialogResult result) {
- dialog_result_ = result;
- }
-
- void set_is_supervised_child_who_may_install_extensions(bool value) {
- is_supervised_child_who_may_install_extensions_ = value;
- }
-
- int show_dialog_count() const { return show_dialog_count_; }
- int show_block_dialog_count() const { return show_block_dialog_count_; }
-
- private:
ParentPermissionDialogResult dialog_result_ =
ParentPermissionDialogResult::kParentPermissionFailed;
int show_dialog_count_ = 0;
int show_block_dialog_count_ = 0;
- bool is_supervised_child_who_may_install_extensions_ = true;
};
// Tests for supervised users (child accounts). Supervised users are not allowed
@@ -940,15 +962,15 @@ class ManagementApiSupervisedUserTest : public ManagementApiUnitTest {
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(
+ // Install a SupervisedUserExtensionsDelegate to sense the dialog state.
+ supervised_user_delegate_ = new TestSupervisedUserExtensionsDelegate;
+ management_api_->set_supervised_user_extensions_delegate_for_test(
base::WrapUnique(supervised_user_delegate_));
}
std::unique_ptr<content::WebContents> web_contents_;
ManagementAPI* management_api_ = nullptr;
- TestSupervisedUserServiceDelegate* supervised_user_delegate_ = nullptr;
+ TestSupervisedUserExtensionsDelegate* supervised_user_delegate_ = nullptr;
};
TEST_F(ManagementApiSupervisedUserTest, SetEnabled_BlockedByParent) {
@@ -974,11 +996,8 @@ TEST_F(ManagementApiSupervisedUserTest, SetEnabled_BlockedByParent) {
// Simulate disabling Permissions for sites, apps and extensions
// in the testing supervised user service delegate used by the Management API.
- supervised_user_delegate_->set_is_supervised_child_who_may_install_extensions(
- false);
- // Ensure that the web contents can be used to create a modal dialog.
- web_modal::WebContentsModalDialogManager::CreateForWebContents(
- web_contents_.get());
+ GetSupervisedUserService()
+ ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(false);
// The supervised user trying to enable while Permissions for sites, apps and
// extensions is disabled should fail.
@@ -1007,61 +1026,6 @@ TEST_F(ManagementApiSupervisedUserTest, SetEnabled_BlockedByParent) {
SupervisedUserExtensionsMetricsRecorder::kFailedToEnableActionName));
}
-TEST_F(ManagementApiSupervisedUserTest,
- SetEnabled_BlockedByParentNoDialogWhenNoDialogManagerAvailable) {
- // Preconditions.
- ASSERT_TRUE(profile()->IsChild());
-
- base::HistogramTester histogram_tester;
- base::UserActionTester user_action_tester;
-
- 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.
- EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
- const std::string extension_id = extension->id();
- ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
- EXPECT_TRUE(prefs->HasDisableReason(
- extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
-
- // Simulate disabling Permissions for sites, apps and extensions
- // in the testing supervised user service delegate used by the Management API.
- supervised_user_delegate_->set_is_supervised_child_who_may_install_extensions(
- false);
-
- // The supervised user trying to enable while Permissions for sites, apps and
- // extensions is disabled 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));
-
- // The block dialog should not have been shown.
- EXPECT_EQ(supervised_user_delegate_->show_block_dialog_count(), 0);
- }
-
- histogram_tester.ExpectUniqueSample(
- SupervisedUserExtensionsMetricsRecorder::kEnablementHistogramName,
- SupervisedUserExtensionsMetricsRecorder::EnablementState::kFailedToEnable,
- 1);
- histogram_tester.ExpectTotalCount(
- SupervisedUserExtensionsMetricsRecorder::kEnablementHistogramName, 1);
- EXPECT_EQ(
- 1,
- user_action_tester.GetActionCount(
- SupervisedUserExtensionsMetricsRecorder::kFailedToEnableActionName));
-}
-
// Tests enabling an extension via management API after it was disabled due to
// permission increase for supervised users.
// Prevents a regression to crbug/1068660.
@@ -1295,7 +1259,7 @@ TEST_F(ManagementApiSupervisedUserTest,
// Now try again with parent approval, and this should succeed.
{
supervised_user_delegate_->set_next_parent_permission_dialog_result(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionReceived);
std::string error;
bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
@@ -1347,7 +1311,7 @@ TEST_F(ManagementApiSupervisedUserTest, SetEnabled_UnsupportedRequirement) {
// Parent approval should fail because of the unsupported requirements.
{
supervised_user_delegate_->set_next_parent_permission_dialog_result(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionReceived);
std::string error;
bool success = RunSetEnabledFunction(web_contents_.get(), extension->id(),
@@ -1382,7 +1346,7 @@ TEST_F(ManagementApiSupervisedUserTest, SetEnabledDisabled_UmaMetrics) {
// The parent will approve.
supervised_user_delegate_->set_next_parent_permission_dialog_result(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionReceived);
RunSetEnabledFunction(web_contents_.get(), extension->id(),
@@ -1469,7 +1433,7 @@ TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentApproves) {
// The parent will approve.
supervised_user_delegate_->set_next_parent_permission_dialog_result(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionReceived);
// Simulate a call to chrome.management.setEnabled(). It should succeed.
@@ -1494,7 +1458,7 @@ TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentDenies) {
// The parent will deny the next dialog.
supervised_user_delegate_->set_next_parent_permission_dialog_result(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionCanceled);
// Simulate a call to chrome.management.setEnabled(). It should not succeed.
@@ -1520,7 +1484,7 @@ TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_DialogFails) {
// The next dialog will close due to a failure (e.g. network failure while
// looking up parent information).
supervised_user_delegate_->set_next_parent_permission_dialog_result(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionFailed);
// Simulate a call to chrome.management.setEnabled(). It should not succeed.
diff --git a/chromium/chrome/browser/extensions/api/management/management_apitest.cc b/chromium/chrome/browser/extensions/api/management/management_apitest.cc
index aded1d518db..7804dcad939 100644
--- a/chromium/chrome/browser/extensions/api/management/management_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_apitest.cc
@@ -18,6 +18,7 @@
#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/install_finalizer.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"
@@ -36,6 +37,7 @@
#include "extensions/test/result_catcher.h"
#include "extensions/test/test_extension_dir.h"
#include "net/dns/mock_host_resolver.h"
+#include "testing/gtest/include/gtest/gtest.h"
using extensions::Extension;
using extensions::Manifest;
@@ -241,9 +243,12 @@ class InstallReplacementWebAppApiTest : public ExtensionManagementApiTest {
chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true);
const GURL start_url = https_test_server_.GetURL(web_app_start_url);
web_app::AppId web_app_id = web_app::GenerateAppIdFromURL(start_url);
-
auto* provider =
web_app::WebAppProviderBase::GetProviderBase(browser()->profile());
+ // Async legacy finalizer install was causing this test to be flaky (see
+ // crbug.com/1094616).
+ provider->install_finalizer().RemoveLegacyInstallFinalizerForTesting();
+
EXPECT_FALSE(provider->registrar().IsLocallyInstalled(start_url));
EXPECT_EQ(0, static_cast<int>(
provider->ui_manager().GetNumWindowsForApp(web_app_id)));
diff --git a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
index 68ecb30c5ed..ec72a41d2d6 100644
--- a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -87,8 +87,7 @@ class ExtensionHostDestructionObserver
}
// ExtensionHostObserver:
- void OnExtensionHostDestroyed(
- const extensions::ExtensionHost* host) override {
+ void OnExtensionHostDestroyed(extensions::ExtensionHost* host) override {
if (host == host_) {
extension_host_observer_.Remove(host_);
run_loop_.Quit();
diff --git a/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc b/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc
index 914c9eb0467..b7f9bde94a7 100644
--- a/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc
@@ -49,15 +49,8 @@ class MDnsAPITest : public extensions::ExtensionApiTest {
} // namespace
-// TODO(justinlin): Win Dbg has a workaround that makes RunExtensionSubtest
-// always return true without actually running the test. Remove when fixed.
-#if defined(OS_WIN) && !defined(NDEBUG)
-#define MAYBE_RegisterListener DISABLED_RegisterListener
-#else
-#define MAYBE_RegisterListener RegisterListener
-#endif
// Test loading extension, registering an MDNS listener and dispatching events.
-IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_RegisterListener) {
+IN_PROC_BROWSER_TEST_F(MDnsAPITest, RegisterListener) {
const std::string& service_type = "_googlecast._tcp.local";
SetUpTestDnsSdRegistry();
@@ -86,15 +79,8 @@ IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_RegisterListener) {
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
-// TODO(justinlin): Win Dbg has a workaround that makes RunExtensionSubtest
-// always return true without actually running the test. Remove when fixed.
-#if defined(OS_WIN) && !defined(NDEBUG)
-#define MAYBE_ForceDiscovery DISABLED_ForceDiscovery
-#else
-#define MAYBE_ForceDiscovery ForceDiscovery
-#endif
// Test loading extension, registering an MDNS listener and dispatching events.
-IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_ForceDiscovery) {
+IN_PROC_BROWSER_TEST_F(MDnsAPITest, ForceDiscovery) {
const std::string& service_type = "_googlecast._tcp.local";
SetUpTestDnsSdRegistry();
@@ -120,15 +106,8 @@ IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_ForceDiscovery) {
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
-// TODO(justinlin): Win Dbg has a workaround that makes RunExtensionSubtest
-// always return true without actually running the test. Remove when fixed.
-#if defined(OS_WIN) && !defined(NDEBUG)
-#define MAYBE_RegisterMultipleListeners DISABLED_RegisterMultipleListeners
-#else
-#define MAYBE_RegisterMultipleListeners RegisterMultipleListeners
-#endif
// Test loading extension and registering multiple listeners.
-IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_RegisterMultipleListeners) {
+IN_PROC_BROWSER_TEST_F(MDnsAPITest, RegisterMultipleListeners) {
const std::string& service_type = "_googlecast._tcp.local";
const std::string& test_service_type = "_testing._tcp.local";
SetUpTestDnsSdRegistry();
@@ -161,15 +140,8 @@ IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_RegisterMultipleListeners) {
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
-// TODO(justinlin): Win Dbg has a workaround that makes RunExtensionSubtest
-// always return true without actually running the test. Remove when fixed.
-#if defined(OS_WIN) && !defined(NDEBUG)
-#define MAYBE_RegisterTooManyListeners DISABLED_RegisterTooManyListeners
-#else
-#define MAYBE_RegisterTooManyListeners RegisterTooManyListeners
-#endif
// Test loading extension and registering multiple listeners.
-IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_RegisterTooManyListeners) {
+IN_PROC_BROWSER_TEST_F(MDnsAPITest, RegisterTooManyListeners) {
SetUpTestDnsSdRegistry();
EXPECT_CALL(*dns_sd_registry_, RegisterDnsSdListener(_)).Times(10);
@@ -182,16 +154,8 @@ IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_RegisterTooManyListeners) {
<< message_;
}
-// TODO(justinlin): Win Dbg has a workaround that makes RunExtensionSubtest
-// always return true without actually running the test. Remove when fixed.
-#if defined(OS_WIN) && !defined(NDEBUG)
-#define MAYBE_MaxServiceInstancesPerEventConst \
- DISABLED_MaxServiceInstancesPerEventConst
-#else
-#define MAYBE_MaxServiceInstancesPerEventConst MaxServiceInstancesPerEventConst
-#endif
// Test loading extension and registering multiple listeners.
-IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_MaxServiceInstancesPerEventConst) {
+IN_PROC_BROWSER_TEST_F(MDnsAPITest, MaxServiceInstancesPerEventConst) {
EXPECT_TRUE(RunExtensionSubtest("mdns/api",
"get_max_service_instances.html"));
}
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 ccfb4199428..a3422c55d05 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
@@ -15,7 +15,6 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
-#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
@@ -99,8 +98,7 @@ struct BuiltInHost {
std::unique_ptr<NativeMessageHost> CreateIt2MeHost(
content::BrowserContext* browser_context) {
return remoting::CreateIt2MeNativeMessagingHostForChromeOS(
- base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}),
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}),
+ content::GetIOThreadTaskRunner({}), content::GetUIThreadTaskRunner({}),
g_browser_process->policy_service());
}
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 8d1911b6118..d1d51bfa74d 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
@@ -13,7 +13,6 @@
#include "base/files/file_path.h"
#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"
@@ -60,7 +59,7 @@ NativeMessageProcessHost::NativeMessageProcessHost(
const std::string& source_extension_id,
const std::string& native_host_name,
std::unique_ptr<NativeProcessLauncher> launcher)
- : client_(NULL),
+ : client_(nullptr),
source_extension_id_(source_extension_id),
native_host_name_(native_host_name),
launcher_(std::move(launcher)),
@@ -72,8 +71,7 @@ NativeMessageProcessHost::NativeMessageProcessHost(
write_pending_(false) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- task_runner_ =
- base::CreateSingleThreadTaskRunner({content::BrowserThread::IO});
+ task_runner_ = content::GetIOThreadTaskRunner({});
}
NativeMessageProcessHost::~NativeMessageProcessHost() {
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chromium/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
index 428ba272fc3..3acc436a7ea 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -27,7 +27,6 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
@@ -59,8 +58,6 @@
#include <unistd.h>
#endif
-using content::BrowserThread;
-
namespace {
const char kTestMessage[] = "{\"text\": \"Hello.\"}";
@@ -125,8 +122,8 @@ class NativeMessagingTest : public ::testing::Test,
void TearDown() override {
if (native_message_host_) {
- base::DeleteSoon(FROM_HERE, {BrowserThread::IO},
- native_message_host_.release());
+ content::GetIOThreadTaskRunner({})->DeleteSoon(
+ FROM_HERE, native_message_host_.release());
}
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
index f25164371e1..7b83c3a74ff 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
@@ -23,11 +23,14 @@
#include "components/keep_alive_registry/keep_alive_types.h"
#include "content/public/test/browser_test.h"
#include "extensions/browser/process_manager.h"
+#include "extensions/common/scoped_worker_based_extensions_channel.h"
#include "extensions/test/result_catcher.h"
namespace extensions {
namespace {
+using ContextType = ExtensionApiTest::ContextType;
+
class NativeMessagingApiTest : public ExtensionApiTest {
protected:
extensions::ScopedTestNativeMessagingHost test_host_;
@@ -43,6 +46,48 @@ IN_PROC_BROWSER_TEST_F(NativeMessagingApiTest, UserLevelNativeMessaging) {
ASSERT_TRUE(RunExtensionTest("native_messaging")) << message_;
}
+// TODO(crbug.com/1094027): Clean up duplicate test coverage.
+class NativeMessagingLazyApiTest
+ : public NativeMessagingApiTest,
+ public testing::WithParamInterface<ContextType> {
+ public:
+ void SetUp() override {
+ NativeMessagingApiTest::SetUp();
+ // Service Workers are currently only available on certain channels, so set
+ // the channel for those tests.
+ if (GetParam() == ContextType::kServiceWorker)
+ current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>();
+ }
+
+ protected:
+ bool RunLazyTest(const std::string& extension_name) {
+ if (GetParam() == ContextType::kEventPage) {
+ return RunExtensionTest(extension_name);
+ }
+ return RunExtensionTestWithFlags(
+ extension_name, kFlagRunAsServiceWorkerBasedExtension, kFlagNone);
+ }
+
+ std::unique_ptr<ScopedWorkerBasedExtensionsChannel> current_channel_;
+};
+
+INSTANTIATE_TEST_SUITE_P(EventPage,
+ NativeMessagingLazyApiTest,
+ ::testing::Values(ContextType::kEventPage));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ NativeMessagingLazyApiTest,
+ ::testing::Values(ContextType::kServiceWorker));
+
+IN_PROC_BROWSER_TEST_P(NativeMessagingLazyApiTest, NativeMessagingBasic) {
+ ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestHost(false));
+ ASSERT_TRUE(RunLazyTest("native_messaging_lazy")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_P(NativeMessagingLazyApiTest, UserLevelNativeMessaging) {
+ ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestHost(true));
+ ASSERT_TRUE(RunLazyTest("native_messaging_lazy")) << message_;
+}
+
#if !defined(OS_CHROMEOS)
class TestProcessManagerObserver : public ProcessManagerObserver {
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.cc
index 967ebb848e4..f675d66c911 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.cc
@@ -11,7 +11,6 @@
#include "base/bind_helpers.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/timer/timer.h"
#include "chrome/browser/browser_process.h"
@@ -75,8 +74,8 @@ class NativeMessagingHostErrorReporter : public NativeMessageHost::Client {
MovableScopedKeepAlive keep_alive(
new ScopedKeepAlive(KeepAliveOrigin::NATIVE_MESSAGING_HOST_ERROR_REPORT,
KeepAliveRestartOption::DISABLED));
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&NativeMessagingHostErrorReporter::ReportOnIoThread,
std::move(host), std::move(keep_alive)));
}
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 5b5b39a5567..439e74947e0 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -23,7 +23,6 @@
#include "base/path_service.h"
#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"
@@ -313,8 +312,8 @@ void NativeProcessLauncherImpl::Core::CallCallbackOnIOThread(
void NativeProcessLauncherImpl::Core::PostErrorResult(
const LaunchedCallback& callback,
LaunchResult error) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread,
this, callback, error, base::Process(), base::File(),
base::File()));
@@ -325,8 +324,8 @@ void NativeProcessLauncherImpl::Core::PostResult(
base::Process process,
base::File read_file,
base::File write_file) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&NativeProcessLauncherImpl::Core::CallCallbackOnIOThread,
this, callback, RESULT_SUCCESS, std::move(process),
std::move(read_file), std::move(write_file)));
diff --git a/chromium/chrome/browser/extensions/api/notifications/DEPS b/chromium/chrome/browser/extensions/api/notifications/DEPS
new file mode 100644
index 00000000000..bdbc70d13b0
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/notifications/DEPS
@@ -0,0 +1,10 @@
+specific_include_rules = {
+ # This DEPS violation snuck in while there was a bug in the checkdeps tool.
+ # https://crbug.com/1084826
+ "notifications_apitest\.cc": [
+ "+chrome/browser/apps/app_service/app_launch_params.h",
+ "+chrome/browser/apps/app_service/app_service_proxy.h",
+ "+chrome/browser/apps/app_service/app_service_proxy_factory.h",
+ "+chrome/browser/apps/app_service/browser_app_launcher.h",
+ ],
+}
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 ba017b4199d..31905b3349a 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,7 +11,6 @@
#include "base/bind.h"
#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"
@@ -76,8 +75,8 @@ PageCaptureSaveAsMHTMLFunction::PageCaptureSaveAsMHTMLFunction() {
PageCaptureSaveAsMHTMLFunction::~PageCaptureSaveAsMHTMLFunction() {
if (mhtml_file_.get()) {
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&ClearFileReferenceOnIOThread, std::move(mhtml_file_)));
}
}
@@ -200,8 +199,8 @@ void PageCaptureSaveAsMHTMLFunction::ResolvePermissionRequest(
void PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile() {
bool success = base::CreateTemporaryFile(&mhtml_path_);
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnIO,
this, success));
}
@@ -226,8 +225,8 @@ void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnIO(bool success) {
base::TaskShutdownBehavior::BLOCK_SHUTDOWN})
.get());
}
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnUI,
this, success));
}
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
index 413965efe9b..54808bfd323 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -36,7 +36,7 @@
#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/compromised_credentials_manager.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"
@@ -54,21 +54,17 @@ namespace {
using autofill::PasswordForm;
using password_manager::CanonicalizeUsername;
-using password_manager::CompromiseType;
+using password_manager::CompromiseTypeFlags;
using password_manager::CredentialWithPassword;
using password_manager::LeakCheckCredential;
-using password_manager::PasswordCredentialLess;
using ui::TimeFormat;
using CompromisedCredentialsView =
- password_manager::CompromisedCredentialsProvider::CredentialsView;
+ password_manager::CompromisedCredentialsManager::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.
@@ -165,35 +161,6 @@ api::passwords_private::PasswordCheckState ConvertPasswordCheckState(
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))
@@ -204,9 +171,7 @@ std::string FormatElapsedTime(base::Time time) {
}
// 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.
+// passwords_private::CompromiseType.
struct CompromisedCredentialAndType {
CredentialWithPassword credential;
api::passwords_private::CompromiseType type;
@@ -214,65 +179,24 @@ struct CompromisedCredentialAndType {
// 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.
+// are ordered by recency.
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
+ std::vector<CredentialWithPassword> compromised_credentials) {
+ // 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});
+ for (auto& credential : compromised_credentials) {
+ auto type = static_cast<api::passwords_private::CompromiseType>(
+ credential.compromise_type);
+ results.push_back({std::move(credential), type});
}
+ // Reordering phished credential to the beginning.
+ auto last_phished = std::partition(
+ results.begin(), results.end(), [](const auto& credential) {
+ return credential.type !=
+ 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
@@ -280,8 +204,8 @@ std::vector<CompromisedCredentialAndType> OrderCompromisedCredentials(
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);
+ std::sort(results.begin(), last_phished, create_time_cmp);
+ std::sort(last_phished, results.end(), create_time_cmp);
return results;
}
@@ -293,25 +217,24 @@ PasswordCheckDelegate::PasswordCheckDelegate(Profile* profile)
profile,
ServiceAccessType::EXPLICIT_ACCESS)),
saved_passwords_presenter_(password_store_),
- compromised_credentials_provider_(password_store_,
- &saved_passwords_presenter_),
+ compromised_credentials_manager_(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_compromised_credentials_manager_.Add(
+ &compromised_credentials_manager_);
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
+ // This will soon after invoke OnCompromisedCredentialsChanged(). Calls to
// GetCompromisedCredentials() that might happen until then will return an
// empty list.
saved_passwords_presenter_.Init();
- compromised_credentials_provider_.Init();
+ compromised_credentials_manager_.Init();
}
PasswordCheckDelegate::~PasswordCheckDelegate() = default;
@@ -320,7 +243,7 @@ std::vector<api::passwords_private::CompromisedCredential>
PasswordCheckDelegate::GetCompromisedCredentials() {
std::vector<CompromisedCredentialAndType>
ordered_compromised_credential_and_types = OrderCompromisedCredentials(
- compromised_credentials_provider_.GetCompromisedCredentials());
+ compromised_credentials_manager_.GetCompromisedCredentials());
std::vector<api::passwords_private::CompromisedCredential>
compromised_credentials;
@@ -338,7 +261,7 @@ PasswordCheckDelegate::GetCompromisedCredentials() {
// 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);
+ compromised_credentials_manager_.GetSavedPasswordsFor(credential)[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;
@@ -401,52 +324,26 @@ PasswordCheckDelegate::GetPlaintextCompromisedPassword(
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.
+ // Try to obtain the original CredentialWithPassword. Return false if 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));
+ return compromised_credentials_manager_.UpdateCompromisedCredentials(
+ *compromised_credential, 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.
+ // Try to obtain the original CredentialWithPassword. Return false if 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();
+ return compromised_credentials_manager_.RemoveCompromisedCredential(
+ *compromised_credential);
}
void PasswordCheckDelegate::StartPasswordCheck(
@@ -547,8 +444,6 @@ void PasswordCheckDelegate::OnSavedPasswordsChanged(SavedPasswordsView) {
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());
@@ -584,24 +479,7 @@ 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,
- });
- }
- }
+ compromised_credentials_manager_.SaveCompromisedCredential(credential);
}
// Update the progress in case there is one.
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
index c2ec8b18e99..a615f879ae8 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
@@ -18,7 +18,7 @@
#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/compromised_credentials_manager.h"
#include "components/password_manager/core/browser/ui/credential_utils.h"
#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
@@ -38,17 +38,12 @@ class PasswordCheckProgress;
// with the bulk password check feature.
class PasswordCheckDelegate
: public password_manager::SavedPasswordsPresenter::Observer,
- public password_manager::CompromisedCredentialsProvider::Observer,
- public password_manager::BulkLeakCheckService::Observer {
+ public password_manager::CompromisedCredentialsManager::Observer,
+ public password_manager::BulkLeakCheckServiceInterface::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;
@@ -98,7 +93,7 @@ class PasswordCheckDelegate
// Invokes PasswordsPrivateEventRouter::OnCompromisedCredentialsChanged if
// a valid pointer can be obtained.
void OnCompromisedCredentialsChanged(
- password_manager::CompromisedCredentialsProvider::CredentialsView
+ password_manager::CompromisedCredentialsManager::CredentialsView
credentials) override;
// password_manager::BulkLeakCheckService::Observer:
@@ -126,16 +121,16 @@ class PasswordCheckDelegate
Profile* profile_ = nullptr;
// Handle to the password store, powering both |saved_passwords_presenter_|
- // and |compromised_credentials_provider_|.
+ // and |compromised_credentials_manager_|.
scoped_refptr<password_manager::PasswordStore> password_store_;
- // Used by |compromised_credentials_provider_| to obtain the list of saved
+ // Used by |compromised_credentials_manager_| 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_;
+ password_manager::CompromisedCredentialsManager
+ compromised_credentials_manager_;
// Adapter used to start, monitor and stop a bulk leak check.
password_manager::BulkLeakCheckServiceAdapter
@@ -162,22 +157,16 @@ class PasswordCheckDelegate
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 |compromised_credentials_manager_|.
+ ScopedObserver<password_manager::CompromisedCredentialsManager,
+ password_manager::CompromisedCredentialsManager::Observer>
+ observed_compromised_credentials_manager_{this};
// A scoped observer for the BulkLeakCheckService.
- ScopedObserver<password_manager::BulkLeakCheckService,
- password_manager::BulkLeakCheckService::Observer>
+ ScopedObserver<password_manager::BulkLeakCheckServiceInterface,
+ password_manager::BulkLeakCheckServiceInterface::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.
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
index 067b79f09b7..ef4fb104178 100644
--- 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
@@ -74,6 +74,7 @@ using password_manager::BulkLeakCheckDelegateInterface;
using password_manager::BulkLeakCheckService;
using password_manager::CompromisedCredentials;
using password_manager::CompromiseType;
+using password_manager::CompromiseTypeFlags;
using password_manager::IsLeaked;
using password_manager::LeakCheckCredential;
using password_manager::TestPasswordStore;
@@ -248,6 +249,27 @@ class PasswordCheckDelegateTest : public ::testing::Test {
} // namespace
+TEST_F(PasswordCheckDelegateTest, VerifyCastingOfCompromisedCredentialTypes) {
+ static_assert(
+ static_cast<int>(api::passwords_private::COMPROMISE_TYPE_NONE) ==
+ static_cast<int>(CompromiseTypeFlags::kNotCompromised),
+ "");
+ static_assert(
+ static_cast<int>(api::passwords_private::COMPROMISE_TYPE_LEAKED) ==
+ static_cast<int>(CompromiseTypeFlags::kCredentialLeaked),
+ "");
+ static_assert(
+ static_cast<int>(api::passwords_private::COMPROMISE_TYPE_PHISHED) ==
+ static_cast<int>(CompromiseTypeFlags::kCredentialPhished),
+ "");
+ static_assert(
+ static_cast<int>(
+ api::passwords_private::COMPROMISE_TYPE_PHISHED_AND_LEAKED) ==
+ static_cast<int>(CompromiseTypeFlags::kCredentialLeaked |
+ CompromiseTypeFlags::kCredentialPhished),
+ "");
+}
+
// 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
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 15df0b1ca92..c66d3306367 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
@@ -77,7 +77,16 @@ ResponseAction PasswordsPrivateRemoveSavedPasswordFunction::Run() {
auto parameters =
api::passwords_private::RemoveSavedPassword::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(parameters);
- GetDelegate(browser_context())->RemoveSavedPassword(parameters->id);
+ GetDelegate(browser_context())->RemoveSavedPasswords({parameters->id});
+ return RespondNow(NoArguments());
+}
+
+// PasswordsPrivateRemoveSavedPasswordsFunction
+ResponseAction PasswordsPrivateRemoveSavedPasswordsFunction::Run() {
+ auto parameters =
+ api::passwords_private::RemoveSavedPasswords::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+ GetDelegate(browser_context())->RemoveSavedPasswords(parameters->ids);
return RespondNow(NoArguments());
}
@@ -86,7 +95,16 @@ ResponseAction PasswordsPrivateRemovePasswordExceptionFunction::Run() {
auto parameters =
api::passwords_private::RemovePasswordException::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(parameters);
- GetDelegate(browser_context())->RemovePasswordException(parameters->id);
+ GetDelegate(browser_context())->RemovePasswordExceptions({parameters->id});
+ return RespondNow(NoArguments());
+}
+
+// PasswordsPrivateRemovePasswordExceptionsFunction
+ResponseAction PasswordsPrivateRemovePasswordExceptionsFunction::Run() {
+ auto parameters =
+ api::passwords_private::RemovePasswordExceptions::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+ GetDelegate(browser_context())->RemovePasswordExceptions(parameters->ids);
return RespondNow(NoArguments());
}
@@ -176,6 +194,16 @@ void PasswordsPrivateGetPasswordExceptionListFunction::GotList(
entries)));
}
+// PasswordsPrivateMovePasswordToAccountFunction
+ResponseAction PasswordsPrivateMovePasswordToAccountFunction::Run() {
+ auto parameters =
+ api::passwords_private::MovePasswordToAccount::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+ GetDelegate(browser_context())
+ ->MovePasswordToAccount(parameters->id, GetSenderWebContents());
+ return RespondNow(NoArguments());
+}
+
// PasswordsPrivateImportPasswordsFunction
ResponseAction PasswordsPrivateImportPasswordsFunction::Run() {
GetDelegate(browser_context())->ImportPasswords(GetSenderWebContents());
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 b374835ffa2..3505216b22a 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
@@ -54,6 +54,18 @@ class PasswordsPrivateRemoveSavedPasswordFunction : public ExtensionFunction {
ResponseAction Run() override;
};
+class PasswordsPrivateRemoveSavedPasswordsFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removeSavedPasswords",
+ PASSWORDSPRIVATE_REMOVESAVEDPASSWORDS)
+
+ protected:
+ ~PasswordsPrivateRemoveSavedPasswordsFunction() override = default;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
class PasswordsPrivateRemovePasswordExceptionFunction
: public ExtensionFunction {
public:
@@ -67,6 +79,19 @@ class PasswordsPrivateRemovePasswordExceptionFunction
ResponseAction Run() override;
};
+class PasswordsPrivateRemovePasswordExceptionsFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removePasswordExceptions",
+ PASSWORDSPRIVATE_REMOVEPASSWORDEXCEPTIONS)
+
+ protected:
+ ~PasswordsPrivateRemovePasswordExceptionsFunction() override = default;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
class PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction
: public ExtensionFunction {
public:
@@ -131,6 +156,18 @@ class PasswordsPrivateGetPasswordExceptionListFunction
void GotList(const PasswordsPrivateDelegate::ExceptionEntries& entries);
};
+class PasswordsPrivateMovePasswordToAccountFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.movePasswordToAccount",
+ PASSWORDSPRIVATE_MOVEPASSWORDTOACCOUNT)
+
+ protected:
+ ~PasswordsPrivateMovePasswordToAccountFunction() override = default;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
class PasswordsPrivateImportPasswordsFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.importPasswords",
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 eba6dbddfd3..45337a9fd68 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
@@ -108,6 +108,10 @@ class PasswordsPrivateApiTest : public ExtensionApiTest {
s_test_delegate_->AddCompromisedCredential(id);
}
+ base::Optional<int> last_moved_password() const {
+ return s_test_delegate_->last_moved_password();
+ }
+
private:
TestPasswordsPrivateDelegate* s_test_delegate_ = nullptr;
@@ -127,11 +131,23 @@ IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
}
IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ RemoveAndUndoRemoveSavedPasswordsBatch) {
+ EXPECT_TRUE(RunPasswordsSubtest("removeAndUndoRemoveSavedPasswordsBatch"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
RemoveAndUndoRemovePasswordException) {
EXPECT_TRUE(RunPasswordsSubtest("removeAndUndoRemovePasswordException"))
<< message_;
}
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ RemoveAndUndoRemovePasswordExceptionsBatch) {
+ EXPECT_TRUE(RunPasswordsSubtest("removeAndUndoRemovePasswordExceptionsBatch"))
+ << message_;
+}
+
IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RequestPlaintextPassword) {
EXPECT_TRUE(RunPasswordsSubtest("requestPlaintextPassword")) << message_;
}
@@ -259,4 +275,10 @@ IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, GetPasswordCheckStatus) {
EXPECT_TRUE(RunPasswordsSubtest("getPasswordCheckStatus")) << message_;
}
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, MovePasswordToAccount) {
+ EXPECT_FALSE(last_moved_password().has_value());
+ EXPECT_TRUE(RunPasswordsSubtest("movePasswordToAccount")) << message_;
+ EXPECT_EQ(42, last_moved_password());
+}
+
} // 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 b1c9d8c20f1..edb030dfe12 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
@@ -65,15 +65,13 @@ class PasswordsPrivateDelegate : public KeyedService {
base::string16 new_username,
base::Optional<base::string16> new_password) = 0;
- // Removes the saved password 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.
- virtual void RemoveSavedPassword(int id) = 0;
+ // Removes the saved password entries corresponding to the |ids| generated for
+ // each entry of the password list. Any invalid id will be ignored.
+ virtual void RemoveSavedPasswords(const std::vector<int>& ids) = 0;
- // Removes the saved password exception entry corresponding set in the
- // given |id|
- // |id| The id for the exception url entry being removed.
- virtual void RemovePasswordException(int id) = 0;
+ // Removes the password exceptions entries corresponding corresponding to
+ // |ids|. Any invalid id will be ignored.
+ virtual void RemovePasswordExceptions(const std::vector<int>& ids) = 0;
// Undoes the last removal of a saved password or exception.
virtual void UndoRemoveSavedPasswordOrException() = 0;
@@ -92,6 +90,14 @@ class PasswordsPrivateDelegate : public KeyedService {
PlaintextPasswordCallback callback,
content::WebContents* web_contents) = 0;
+ // Moves a password currently stored on the device to being stored in the
+ // signed-in, non-syncing Google Account. The result is a no-op if any of
+ // these is true: |id| is invalid; |id| corresponds to a password already
+ // stored in the account; or the user is not using the account-scoped password
+ // storage.
+ virtual void MovePasswordToAccount(int id,
+ content::WebContents* web_contents) = 0;
+
// Trigger the password import procedure, allowing the user to select a file
// containing passwords to import.
virtual void ImportPasswords(content::WebContents* web_contents) = 0;
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 2aaf4ec2863..b23254c66fc 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
@@ -29,6 +29,7 @@
#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/base/signin_metrics.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/l10n/l10n_util.h"
@@ -122,6 +123,20 @@ password_manager::PlaintextReason ConvertPlaintextReason(
return password_manager::PlaintextReason::kView;
}
+// Gets all the existing keys in |generator| corresponding to |ids|. If no key
+// is found for an id, it is simply ignored.
+std::vector<std::string> GetSortKeys(
+ const extensions::IdGenerator<std::string>& generator,
+ const std::vector<int> ids) {
+ std::vector<std::string> sort_keys;
+ sort_keys.reserve(ids.size());
+ for (int id : ids) {
+ if (const std::string* sort_key = generator.TryGetKey(id))
+ sort_keys.emplace_back(*sort_key);
+ }
+ return sort_keys;
+}
+
} // namespace
namespace extensions {
@@ -197,28 +212,30 @@ void PasswordsPrivateDelegateImpl::ChangeSavedPassword(
*sort_key, std::move(new_username), std::move(new_password));
}
-void PasswordsPrivateDelegateImpl::RemoveSavedPassword(int id) {
+void PasswordsPrivateDelegateImpl::RemoveSavedPasswords(
+ const std::vector<int>& ids) {
ExecuteFunction(
- base::Bind(&PasswordsPrivateDelegateImpl::RemoveSavedPasswordInternal,
- base::Unretained(this), id));
+ base::Bind(&PasswordsPrivateDelegateImpl::RemoveSavedPasswordsInternal,
+ base::Unretained(this), ids));
}
-void PasswordsPrivateDelegateImpl::RemoveSavedPasswordInternal(int id) {
- const std::string* sort_key = password_id_generator_.TryGetKey(id);
- if (sort_key)
- password_manager_presenter_->RemoveSavedPassword(*sort_key);
+void PasswordsPrivateDelegateImpl::RemoveSavedPasswordsInternal(
+ const std::vector<int>& ids) {
+ password_manager_presenter_->RemoveSavedPasswords(
+ GetSortKeys(password_id_generator_, ids));
}
-void PasswordsPrivateDelegateImpl::RemovePasswordException(int id) {
- ExecuteFunction(
- base::Bind(&PasswordsPrivateDelegateImpl::RemovePasswordExceptionInternal,
- base::Unretained(this), id));
+void PasswordsPrivateDelegateImpl::RemovePasswordExceptions(
+ const std::vector<int>& ids) {
+ ExecuteFunction(base::Bind(
+ &PasswordsPrivateDelegateImpl::RemovePasswordExceptionsInternal,
+ base::Unretained(this), ids));
}
-void PasswordsPrivateDelegateImpl::RemovePasswordExceptionInternal(int id) {
- const std::string* sort_key = exception_id_generator_.TryGetKey(id);
- if (sort_key)
- password_manager_presenter_->RemovePasswordException(*sort_key);
+void PasswordsPrivateDelegateImpl::RemovePasswordExceptionsInternal(
+ const std::vector<int>& ids) {
+ password_manager_presenter_->RemovePasswordExceptions(
+ GetSortKeys(exception_id_generator_, ids));
}
void PasswordsPrivateDelegateImpl::UndoRemoveSavedPasswordOrException() {
@@ -267,8 +284,10 @@ void PasswordsPrivateDelegateImpl::RequestPlaintextPassword(
std::move(callback).Run(base::nullopt);
return;
}
- ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
- .WriteText(*password);
+ ui::ScopedClipboardWriter clipboard_writer(
+ ui::ClipboardBuffer::kCopyPaste);
+ clipboard_writer.WriteText(*password);
+ clipboard_writer.MarkAsConfidential();
std::move(callback).Run(base::string16());
},
std::move(callback));
@@ -325,6 +344,9 @@ void PasswordsPrivateDelegateImpl::SetPasswordList(
entry.username = base::UTF16ToUTF8(form->username_value);
entry.id = password_id_generator_.GenerateId(
password_manager::CreateSortKey(*form));
+ entry.frontend_id = password_frontend_id_generator_.GenerateId(
+ password_manager::CreateSortKey(*form,
+ password_manager::IgnoreStore(true)));
if (!form->federation_origin.opaque()) {
entry.federation_text.reset(new std::string(l10n_util::GetStringFUTF8(
@@ -360,6 +382,10 @@ void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
current_exception_entry.urls = CreateUrlCollectionFromForm(*form);
current_exception_entry.id = exception_id_generator_.GenerateId(
password_manager::CreateSortKey(*form));
+ current_exception_entry.frontend_id =
+ exception_frontend_id_generator_.GenerateId(
+ password_manager::CreateSortKey(
+ *form, password_manager::IgnoreStore(true)));
current_exception_entry.from_account_store = form->IsUsingAccountStore();
current_exceptions_.push_back(std::move(current_exception_entry));
@@ -378,6 +404,18 @@ void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
get_password_exception_list_callbacks_.clear();
}
+void PasswordsPrivateDelegateImpl::MovePasswordToAccount(
+ int id,
+ content::WebContents* web_contents) {
+ auto* client = ChromePasswordManagerClient::FromWebContents(web_contents);
+ // TODO(victorvianna): Use a DCHECK instead.
+ if (!client)
+ return;
+
+ if (const std::string* sort_key = password_id_generator_.TryGetKey(id))
+ password_manager_presenter_->MovePasswordToAccountStore(*sort_key, client);
+}
+
void PasswordsPrivateDelegateImpl::ImportPasswords(
content::WebContents* web_contents) {
password_manager_porter_->set_web_contents(web_contents);
@@ -434,7 +472,8 @@ void PasswordsPrivateDelegateImpl::SetAccountStorageOptIn(
return;
}
// The opt in pref is automatically set upon successful reauth.
- client->TriggerReauthForPrimaryAccount(base::DoNothing());
+ client->TriggerReauthForPrimaryAccount(
+ signin_metrics::ReauthAccessPoint::kPasswordSettings, base::DoNothing());
}
std::vector<api::passwords_private::CompromisedCredential>
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 5e37007baf2..10de06d47d2 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
@@ -53,13 +53,15 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
int id,
base::string16 new_username,
base::Optional<base::string16> new_password) override;
- void RemoveSavedPassword(int id) override;
- void RemovePasswordException(int id) override;
+ void RemoveSavedPasswords(const std::vector<int>& ids) override;
+ void RemovePasswordExceptions(const std::vector<int>& ids) override;
void UndoRemoveSavedPasswordOrException() override;
void RequestPlaintextPassword(int id,
api::passwords_private::PlaintextReason reason,
PlaintextPasswordCallback callback,
content::WebContents* web_contents) override;
+ void MovePasswordToAccount(int id,
+ 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;
@@ -123,8 +125,8 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
void SendSavedPasswordsList();
void SendPasswordExceptionsList();
- void RemoveSavedPasswordInternal(int id);
- void RemovePasswordExceptionInternal(int id);
+ void RemoveSavedPasswordsInternal(const std::vector<int>& ids);
+ void RemovePasswordExceptionsInternal(const std::vector<int>& ids);
void UndoRemoveSavedPasswordOrExceptionInternal();
// Callback for when the password list has been written to the destination.
@@ -162,7 +164,9 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
// Generators that map between sort keys used by |password_manager_presenter_|
// and ids used by the JavaScript front end.
IdGenerator<std::string> password_id_generator_;
+ IdGenerator<std::string> password_frontend_id_generator_;
IdGenerator<std::string> exception_id_generator_;
+ IdGenerator<std::string> exception_frontend_id_generator_;
// Whether SetPasswordList and SetPasswordExceptionList have been called, and
// whether this class has been initialized, meaning both have been called.
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 015feb23ab7..7871953f2e6 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
@@ -36,6 +36,7 @@
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/reauth_purpose.h"
#include "components/password_manager/core/browser/test_password_store.h"
+#include "components/signin/public/base/signin_metrics.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_renderer_host.h"
@@ -49,9 +50,11 @@ using MockReauthCallback = base::MockCallback<
using PasswordFormList = std::vector<std::unique_ptr<autofill::PasswordForm>>;
using password_manager::ReauthPurpose;
using password_manager::TestPasswordStore;
+using ::testing::_;
using ::testing::Eq;
using ::testing::Ne;
using ::testing::Return;
+using ::testing::SizeIs;
using ::testing::StrictMock;
namespace extensions {
@@ -84,7 +87,8 @@ class MockPasswordManagerClient : public ChromePasswordManagerClient {
// ChromePasswordManagerClient overrides.
MOCK_METHOD(void,
TriggerReauthForPrimaryAccount,
- (base::OnceCallback<void(ReauthSucceeded)>),
+ (signin_metrics::ReauthAccessPoint,
+ base::OnceCallback<void(ReauthSucceeded)>),
(override));
const password_manager::MockPasswordFeatureManager*
GetPasswordFeatureManager() const override {
@@ -168,7 +172,7 @@ std::unique_ptr<KeyedService> BuildPasswordsPrivateEventRouter(
autofill::PasswordForm CreateSampleForm() {
autofill::PasswordForm form;
form.signon_realm = "http://abc1.com";
- form.origin = GURL("http://abc1.com");
+ form.url = GURL("http://abc1.com");
form.username_value = base::ASCIIToUTF16("test@gmail.com");
form.password_value = base::ASCIIToUTF16("test");
return form;
@@ -247,6 +251,34 @@ TEST_F(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {
delegate.GetSavedPasswordsList(callback.Get());
}
+TEST_F(PasswordsPrivateDelegateImplTest,
+ PasswordsDuplicatedInStoresHaveSameFrontendId) {
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+
+ auto account_password = std::make_unique<autofill::PasswordForm>();
+ account_password->in_store = autofill::PasswordForm::Store::kAccountStore;
+ auto profile_password = std::make_unique<autofill::PasswordForm>();
+ profile_password->in_store = autofill::PasswordForm::Store::kProfileStore;
+
+ PasswordFormList list;
+ list.push_back(std::move(account_password));
+ list.push_back(std::move(profile_password));
+
+ delegate.SetPasswordList(list);
+
+ base::MockCallback<PasswordsPrivateDelegate::UiEntriesCallback> callback;
+ int first_frontend_id, second_frontend_id;
+ EXPECT_CALL(callback, Run(SizeIs(2)))
+ .WillOnce([&](const PasswordsPrivateDelegate::UiEntries& passwords) {
+ first_frontend_id = passwords[0].frontend_id;
+ second_frontend_id = passwords[1].frontend_id;
+ });
+
+ delegate.GetSavedPasswordsList(callback.Get());
+
+ EXPECT_EQ(first_frontend_id, second_frontend_id);
+}
+
TEST_F(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
PasswordsPrivateDelegateImpl delegate(&profile_);
@@ -265,6 +297,38 @@ TEST_F(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
delegate.GetPasswordExceptionsList(callback.Get());
}
+TEST_F(PasswordsPrivateDelegateImplTest,
+ ExceptionsDuplicatedInStoresHaveSameFrontendId) {
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+
+ auto account_exception = std::make_unique<autofill::PasswordForm>();
+ account_exception->blacklisted_by_user = true;
+ account_exception->in_store = autofill::PasswordForm::Store::kAccountStore;
+ auto profile_exception = std::make_unique<autofill::PasswordForm>();
+ profile_exception->blacklisted_by_user = true;
+ profile_exception->in_store = autofill::PasswordForm::Store::kProfileStore;
+
+ PasswordFormList list;
+ list.push_back(std::move(account_exception));
+ list.push_back(std::move(profile_exception));
+
+ delegate.SetPasswordExceptionList(list);
+
+ base::MockCallback<PasswordsPrivateDelegate::ExceptionEntriesCallback>
+ callback;
+ int first_frontend_id, second_frontend_id;
+ EXPECT_CALL(callback, Run(SizeIs(2)))
+ .WillOnce(
+ [&](const PasswordsPrivateDelegate::ExceptionEntries& exceptions) {
+ first_frontend_id = exceptions[0].frontend_id;
+ second_frontend_id = exceptions[1].frontend_id;
+ });
+
+ delegate.GetPasswordExceptionsList(callback.Get());
+
+ EXPECT_EQ(first_frontend_id, second_frontend_id);
+}
+
TEST_F(PasswordsPrivateDelegateImplTest, ChangeSavedPassword) {
autofill::PasswordForm sample_form = CreateSampleForm();
SetUpPasswordStore({sample_form});
@@ -348,7 +412,9 @@ TEST_F(PasswordsPrivateDelegateImplTest, TestShouldReauthForOptIn) {
ON_CALL(*(client->GetPasswordFeatureManager()), IsOptedInForAccountStorage)
.WillByDefault(Return(false));
- EXPECT_CALL(*client, TriggerReauthForPrimaryAccount);
+ EXPECT_CALL(*client,
+ TriggerReauthForPrimaryAccount(
+ signin_metrics::ReauthAccessPoint::kPasswordSettings, _));
PasswordsPrivateDelegateImpl delegate(&profile_);
delegate.SetAccountStorageOptIn(true, web_contents.get());
@@ -368,7 +434,10 @@ TEST_F(PasswordsPrivateDelegateImplTest,
ON_CALL(*feature_manager, IsOptedInForAccountStorage)
.WillByDefault(Return(true));
- EXPECT_CALL(*client, TriggerReauthForPrimaryAccount).Times(0);
+ EXPECT_CALL(*client,
+ TriggerReauthForPrimaryAccount(
+ signin_metrics::ReauthAccessPoint::kPasswordSettings, _))
+ .Times(0);
EXPECT_CALL(*feature_manager, OptOutOfAccountStorageAndClearSettings);
PasswordsPrivateDelegateImpl delegate(&profile_);
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 574cac203aa..bca700f8a15 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
@@ -13,8 +13,8 @@ namespace extensions {
TEST(CreateUrlCollectionFromFormTest, UrlsFromHtmlForm) {
autofill::PasswordForm html_form;
- html_form.origin = GURL("http://example.com/LoginAuth");
- html_form.signon_realm = html_form.origin.GetOrigin().spec();
+ html_form.url = GURL("http://example.com/LoginAuth");
+ html_form.signon_realm = html_form.url.GetOrigin().spec();
api::passwords_private::UrlCollection html_urls =
CreateUrlCollectionFromForm(html_form);
@@ -26,7 +26,7 @@ TEST(CreateUrlCollectionFromFormTest, UrlsFromHtmlForm) {
TEST(CreateUrlCollectionFromFormTest, UrlsFromFederatedForm) {
autofill::PasswordForm federated_form;
federated_form.signon_realm = "federation://example.com/google.com";
- federated_form.origin = GURL("https://example.com/");
+ federated_form.url = GURL("https://example.com/");
federated_form.federation_origin =
url::Origin::Create(GURL("https://google.com/"));
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
index 6f0005f6cf9..593c0d9a140 100644
--- 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
@@ -26,6 +26,7 @@ api::passwords_private::PasswordUiEntry CreateEntry(int id) {
entry.urls.link = entry.urls.origin;
entry.username = "testName" + base::NumberToString(id);
entry.id = id;
+ entry.frontend_id = id;
return entry;
}
@@ -35,6 +36,7 @@ api::passwords_private::ExceptionEntry CreateException(int id) {
exception.urls.origin = "http://" + exception.urls.shown + "/login";
exception.urls.link = exception.urls.origin;
exception.id = id;
+ exception.frontend_id = id;
return exception;
}
} // namespace
@@ -72,36 +74,55 @@ void TestPasswordsPrivateDelegate::ChangeSavedPassword(
SendSavedPasswordsList();
}
-void TestPasswordsPrivateDelegate::RemoveSavedPassword(int id) {
+void TestPasswordsPrivateDelegate::RemoveSavedPasswords(
+ const std::vector<int>& ids) {
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());
+ // Since this is just mock data, remove the first |ids.size()| elements
+ // regardless of the data contained.
+ auto first_remaining = (ids.size() <= current_entries_.size())
+ ? current_entries_.begin() + ids.size()
+ : current_entries_.end();
+ last_deleted_entries_batch_.assign(
+ std::make_move_iterator(current_entries_.begin()),
+ std::make_move_iterator(first_remaining));
+ current_entries_.erase(current_entries_.begin(), first_remaining);
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());
+void TestPasswordsPrivateDelegate::RemovePasswordExceptions(
+ const std::vector<int>& ids) {
+ if (current_exceptions_.empty())
+ return;
+
+ // Since this is just mock data, remove the first |ids.size()| elements
+ // regardless of the data contained.
+ auto first_remaining = (ids.size() <= current_exceptions_.size())
+ ? current_exceptions_.begin() + ids.size()
+ : current_exceptions_.end();
+ last_deleted_exceptions_batch_.assign(
+ std::make_move_iterator(current_exceptions_.begin()),
+ std::make_move_iterator(first_remaining));
+ current_exceptions_.erase(current_exceptions_.begin(), first_remaining);
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;
+ if (!last_deleted_entries_batch_.empty()) {
+ current_entries_.insert(
+ current_entries_.begin(),
+ std::make_move_iterator(last_deleted_entries_batch_.begin()),
+ std::make_move_iterator(last_deleted_entries_batch_.end()));
+ last_deleted_entries_batch_.clear();
SendSavedPasswordsList();
- } else if (last_deleted_exception_) {
- current_exceptions_.insert(current_exceptions_.begin(),
- std::move(*last_deleted_exception_));
- last_deleted_exception_ = base::nullopt;
+ } else if (!last_deleted_exceptions_batch_.empty()) {
+ current_exceptions_.insert(
+ current_exceptions_.begin(),
+ std::make_move_iterator(last_deleted_exceptions_batch_.begin()),
+ std::make_move_iterator(last_deleted_exceptions_batch_.end()));
+ last_deleted_exceptions_batch_.clear();
SendPasswordExceptionsList();
}
}
@@ -115,6 +136,12 @@ void TestPasswordsPrivateDelegate::RequestPlaintextPassword(
std::move(callback).Run(plaintext_password_);
}
+void TestPasswordsPrivateDelegate::MovePasswordToAccount(
+ int id,
+ content::WebContents* web_contents) {
+ last_moved_password_ = id;
+}
+
void TestPasswordsPrivateDelegate::ImportPasswords(
content::WebContents* web_contents) {
// The testing of password importing itself should be handled via
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
index 639c9092fc4..3b88cedf525 100644
--- 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
@@ -5,6 +5,7 @@
#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/optional.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"
@@ -25,14 +26,16 @@ class TestPasswordsPrivateDelegate : public PasswordsPrivateDelegate {
void ChangeSavedPassword(int id,
base::string16 username,
base::Optional<base::string16> password) override;
- void RemoveSavedPassword(int id) override;
- void RemovePasswordException(int id) override;
+ void RemoveSavedPasswords(const std::vector<int>& id) override;
+ void RemovePasswordExceptions(const std::vector<int>& ids) 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 MovePasswordToAccount(int id,
+ 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;
@@ -84,6 +87,10 @@ class TestPasswordsPrivateDelegate : public PasswordsPrivateDelegate {
start_password_check_state_ = state;
}
+ base::Optional<int> last_moved_password() const {
+ return last_moved_password_;
+ }
+
private:
void SendSavedPasswordsList();
void SendPasswordExceptionsList();
@@ -93,11 +100,15 @@ class TestPasswordsPrivateDelegate : public PasswordsPrivateDelegate {
// 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_;
+
+ // Simplified version of an undo manager that only allows undoing and redoing
+ // the very last deletion. When the batches are *empty*, this means there is
+ // no previous deletion to undo.
+ std::vector<api::passwords_private::PasswordUiEntry>
+ last_deleted_entries_batch_;
+ std::vector<api::passwords_private::ExceptionEntry>
+ last_deleted_exceptions_batch_;
+
base::Optional<base::string16> plaintext_password_ =
base::ASCIIToUTF16("plaintext");
@@ -118,6 +129,9 @@ class TestPasswordsPrivateDelegate : public PasswordsPrivateDelegate {
bool stop_password_check_triggered_ = false;
password_manager::BulkLeakCheckService::State start_password_check_state_ =
password_manager::BulkLeakCheckService::State::kRunning;
+
+ // Records the id of the last password that was moved.
+ base::Optional<int> last_moved_password_ = base::nullopt;
};
} // namespace extensions
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 be4e536005b..366ae43ac65 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
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
#include "base/values.h"
#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h"
#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h"
@@ -37,6 +38,8 @@ const char kErrorInteractiveCallFromBackground[] =
"Interactive calls must happen in the context of a browser tab or a "
"window.";
+const char kWebCryptoEcdsa[] = "ECDSA";
+const char kWebCryptoNamedCurveP256[] = "P-256";
const char kWebCryptoRSASSA_PKCS1_v1_5[] = "RSASSA-PKCS1-v1_5";
struct PublicKeyInfo {
@@ -58,7 +61,7 @@ struct PublicKeyInfo {
void BuildWebCryptoRSAAlgorithmDictionary(const PublicKeyInfo& key_info,
base::DictionaryValue* algorithm) {
CHECK_EQ(net::X509Certificate::kPublicKeyTypeRSA, key_info.key_type);
- algorithm->SetKey("name", base::Value(kWebCryptoRSASSA_PKCS1_v1_5));
+ algorithm->SetStringKey("name", kWebCryptoRSASSA_PKCS1_v1_5);
algorithm->SetKey("modulusLength",
base::Value(static_cast<int>(key_info.key_size_bits)));
@@ -71,6 +74,15 @@ void BuildWebCryptoRSAAlgorithmDictionary(const PublicKeyInfo& key_info,
base::size(defaultPublicExponent)));
}
+void BuildWebCryptoEcdsaAlgorithmDictionary(const PublicKeyInfo& key_info,
+ base::DictionaryValue* algorithm) {
+ CHECK_EQ(net::X509Certificate::kPublicKeyTypeECDSA, key_info.key_type);
+ algorithm->SetStringKey("name", kWebCryptoEcdsa);
+
+ // Only P-256 named curve is supported.
+ algorithm->SetStringKey("namedCurve", kWebCryptoNamedCurveP256);
+}
+
const struct NameValuePair {
const char* const name;
const int value;
@@ -84,6 +96,7 @@ const struct NameValuePair {
namespace platform_keys {
+const char kErrorInvalidSpki[] = "The SubjectPublicKeyInfo is not valid.";
const char kErrorInvalidToken[] = "The token is not valid.";
const char kErrorInvalidX509Cert[] =
"Certificate is not a valid X.509 certificate.";
@@ -145,25 +158,85 @@ PlatformKeysInternalGetPublicKeyFunction::Run() {
chromeos::platform_keys::GetSubjectPublicKeyInfo(cert_x509);
if (!chromeos::platform_keys::GetPublicKey(cert_x509, &key_info.key_type,
&key_info.key_size_bits) ||
+ (key_info.key_type != net::X509Certificate::kPublicKeyTypeRSA &&
+ key_info.key_type != net::X509Certificate::kPublicKeyTypeECDSA)) {
+ return RespondNow(Error(kErrorAlgorithmNotSupported));
+ }
+
+ // Currently, the only supported combinations are:
+ // 1- A certificate declaring rsaEncryption in the SubjectPublicKeyInfo used
+ // with the RSASSA-PKCS1-v1.5 algorithm.
+ // 2- A certificate declaring id-ecPublicKey in the SubjectPublicKeyInfo used
+ // with the ECDSA algorithm.
+ if (params->algorithm_name == kWebCryptoRSASSA_PKCS1_v1_5) {
+ if (key_info.key_type != net::X509Certificate::kPublicKeyTypeRSA) {
+ return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
+ }
+
+ api_pki::GetPublicKey::Results::Algorithm algorithm;
+ BuildWebCryptoRSAAlgorithmDictionary(key_info,
+ &algorithm.additional_properties);
+
+ return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create(
+ std::vector<uint8_t>(key_info.public_key_spki_der.begin(),
+ key_info.public_key_spki_der.end()),
+ algorithm)));
+ }
+
+ if (params->algorithm_name == kWebCryptoEcdsa) {
+ if (key_info.key_type != net::X509Certificate::kPublicKeyTypeECDSA) {
+ return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
+ }
+
+ api_pki::GetPublicKey::Results::Algorithm algorithm;
+ BuildWebCryptoEcdsaAlgorithmDictionary(key_info,
+ &algorithm.additional_properties);
+
+ return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create(
+ std::vector<uint8_t>(key_info.public_key_spki_der.begin(),
+ key_info.public_key_spki_der.end()),
+ algorithm)));
+ }
+
+ return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
+}
+
+PlatformKeysInternalGetPublicKeyBySpkiFunction::
+ ~PlatformKeysInternalGetPublicKeyBySpkiFunction() = default;
+
+ExtensionFunction::ResponseAction
+PlatformKeysInternalGetPublicKeyBySpkiFunction::Run() {
+ std::unique_ptr<api_pki::GetPublicKeyBySpki::Params> params(
+ api_pki::GetPublicKeyBySpki::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ const auto& public_key_spki_der = params->public_key_spki_der;
+ if (public_key_spki_der.empty())
+ return RespondNow(Error(platform_keys::kErrorInvalidSpki));
+
+ PublicKeyInfo key_info;
+ key_info.public_key_spki_der.assign(std::begin(public_key_spki_der),
+ std::end(public_key_spki_der));
+
+ if (!chromeos::platform_keys::GetPublicKeyBySpki(key_info.public_key_spki_der,
+ &key_info.key_type,
+ &key_info.key_size_bits) ||
key_info.key_type != net::X509Certificate::kPublicKeyTypeRSA) {
return RespondNow(Error(kErrorAlgorithmNotSupported));
}
// Currently, the only supported combination is:
- // A certificate declaring rsaEncryption in the SubjectPublicKeyInfo used
- // with the RSASSA-PKCS1-v1.5 algorithm.
+ // A SPKI declaring rsaEncryption used with the RSASSA-PKCS1-v1.5 algorithm.
if (params->algorithm_name != kWebCryptoRSASSA_PKCS1_v1_5) {
- return RespondNow(Error(kErrorAlgorithmNotPermittedByCertificate));
+ return RespondNow(Error(kErrorAlgorithmNotSupported));
}
- api_pki::GetPublicKey::Results::Algorithm algorithm;
+ api_pki::GetPublicKeyBySpki::Results::Algorithm algorithm;
BuildWebCryptoRSAAlgorithmDictionary(key_info,
&algorithm.additional_properties);
- return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create(
- std::vector<uint8_t>(key_info.public_key_spki_der.begin(),
- key_info.public_key_spki_der.end()),
- algorithm)));
+ return RespondNow(ArgumentList(api_pki::GetPublicKeyBySpki::Results::Create(
+ public_key_spki_der, algorithm)));
}
PlatformKeysInternalSelectClientCertificatesFunction::
@@ -305,7 +378,7 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() {
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")
+ if (params->algorithm_name != kWebCryptoRSASSA_PKCS1_v1_5)
return RespondNow(Error(kErrorAlgorithmNotSupported));
service->SignRSAPKCS1Raw(
@@ -329,9 +402,9 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() {
}
chromeos::platform_keys::KeyType key_type;
- if (params->algorithm_name == "RSASSA-PKCS1-v1_5") {
+ if (params->algorithm_name == kWebCryptoRSASSA_PKCS1_v1_5) {
key_type = chromeos::platform_keys::KeyType::kRsassaPkcs1V15;
- } else if (params->algorithm_name == "ECDSA") {
+ } else if (params->algorithm_name == kWebCryptoEcdsa) {
key_type = chromeos::platform_keys::KeyType::kEcdsa;
} else {
return RespondNow(Error(kErrorAlgorithmNotSupported));
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.h b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
index 4d1ece03673..fe503135b62 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
+++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
@@ -56,6 +56,16 @@ class PlatformKeysInternalGetPublicKeyFunction : public ExtensionFunction {
PLATFORMKEYSINTERNAL_GETPUBLICKEY)
};
+class PlatformKeysInternalGetPublicKeyBySpkiFunction
+ : public ExtensionFunction {
+ private:
+ ~PlatformKeysInternalGetPublicKeyBySpkiFunction() override;
+ ResponseAction Run() override;
+
+ DECLARE_EXTENSION_FUNCTION("platformKeysInternal.getPublicKeyBySpki",
+ PLATFORMKEYSINTERNAL_GETPUBLICKEYBYSPKI)
+};
+
class PlatformKeysInternalSignFunction : public ExtensionFunction {
private:
~PlatformKeysInternalSignFunction() override;
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 1b2bcb7417a..c5b730978bb 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
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
-#include "base/task/post_task.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"
@@ -21,6 +20,7 @@
#include "chrome/browser/profiles/profile.h"
#include "components/policy/policy_constants.h"
#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test.h"
#include "crypto/nss_util_internal.h"
#include "crypto/scoped_nss_types.h"
@@ -53,8 +53,8 @@ class PlatformKeysTest : public PlatformKeysTestBase {
// |PlatformKeysTestBase::SetUpOnMainThread| triggers the user sign-in.
ASSERT_TRUE(user_private_slot_db_.is_open());
base::RunLoop loop;
- base::PostTaskAndReply(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTaskAndReply(
+ FROM_HERE,
base::BindOnce(&PlatformKeysTest::SetPrivateSoftwareSlotOnIO,
base::Unretained(this),
crypto::ScopedPK11Slot(
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
index 166d76a626f..b1847d07f98 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
+++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/path_service.h"
#include "base/run_loop.h"
-#include "base/task/post_task.h"
#include "chrome/browser/chromeos/policy/affiliation_test_helper.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/ui/browser.h"
@@ -155,8 +154,8 @@ void PlatformKeysTestBase::SetUpOnMainThread() {
if (system_token_status() == SystemTokenStatus::EXISTS) {
base::RunLoop loop;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&PlatformKeysTestBase::SetUpTestSystemSlotOnIO,
base::Unretained(this), loop.QuitClosure()));
loop.Run();
@@ -170,8 +169,8 @@ void PlatformKeysTestBase::TearDownOnMainThread() {
if (system_token_status() == SystemTokenStatus::EXISTS) {
base::RunLoop loop;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&PlatformKeysTestBase::TearDownTestSystemSlotOnIO,
base::Unretained(this), loop.QuitClosure()));
loop.Run();
@@ -211,14 +210,14 @@ void PlatformKeysTestBase::SetUpTestSystemSlotOnIO(
PrepareTestSystemSlotOnIO(test_system_slot_.get());
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- std::move(done_callback));
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
+ std::move(done_callback));
}
void PlatformKeysTestBase::TearDownTestSystemSlotOnIO(
base::OnceClosure done_callback) {
test_system_slot_.reset();
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- std::move(done_callback));
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
+ std::move(done_callback));
}
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 6f382e521ba..1daf379593b 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
@@ -12,7 +12,6 @@
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
#include "chrome/common/extensions/api/platform_keys_internal.h"
#include "content/public/browser/browser_task_traits.h"
@@ -113,8 +112,8 @@ void VerifyTrustAPI::Verify(std::unique_ptr<Params> params,
&CallBackOnUI, base::Bind(&VerifyTrustAPI::FinishedVerificationOnUI,
weak_factory_.GetWeakPtr(), ui_callback)));
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&IOPart::Verify, base::Unretained(io_part_.get()),
std::move(params), extension_id, finish_callback));
}
@@ -123,8 +122,8 @@ void VerifyTrustAPI::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&IOPart::OnExtensionUnloaded,
base::Unretained(io_part_.get()), extension->id()));
}
@@ -143,8 +142,8 @@ void VerifyTrustAPI::CallBackOnUI(const VerifyCallback& ui_callback,
const std::string& error,
int return_value,
int cert_status) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(ui_callback, error, return_value, cert_status));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(ui_callback, error, return_value, cert_status));
}
VerifyTrustAPI::IOPart::~IOPart() {
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
index 3dfd9b014ce..e11e90a7f90 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -42,7 +42,7 @@
class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
protected:
- ExtensionPreferenceApiTest() : profile_(NULL) {}
+ ExtensionPreferenceApiTest() : profile_(nullptr) {}
void CheckPreferencesSet() {
PrefService* prefs = profile_->GetPrefs();
@@ -168,7 +168,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest, Standard) {
const char kExtensionPath[] = "preference/standard";
- EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_;
+ EXPECT_TRUE(RunExtensionTest(kExtensionPath)) << message_;
CheckPreferencesSet();
// The settings should not be reset when the extension is reloaded.
diff --git a/chromium/chrome/browser/extensions/api/processes/processes_api.cc b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
index bd0417665c3..112a293b669 100644
--- a/chromium/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
@@ -17,7 +17,6 @@
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
@@ -512,8 +511,8 @@ ExtensionFunction::ResponseAction ProcessesTerminateFunction::Run() {
// This could be a non-renderer child process like a plugin or a nacl
// process. Try to get its handle from the BrowserChildProcessHost on the
// IO thread.
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult(
+ FROM_HERE,
base::BindOnce(&ProcessesTerminateFunction::GetProcessHandleOnIO, this,
child_process_host_id_),
base::BindOnce(&ProcessesTerminateFunction::OnProcessHandleOnUI, this));
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
index 153d46d923d..1a56cf910e8 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -18,6 +18,7 @@
#include <utility>
#include "base/base64.h"
+#include "base/notreached.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
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 24faa7952af..a3597241802 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
@@ -10,21 +10,15 @@
#include "base/values.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/ui/webui/webui_util.h"
#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"
#include "ui/base/webui/web_ui_util.h"
#if BUILDFLAG(ENABLE_PDF)
-#include "pdf/pdf_features.h"
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/ui/login_display_host.h"
-#endif // defined(OS_CHROMEOS)
+#include "chrome/browser/pdf/pdf_extension_util.h"
#endif // BUILDFLAG(ENABLE_PDF)
// To add a new component to this API, simply:
@@ -42,109 +36,6 @@ void AddStringsForIdentity(base::DictionaryValue* dict) {
l10n_util::GetStringUTF16(IDS_EXTENSION_CONFIRM_PERMISSIONS));
}
-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},
- {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT},
- {"passwordInvalid", IDS_PDF_PASSWORD_INVALID},
- {"pageLoading", IDS_PDF_PAGE_LOADING},
- {"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED},
- {"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE},
- {"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON},
- {"bookmarks", IDS_PDF_BOOKMARKS},
- {"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER},
- {"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW},
- {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
- {"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)
- {"tooltipAnnotate", IDS_PDF_ANNOTATION_ANNOTATE},
- {"annotationDocumentTooLarge", IDS_PDF_ANNOTATION_DOCUMENT_TOO_LARGE},
- {"annotationDocumentProtected", IDS_PDF_ANNOTATION_DOCUMENT_PROTECTED},
- {"annotationDocumentRotated", IDS_PDF_ANNOTATION_DOCUMENT_ROTATED},
- {"annotationPen", IDS_PDF_ANNOTATION_PEN},
- {"annotationHighlighter", IDS_PDF_ANNOTATION_HIGHLIGHTER},
- {"annotationEraser", IDS_PDF_ANNOTATION_ERASER},
- {"annotationUndo", IDS_PDF_ANNOTATION_UNDO},
- {"annotationRedo", IDS_PDF_ANNOTATION_REDO},
- {"annotationExpand", IDS_PDF_ANNOTATION_EXPAND},
- {"annotationColorBlack", IDS_PDF_ANNOTATION_COLOR_BLACK},
- {"annotationColorRed", IDS_PDF_ANNOTATION_COLOR_RED},
- {"annotationColorYellow", IDS_PDF_ANNOTATION_COLOR_YELLOW},
- {"annotationColorGreen", IDS_PDF_ANNOTATION_COLOR_GREEN},
- {"annotationColorCyan", IDS_PDF_ANNOTATION_COLOR_CYAN},
- {"annotationColorPurple", IDS_PDF_ANNOTATION_COLOR_PURPLE},
- {"annotationColorBrown", IDS_PDF_ANNOTATION_COLOR_BROWN},
- {"annotationColorWhite", IDS_PDF_ANNOTATION_COLOR_WHITE},
- {"annotationColorCrimson", IDS_PDF_ANNOTATION_COLOR_CRIMSON},
- {"annotationColorAmber", IDS_PDF_ANNOTATION_COLOR_AMBER},
- {"annotationColorAvocadoGreen", IDS_PDF_ANNOTATION_COLOR_AVOCADO_GREEN},
- {"annotationColorCobaltBlue", IDS_PDF_ANNOTATION_COLOR_COBALT_BLUE},
- {"annotationColorDeepPurple", IDS_PDF_ANNOTATION_COLOR_DEEP_PURPLE},
- {"annotationColorDarkBrown", IDS_PDF_ANNOTATION_COLOR_DARK_BROWN},
- {"annotationColorDarkGrey", IDS_PDF_ANNOTATION_COLOR_DARK_GREY},
- {"annotationColorHotPink", IDS_PDF_ANNOTATION_COLOR_HOT_PINK},
- {"annotationColorOrange", IDS_PDF_ANNOTATION_COLOR_ORANGE},
- {"annotationColorLime", IDS_PDF_ANNOTATION_COLOR_LIME},
- {"annotationColorBlue", IDS_PDF_ANNOTATION_COLOR_BLUE},
- {"annotationColorViolet", IDS_PDF_ANNOTATION_COLOR_VIOLET},
- {"annotationColorTeal", IDS_PDF_ANNOTATION_COLOR_TEAL},
- {"annotationColorLightGrey", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREY},
- {"annotationColorLightPink", IDS_PDF_ANNOTATION_COLOR_LIGHT_PINK},
- {"annotationColorLightOrange", IDS_PDF_ANNOTATION_COLOR_LIGHT_ORANGE},
- {"annotationColorLightGreen", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREEN},
- {"annotationColorLightBlue", IDS_PDF_ANNOTATION_COLOR_LIGHT_BLUE},
- {"annotationColorLavender", IDS_PDF_ANNOTATION_COLOR_LAVENDER},
- {"annotationColorLightTeal", IDS_PDF_ANNOTATION_COLOR_LIGHT_TEAL},
- {"annotationSize1", IDS_PDF_ANNOTATION_SIZE1},
- {"annotationSize2", IDS_PDF_ANNOTATION_SIZE2},
- {"annotationSize3", IDS_PDF_ANNOTATION_SIZE3},
- {"annotationSize4", IDS_PDF_ANNOTATION_SIZE4},
- {"annotationSize8", IDS_PDF_ANNOTATION_SIZE8},
- {"annotationSize12", IDS_PDF_ANNOTATION_SIZE12},
- {"annotationSize16", IDS_PDF_ANNOTATION_SIZE16},
- {"annotationSize20", IDS_PDF_ANNOTATION_SIZE20},
- {"annotationFormWarningTitle", IDS_PDF_DISCARD_FORM_CHANGES},
- {"annotationFormWarningDetail", IDS_PDF_DISCARD_FORM_CHANGES_DETAIL},
- {"annotationFormWarningKeepEditing", IDS_PDF_KEEP_EDITING},
- {"annotationFormWarningDiscard", IDS_PDF_DISCARD},
-#endif // defined(OS_CHROMEOS)
- };
- 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) {
-#if BUILDFLAG(ENABLE_PDF)
- dict->SetKey("pdfFormSaveEnabled",
- base::Value(base::FeatureList::IsEnabled(
- chrome_pdf::features::kSaveEditedPDFForm)));
- 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)
- // For Chrome OS, enable printing only if we are not at OOBE.
- enable_printing = !chromeos::LoginDisplayHost::default_host();
-#endif // defined(OS_CHROMEOS)
- dict->SetKey("printingEnabled", base::Value(enable_printing));
-#endif // BUILDFLAG(ENABLE_PDF)
-}
-
} // namespace
namespace get_strings = api::resources_private::GetStrings;
@@ -164,10 +55,13 @@ ExtensionFunction::ResponseAction ResourcesPrivateGetStringsFunction::Run() {
case api::resources_private::COMPONENT_IDENTITY:
AddStringsForIdentity(dict.get());
break;
- case api::resources_private::COMPONENT_PDF:
- AddStringsForPdf(dict.get());
- AddAdditionalDataForPdf(dict.get());
- break;
+#if BUILDFLAG(ENABLE_PDF)
+ case api::resources_private::COMPONENT_PDF: {
+ pdf_extension_util::AddStrings(pdf_extension_util::PdfViewerContext::kAll,
+ dict.get());
+ pdf_extension_util::AddAdditionalData(dict.get());
+ } break;
+#endif // BUILDFLAG(ENABLE_PDF)
case api::resources_private::COMPONENT_NONE:
NOTREACHED();
}
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 a8d41b78f10..ead182f7275 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
@@ -94,7 +94,7 @@ class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate {
no_updates_.erase(id);
DownloadFinishedArgs args;
args.path = path;
- args.version = version;
+ args.version = base::Version(version);
updates_[id] = std::move(args);
}
@@ -107,7 +107,7 @@ class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate {
// expecting a synchronous reply (the real code has to go do at least one
// network request before getting a response, so this is is a reasonable
// expectation by delegates).
- for (const std::string& id : fetch_data->extension_ids()) {
+ for (const std::string& id : fetch_data->GetExtensionIds()) {
auto no_update = no_updates_.find(id);
if (no_update != no_updates_.end()) {
no_updates_.erase(no_update);
@@ -147,7 +147,7 @@ class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate {
// Simple holder for the data passed in AddUpdateResponse calls.
struct DownloadFinishedArgs {
base::FilePath path;
- std::string version;
+ base::Version version;
};
// These keep track of what response we should give for update checks, keyed
@@ -206,7 +206,8 @@ class ChromeRuntimeAPIDelegateTest : public ExtensionServiceTestWithInstall {
// Setup the ExtensionService so that extension updates won't complete
// installation until the extension is idle.
- update_install_gate_ = std::make_unique<UpdateInstallGate>(service());
+ update_install_gate_ =
+ std::make_unique<UpdateInstallGate>(service()->profile());
service()->RegisterInstallGate(ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
update_install_gate_.get());
static_cast<TestExtensionSystem*>(ExtensionSystem::Get(browser_context()))
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 e0dbf81759b..6c34804f9dc 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
@@ -18,17 +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"
-#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
-#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#else
-#include "chrome/browser/policy/browser_dm_token_storage.h"
-#include "chrome/browser/policy/chrome_browser_cloud_management_controller.h"
-#endif
+#include "chrome/browser/enterprise/connectors/common.h"
+#include "chrome/browser/enterprise/connectors/connectors_manager.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
@@ -36,6 +27,8 @@
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/reporting_util.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h"
+#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service_factory.h"
+#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/common/extensions/api/safe_browsing_private.h"
@@ -45,18 +38,27 @@
#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/content/web_ui/safe_browsing_ui.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"
-#include "components/user_manager/user_manager.h"
-#endif
#include "content/public/browser/browser_context.h"
#include "extensions/browser/event_router.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/browser_process_platform_part_chromeos.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
+#else
+#include "chrome/browser/policy/browser_dm_token_storage.h"
+#include "chrome/browser/policy/chrome_browser_cloud_management_controller.h"
+#endif
+
namespace {
#if defined(OS_CHROMEOS)
@@ -68,46 +70,29 @@ const char kChromeBrowserCloudManagementClientDescription[] =
"a machine-level user";
#endif
-void AddDlpVerdictToEvent(const safe_browsing::DlpDeepScanningVerdict& verdict,
- base::Value* event) {
+void AddAnalysisConnectorVerdictToEvent(
+ const safe_browsing::ContentAnalysisScanResult& result,
+ base::Value* event) {
DCHECK(event);
base::ListValue triggered_rule_info;
- for (const auto& rule : verdict.triggered_rules()) {
+ for (const auto& trigger : result.triggers) {
base::Value triggered_rule(base::Value::Type::DICTIONARY);
- triggered_rule.SetIntKey(
- extensions::SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleId,
- rule.rule_id());
+ int64_t rule_id;
+ if (base::StringToInt64(trigger.id, &rule_id)) {
+ triggered_rule.SetIntKey(
+ extensions::SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleId,
+ rule_id);
+ } else {
+ triggered_rule.SetIntKey(
+ extensions::SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleId, 0);
+ }
+
triggered_rule.SetStringKey(
extensions::SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleName,
- rule.rule_name());
- triggered_rule.SetStringKey(extensions::SafeBrowsingPrivateEventRouter::
- kKeyTriggeredRuleResourceName,
- rule.rule_resource_name());
- triggered_rule.SetStringKey(
- extensions::SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleSeverity,
- rule.rule_severity());
+ trigger.name);
triggered_rule.SetIntKey(
extensions::SafeBrowsingPrivateEventRouter::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(
- extensions::SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorId,
- detector.detector_id());
- matched_detector.SetStringKey(
- extensions::SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorName,
- detector.display_name());
- matched_detector.SetStringKey(
- extensions::SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorType,
- detector.detector_type());
-
- matched_detectors.Append(std::move(matched_detector));
- }
- triggered_rule.SetKey(
- extensions::SafeBrowsingPrivateEventRouter::kKeyMatchedDetectors,
- std::move(matched_detectors));
+ trigger.action);
triggered_rule_info.Append(std::move(triggered_rule));
}
@@ -116,12 +101,22 @@ void AddDlpVerdictToEvent(const safe_browsing::DlpDeepScanningVerdict& verdict,
std::move(triggered_rule_info));
}
+std::string MalwareRuleToThreatType(const std::string& rule_name) {
+ if (rule_name == "UWS") {
+ return "POTENTIALLY_UNWANTED";
+ } else if (rule_name == "MALWARE") {
+ return "DANGEROUS";
+ } else {
+ return "UNKNOWN";
+ }
+}
+
} // namespace
namespace extensions {
const base::Feature SafeBrowsingPrivateEventRouter::kRealtimeReportingFeature{
- "SafeBrowsingRealtimeReporting", base::FEATURE_ENABLED_BY_DEFAULT};
+ "SafeBrowsingRealtimeReporting", base::FEATURE_DISABLED_BY_DEFAULT};
// Key names used with when building the dictionary to pass to the real-time
// reporting API.
@@ -140,19 +135,7 @@ const char SafeBrowsingPrivateEventRouter::kKeyClickedThrough[] =
"clickedThrough";
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";
@@ -172,6 +155,8 @@ const char SafeBrowsingPrivateEventRouter::kKeySensitiveDataEvent[] =
"sensitiveDataEvent";
const char SafeBrowsingPrivateEventRouter::kKeyUnscannedFileEvent[] =
"unscannedFileEvent";
+const char SafeBrowsingPrivateEventRouter::kKeyUnscannedReason[] =
+ "unscannedReason";
const char SafeBrowsingPrivateEventRouter::kTriggerFileDownload[] =
"FILE_DOWNLOAD";
@@ -183,18 +168,6 @@ SafeBrowsingPrivateEventRouter::SafeBrowsingPrivateEventRouter(
content::BrowserContext* context)
: context_(context) {
event_router_ = EventRouter::Get(context_);
-
- // g_browser_process and/or g_browser_process->local_state() may be null
- // in tests.
- if (g_browser_process && g_browser_process->local_state()) {
- RealtimeReportingPrefChanged(std::string());
- registrar_.Init(g_browser_process->local_state());
- registrar_.Add(
- prefs::kUnsafeEventsReportingEnabled,
- base::BindRepeating(
- &SafeBrowsingPrivateEventRouter::RealtimeReportingPrefChanged,
- base::Unretained(this)));
- }
}
SafeBrowsingPrivateEventRouter::~SafeBrowsingPrivateEventRouter() {}
@@ -418,6 +391,30 @@ void SafeBrowsingPrivateEventRouter::OnSecurityInterstitialProceeded(
params.url, params.reason, net_error_code, params.user_name));
}
+void SafeBrowsingPrivateEventRouter::OnAnalysisConnectorResult(
+ const GURL& url,
+ const std::string& file_name,
+ const std::string& download_digest_sha256,
+ const std::string& mime_type,
+ const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint /* access_point */,
+ const safe_browsing::ContentAnalysisScanResult& result,
+ const int64_t content_size) {
+ if (!IsRealtimeReportingEnabled())
+ return;
+
+ if (result.tag == "malware") {
+ DCHECK_EQ(1u, result.triggers.size());
+ OnDangerousDeepScanningResult(
+ url, file_name, download_digest_sha256,
+ MalwareRuleToThreatType(result.triggers[0].name), mime_type, trigger,
+ content_size);
+ } else if (result.tag == "dlp") {
+ OnSensitiveDataEvent(url, file_name, download_digest_sha256, mime_type,
+ trigger, result, content_size);
+ }
+}
+
void SafeBrowsingPrivateEventRouter::OnDangerousDeepScanningResult(
const GURL& url,
const std::string& file_name,
@@ -459,12 +456,12 @@ void SafeBrowsingPrivateEventRouter::OnDangerousDeepScanningResult(
}
void SafeBrowsingPrivateEventRouter::OnSensitiveDataEvent(
- const safe_browsing::DlpDeepScanningVerdict& verdict,
const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& mime_type,
const std::string& trigger,
+ const safe_browsing::ContentAnalysisScanResult& result,
const int64_t content_size) {
if (!IsRealtimeReportingEnabled())
return;
@@ -472,7 +469,7 @@ void SafeBrowsingPrivateEventRouter::OnSensitiveDataEvent(
ReportRealtimeEvent(
kKeySensitiveDataEvent,
base::BindOnce(
- [](const safe_browsing::DlpDeepScanningVerdict& verdict,
+ [](const safe_browsing::ContentAnalysisScanResult& result,
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,
@@ -493,33 +490,38 @@ void SafeBrowsingPrivateEventRouter::OnSensitiveDataEvent(
event.SetStringKey(kKeyTrigger, trigger);
event.SetBoolKey(kKeyClickedThrough, false);
- AddDlpVerdictToEvent(verdict, &event);
+ AddAnalysisConnectorVerdictToEvent(result, &event);
return event;
},
- verdict, url.spec(), file_name, download_digest_sha256,
+ result, url.spec(), file_name, download_digest_sha256,
GetProfileUserName(), mime_type, trigger, content_size));
}
-void SafeBrowsingPrivateEventRouter::OnSensitiveDataWarningBypassed(
- const safe_browsing::DlpDeepScanningVerdict& verdict,
+void SafeBrowsingPrivateEventRouter::OnAnalysisConnectorWarningBypassed(
const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& mime_type,
const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint access_point,
+ const safe_browsing::ContentAnalysisScanResult& result,
const int64_t content_size) {
if (!IsRealtimeReportingEnabled())
return;
+ DCHECK_EQ("dlp", result.tag);
+
ReportRealtimeEvent(
kKeySensitiveDataEvent,
base::BindOnce(
- [](const safe_browsing::DlpDeepScanningVerdict& verdict,
+ [](const safe_browsing::ContentAnalysisScanResult& result,
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) {
+ const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint /* access_point */,
+ const int64_t content_size) {
// Create a real-time event dictionary from the arguments and
// report it.
base::Value event(base::Value::Type::DICTIONARY);
@@ -536,12 +538,13 @@ void SafeBrowsingPrivateEventRouter::OnSensitiveDataWarningBypassed(
event.SetStringKey(kKeyTrigger, trigger);
event.SetBoolKey(kKeyClickedThrough, true);
- AddDlpVerdictToEvent(verdict, &event);
+ AddAnalysisConnectorVerdictToEvent(result, &event);
return event;
},
- verdict, url.spec(), file_name, download_digest_sha256,
- GetProfileUserName(), mime_type, trigger, content_size));
+ result, url.spec(), file_name, download_digest_sha256,
+ GetProfileUserName(), mime_type, trigger, access_point,
+ content_size));
}
void SafeBrowsingPrivateEventRouter::OnUnscannedFileEvent(
@@ -550,6 +553,7 @@ void SafeBrowsingPrivateEventRouter::OnUnscannedFileEvent(
const std::string& download_digest_sha256,
const std::string& mime_type,
const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint access_point,
const std::string& reason,
const int64_t content_size) {
if (!IsRealtimeReportingEnabled())
@@ -561,8 +565,9 @@ void SafeBrowsingPrivateEventRouter::OnUnscannedFileEvent(
[](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 std::string& reason,
- const int64_t content_size) {
+ const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint access_point,
+ const std::string& reason, const int64_t content_size) {
// Create a real-time event dictionary from the arguments and
// report it.
base::Value event(base::Value::Type::DICTIONARY);
@@ -572,7 +577,7 @@ void SafeBrowsingPrivateEventRouter::OnUnscannedFileEvent(
download_digest_sha256);
event.SetStringKey(kKeyProfileUserName, profile_user_name);
event.SetStringKey(kKeyContentType, mime_type);
- event.SetStringKey(kKeyReason, reason);
+ event.SetStringKey(kKeyUnscannedReason, reason);
// |content_size| can be set to -1 to indicate an unknown size, in
// which case the field is not set.
if (content_size >= 0)
@@ -581,7 +586,7 @@ void SafeBrowsingPrivateEventRouter::OnUnscannedFileEvent(
return event;
},
url.spec(), file_name, download_digest_sha256, GetProfileUserName(),
- mime_type, trigger, reason, content_size));
+ mime_type, trigger, access_point, reason, content_size));
}
void SafeBrowsingPrivateEventRouter::OnDangerousDownloadWarning(
@@ -664,7 +669,9 @@ void SafeBrowsingPrivateEventRouter::OnDangerousDownloadWarningBypassed(
// static
bool SafeBrowsingPrivateEventRouter::ShouldInitRealtimeReportingClient() {
- if (!base::FeatureList::IsEnabled(kRealtimeReportingFeature)) {
+ if (!base::FeatureList::IsEnabled(kRealtimeReportingFeature) &&
+ !base::FeatureList::IsEnabled(
+ enterprise_connectors::kEnterpriseConnectorsEnabled)) {
DVLOG(2) << "Safe browsing real-time reporting is not enabled.";
return false;
}
@@ -687,6 +694,11 @@ void SafeBrowsingPrivateEventRouter::SetBinaryUploadServiceForTesting(
binary_upload_service_ = binary_upload_service;
}
+void SafeBrowsingPrivateEventRouter::SetIdentityManagerForTesting(
+ signin::IdentityManager* identity_manager) {
+ identity_manager_ = identity_manager;
+}
+
void SafeBrowsingPrivateEventRouter::InitRealtimeReportingClient() {
// If already initialized, do nothing.
if (client_) {
@@ -719,26 +731,6 @@ void SafeBrowsingPrivateEventRouter::InitRealtimeReportingClient() {
return;
}
- if (g_browser_process) {
- binary_upload_service_ =
- safe_browsing::BinaryUploadServiceFactory::GetForProfile(
- Profile::FromBrowserContext(context_));
- IfAuthorized(base::BindOnce(
- &SafeBrowsingPrivateEventRouter::InitRealtimeReportingClientCallback,
- weak_ptr_factory_.GetWeakPtr(), device_management_service));
- }
-}
-
-void SafeBrowsingPrivateEventRouter::InitRealtimeReportingClientCallback(
- policy::DeviceManagementService* device_management_service,
- bool authorized) {
- // Don't initialize the client if the browser cannot upload data.
- if (!authorized) {
- LOG(WARNING) << "The client is not authorized to do safe browsing "
- "real-time event reporting.";
- return;
- }
-
policy::CloudPolicyClient* client = nullptr;
std::string policy_client_desc;
@@ -791,6 +783,11 @@ void SafeBrowsingPrivateEventRouter::InitRealtimeReportingClientCallback(
policy::CloudPolicyClient::DeviceDMTokenCallback());
client = private_client_.get();
+ // TODO(crbug.com/1069049): when we decide to add the extra URL parameters to
+ // the uploaded reports, do the following:
+ // client->add_connector_url_params(base::FeatureList::IsEnabled(
+ // enterprise_connectors::kEnterpriseConnectorsEnabled));
+
if (!client->is_registered()) {
client->SetupRegistration(
dm_token.value(), client_id,
@@ -815,25 +812,24 @@ void SafeBrowsingPrivateEventRouter::OnCloudPolicyClientAvailable(
}
bool SafeBrowsingPrivateEventRouter::IsRealtimeReportingEnabled() {
- // g_browser_process and/or g_browser_process->local_state() may be null
- // in tests.
- return g_browser_process && g_browser_process->local_state() &&
- g_browser_process->local_state()->GetBoolean(
- prefs::kUnsafeEventsReportingEnabled);
-}
-
-void SafeBrowsingPrivateEventRouter::RealtimeReportingPrefChanged(
- const std::string& pref) {
- // If the reporting policy has been turned on, try to initialized now.
- if (IsRealtimeReportingEnabled())
- InitRealtimeReportingClient();
+ auto settings =
+ enterprise_connectors::ConnectorsManager::GetInstance()
+ ->GetReportingSettings(
+ enterprise_connectors::ReportingConnector::SECURITY_EVENT);
+ return settings.has_value();
}
void SafeBrowsingPrivateEventRouter::IfAuthorized(
base::OnceCallback<void(bool)> cont) {
- if (binary_upload_service_) {
- binary_upload_service_->IsAuthorized(std::move(cont));
+ if (!binary_upload_service_ && g_browser_process) {
+ binary_upload_service_ =
+ safe_browsing::BinaryUploadServiceFactory::GetForProfile(
+ Profile::FromBrowserContext(context_));
}
+
+ // TODO(crbug/1069049): Use reporting URL.
+ if (binary_upload_service_)
+ binary_upload_service_->IsAuthorized(GURL(), std::move(cont));
}
void SafeBrowsingPrivateEventRouter::ReportRealtimeEvent(
@@ -854,8 +850,10 @@ void SafeBrowsingPrivateEventRouter::ReportRealtimeEventCallback(
return;
}
- // |client_| should be set when authorized is true.
- DCHECK(client_);
+ // Make sure real-time reporting is initialized.
+ InitRealtimeReportingClient();
+ if (!client_)
+ return;
// Format the current time (UTC) in RFC3339 format.
base::Time::Exploded now_exploded;
@@ -884,10 +882,18 @@ void SafeBrowsingPrivateEventRouter::ReportRealtimeEventCallback(
}
std::string SafeBrowsingPrivateEventRouter::GetProfileUserName() const {
- // |identity_manager_| may be null is some tests.
- return identity_manager_ && identity_manager_->HasPrimaryAccount()
- ? identity_manager_->GetPrimaryAccountInfo().email
- : std::string();
+ // |identity_manager_| may be null in some tests.
+ if (!identity_manager_)
+ return std::string();
+
+ if (!identity_manager_->HasPrimaryAccount(
+ signin::ConsentLevel::kNotRequired)) {
+ return std::string();
+ }
+
+ return identity_manager_
+ ->GetPrimaryAccountInfo(signin::ConsentLevel::kNotRequired)
+ .email;
}
#if defined(OS_CHROMEOS)
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 dc0ceea0b29..da76717180d 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
@@ -14,7 +14,6 @@
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "components/prefs/pref_change_registrar.h"
namespace content {
class BrowserContext;
@@ -37,7 +36,8 @@ class DeviceManagementService;
namespace safe_browsing {
class BinaryUploadService;
-class DlpDeepScanningVerdict;
+enum class DeepScanAccessPoint;
+struct ContentAnalysisScanResult;
}
#if defined(OS_CHROMEOS)
@@ -71,13 +71,7 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
static const char kKeyClickedThrough[];
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[];
@@ -90,8 +84,10 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
static const char kKeyInterstitialEvent[];
static const char kKeySensitiveDataEvent[];
static const char kKeyUnscannedFileEvent[];
+ static const char kKeyUnscannedReason[];
- // String constants for the "trigger" event field.
+ // String constants for the "trigger" event field. This corresponds to
+ // an enterprise connector.
static const char kTriggerFileDownload[];
static const char kTriggerFileUpload[];
static const char kTriggerWebContentUpload[];
@@ -126,33 +122,26 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
const std::string& reason,
int net_error_code);
- // Notifies listeners that deep scanning detected a dangerous download.
- void OnDangerousDeepScanningResult(const GURL& url,
- const std::string& file_name,
- const std::string& download_digest_sha256,
- const std::string& threat_type,
- const std::string& mime_type,
- const std::string& trigger,
- const int64_t content_size);
-
- // Notifies listeners that scanning for sensitive data detected a violation.
- void OnSensitiveDataEvent(
- const safe_browsing::DlpDeepScanningVerdict& verdict,
+ // Notifies listeners that the analysis connector detected a violation.
+ void OnAnalysisConnectorResult(
const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& mime_type,
const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint access_point,
+ const safe_browsing::ContentAnalysisScanResult& result,
const int64_t content_size);
- // Notifies listeners that scanning for sensitive data detected a violation.
- void OnSensitiveDataWarningBypassed(
- const safe_browsing::DlpDeepScanningVerdict& verdict,
+ // Notifies listeners that an analysis connector violation was bypassed.
+ void OnAnalysisConnectorWarningBypassed(
const GURL& url,
const std::string& file_name,
const std::string& download_digest_sha256,
const std::string& mime_type,
const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint access_point,
+ const safe_browsing::ContentAnalysisScanResult& result,
const int64_t content_size);
// Notifies listeners that deep scanning failed, for the given |reason|.
@@ -161,6 +150,7 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
const std::string& download_digest_sha256,
const std::string& mime_type,
const std::string& trigger,
+ safe_browsing::DeepScanAccessPoint access_point,
const std::string& reason,
const int64_t content_size);
@@ -199,6 +189,8 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
void SetBinaryUploadServiceForTesting(
safe_browsing::BinaryUploadService* binary_upload_service);
+ void SetIdentityManagerForTesting(signin::IdentityManager* identity_manager);
+
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
@@ -215,12 +207,6 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
// with CBCM and the appropriate policies are enabled.
void InitRealtimeReportingClient();
- // Initialize DeviceManagementService and |client_| after validating the
- // browser can upload data.
- void InitRealtimeReportingClientCallback(
- policy::DeviceManagementService* device_management_service,
- bool authorized);
-
// Continues execution if the client is authorized to do so.
void IfAuthorized(base::OnceCallback<void(bool)> cont);
@@ -261,6 +247,25 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
// an empty string if the profile is not signed in.
std::string GetProfileUserName() const;
+ // Notifies listeners that deep scanning detected a dangerous download.
+ void OnDangerousDeepScanningResult(const GURL& url,
+ const std::string& file_name,
+ const std::string& download_digest_sha256,
+ const std::string& threat_type,
+ const std::string& mime_type,
+ const std::string& trigger,
+ const int64_t content_size);
+
+ // Notifies listeners that the analysis connector detected a violation.
+ void OnSensitiveDataEvent(
+ const GURL& url,
+ const std::string& file_name,
+ const std::string& download_digest_sha256,
+ const std::string& mime_type,
+ const std::string& trigger,
+ const safe_browsing::ContentAnalysisScanResult& result,
+ const int64_t content_size);
+
content::BrowserContext* context_;
signin::IdentityManager* identity_manager_ = nullptr;
EventRouter* event_router_ = nullptr;
@@ -271,7 +276,6 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
// The |private_client_| is used on platforms where we cannot just get a
// client and we create our own (used through |client_|).
std::unique_ptr<policy::CloudPolicyClient> private_client_;
- PrefChangeRegistrar registrar_;
base::WeakPtrFactory<SafeBrowsingPrivateEventRouter> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SafeBrowsingPrivateEventRouter);
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 3b5e213a364..4685fb42d13 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
@@ -3,9 +3,11 @@
// found in the LICENSE file.
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
+#include "base/json/json_reader.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/mock_callback.h"
@@ -13,7 +15,10 @@
#include "base/values.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
+#include "chrome/browser/enterprise/connectors/common.h"
+#include "chrome/browser/enterprise/connectors/connectors_manager.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
+#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/safe_browsing_private.h"
#include "chrome/test/base/testing_browser_process.h"
@@ -22,7 +27,9 @@
#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/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/features.h"
#include "components/safe_browsing/core/proto/webprotect.pb.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/test_event_router.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -40,6 +47,7 @@
using ::testing::_;
using ::testing::Mock;
+using ::testing::Return;
using ::testing::SaveArg;
namespace extensions {
@@ -50,6 +58,12 @@ ACTION_P(CaptureArg, wrapper) {
*wrapper = arg0.Clone();
}
+constexpr char kConnectorsPrefValue[] = R"([
+ {
+ "service_provider": "google"
+ }
+])";
+
} // namespace
class FakeAuthorizedSafeBrowsingPrivateEventRouter
@@ -175,41 +189,31 @@ class SafeBrowsingPrivateEventRouterTest : public testing::Test {
}
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");
+ safe_browsing::ContentAnalysisScanResult result;
+ result.tag = "dlp";
+ result.status = 1;
+ safe_browsing::ContentAnalysisTrigger trigger;
+ trigger.action = 3;
+ trigger.name = "fake rule";
+ trigger.id = "12345";
+ result.triggers.push_back(std::move(trigger));
SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile_)
- ->OnSensitiveDataEvent(verdict,
- GURL("https://evil.com/sensitive_data.txt"),
- "sensitive_data.txt", "sha256_of_data",
- "text/plain", "FILE_UPLOAD", 12345);
+ ->OnAnalysisConnectorResult(
+ GURL("https://evil.com/sensitive_data.txt"), "sensitive_data.txt",
+ "sha256_of_data", "text/plain",
+ SafeBrowsingPrivateEventRouter::kTriggerFileUpload,
+ safe_browsing::DeepScanAccessPoint::UPLOAD, result, 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);
+ ->OnUnscannedFileEvent(
+ GURL("https://evil.com/sensitive_data.txt"), "sensitive_data.txt",
+ "sha256_of_data", "text/plain",
+ SafeBrowsingPrivateEventRouter::kTriggerFileDownload,
+ safe_browsing::DeepScanAccessPoint::DOWNLOAD,
+ "filePasswordProtected", 12345);
}
void SetReportingPolicy(bool enabled) {
@@ -714,7 +718,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnSensitiveDataEvent) {
EXPECT_EQ(
"sensitive_data.txt",
*event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyFileName));
- EXPECT_EQ("FILE_UPLOAD",
+ EXPECT_EQ(SafeBrowsingPrivateEventRouter::kTriggerFileUpload,
*event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyTrigger));
base::Value* triggered_rule_info =
@@ -729,27 +733,6 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnSensitiveDataEvent) {
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) {
@@ -786,10 +769,48 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnUnscannedFileEvent) {
EXPECT_EQ(
"sensitive_data.txt",
*event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyFileName));
- EXPECT_EQ("FILE_DOWNLOAD",
+ EXPECT_EQ(SafeBrowsingPrivateEventRouter::kTriggerFileDownload,
*event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyTrigger));
EXPECT_EQ("filePasswordProtected",
- *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyReason));
+ *event->FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyUnscannedReason));
+}
+
+TEST_F(SafeBrowsingPrivateEventRouterTest, TestProfileUsername) {
+ SetUpRouters();
+ SafeBrowsingEventObserver event_observer(
+ api::safe_browsing_private::OnSecurityInterstitialShown::kEventName);
+ event_router_->AddEventObserver(&event_observer);
+
+ signin::IdentityTestEnvironment identity_test_environment;
+ SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile_)
+ ->SetIdentityManagerForTesting(
+ identity_test_environment.identity_manager());
+
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).WillRepeatedly(Return());
+
+ // With no primary account, we should not set the username.
+ TriggerOnSecurityInterstitialShownEvent();
+ base::RunLoop().RunUntilIdle();
+ auto captured_args = event_observer.PassEventArgs().GetList()[0].Clone();
+ EXPECT_EQ("", captured_args.FindKey("userName")->GetString());
+
+ // With an unconsented primary account, we should set the username.
+ identity_test_environment.MakeUnconsentedPrimaryAccountAvailable(
+ "profile@example.com");
+ TriggerOnSecurityInterstitialShownEvent();
+ base::RunLoop().RunUntilIdle();
+ captured_args = event_observer.PassEventArgs().GetList()[0].Clone();
+ EXPECT_EQ("profile@example.com",
+ captured_args.FindKey("userName")->GetString());
+
+ // With a consented primary account, we should set the username.
+ identity_test_environment.MakePrimaryAccountAvailable("profile@example.com");
+ TriggerOnSecurityInterstitialShownEvent();
+ base::RunLoop().RunUntilIdle();
+ captured_args = event_observer.PassEventArgs().GetList()[0].Clone();
+ EXPECT_EQ("profile@example.com",
+ captured_args.FindKey("userName")->GetString());
}
// Tests to make sure the feature flag and policy control real-time reporting
@@ -799,22 +820,42 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnUnscannedFileEvent) {
// bool: whether the browser is manageable.
// bool: whether the policy is enabled.
// bool: whether the server has authorized this browser instance.
+// bool: whether to use new connectors or old legacy code.
class SafeBrowsingIsRealtimeReportingEnabledTest
: public SafeBrowsingPrivateEventRouterTest,
public testing::WithParamInterface<
- testing::tuple<bool, bool, bool, bool>> {
+ testing::tuple<bool, bool, bool, bool, bool>> {
public:
SafeBrowsingIsRealtimeReportingEnabledTest()
: is_feature_flag_enabled_(testing::get<0>(GetParam())),
is_manageable_(testing::get<1>(GetParam())),
is_policy_enabled_(testing::get<2>(GetParam())),
- is_authorized_(testing::get<3>(GetParam())) {
- if (is_feature_flag_enabled_) {
- scoped_feature_list_.InitAndEnableFeature(
- SafeBrowsingPrivateEventRouter::kRealtimeReportingFeature);
+ is_authorized_(testing::get<3>(GetParam())),
+ use_new_connectors_(testing::get<4>(GetParam())) {
+ if (use_new_connectors_) {
+ if (is_feature_flag_enabled_) {
+ scoped_feature_list_.InitWithFeatures(
+ {enterprise_connectors::kEnterpriseConnectorsEnabled},
+ {extensions::SafeBrowsingPrivateEventRouter::
+ kRealtimeReportingFeature});
+ } else {
+ scoped_feature_list_.InitWithFeatures(
+ {}, {enterprise_connectors::kEnterpriseConnectorsEnabled,
+ extensions::SafeBrowsingPrivateEventRouter::
+ kRealtimeReportingFeature});
+ }
} else {
- scoped_feature_list_.InitAndDisableFeature(
- SafeBrowsingPrivateEventRouter::kRealtimeReportingFeature);
+ if (is_feature_flag_enabled_) {
+ scoped_feature_list_.InitWithFeatures(
+ {extensions::SafeBrowsingPrivateEventRouter::
+ kRealtimeReportingFeature},
+ {enterprise_connectors::kEnterpriseConnectorsEnabled});
+ } else {
+ scoped_feature_list_.InitWithFeatures(
+ {}, {enterprise_connectors::kEnterpriseConnectorsEnabled,
+ extensions::SafeBrowsingPrivateEventRouter::
+ kRealtimeReportingFeature});
+ }
}
// In chrome branded desktop builds, the browser is always manageable.
@@ -825,8 +866,17 @@ class SafeBrowsingIsRealtimeReportingEnabledTest
}
#endif
- TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean(
- prefs::kUnsafeEventsReportingEnabled, is_policy_enabled_);
+ if (use_new_connectors_) {
+ if (is_policy_enabled_) {
+ scoped_connector_pref_ = std::make_unique<ScopedConnectorPref>(
+ ConnectorPref(
+ enterprise_connectors::ReportingConnector::SECURITY_EVENT),
+ kConnectorsPrefValue);
+ }
+ } else {
+ TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean(
+ prefs::kUnsafeEventsReportingEnabled, is_policy_enabled_);
+ }
#if defined(OS_CHROMEOS)
auto user_manager = std::make_unique<chromeos::FakeChromeUserManager>();
@@ -847,6 +897,15 @@ class SafeBrowsingIsRealtimeReportingEnabledTest
#endif
}
+ void SetUp() override {
+ enterprise_connectors::ConnectorsManager::GetInstance()->SetUpForTesting();
+ }
+
+ void TearDown() override {
+ enterprise_connectors::ConnectorsManager::GetInstance()
+ ->TearDownForTesting();
+ }
+
bool should_init() {
#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !defined(OS_CHROMEOS)
return is_feature_flag_enabled_;
@@ -856,11 +915,32 @@ class SafeBrowsingIsRealtimeReportingEnabledTest
}
protected:
+ class ScopedConnectorPref {
+ public:
+ ScopedConnectorPref(const char* pref, const char* pref_value)
+ : pref_(pref) {
+ auto maybe_pref_value =
+ base::JSONReader::Read(pref_value, base::JSON_ALLOW_TRAILING_COMMAS);
+ EXPECT_TRUE(maybe_pref_value.has_value());
+ TestingBrowserProcess::GetGlobal()->local_state()->Set(
+ pref, maybe_pref_value.value());
+ }
+
+ ~ScopedConnectorPref() {
+ TestingBrowserProcess::GetGlobal()->local_state()->ClearPref(pref_);
+ }
+
+ private:
+ const char* pref_;
+ };
+
base::test::ScopedFeatureList scoped_feature_list_;
+ std::unique_ptr<ScopedConnectorPref> scoped_connector_pref_;
const bool is_feature_flag_enabled_;
const bool is_manageable_;
const bool is_policy_enabled_;
const bool is_authorized_;
+ const bool use_new_connectors_;
#if defined(OS_CHROMEOS)
private:
@@ -918,6 +998,7 @@ INSTANTIATE_TEST_SUITE_P(All,
testing::Combine(testing::Bool(),
testing::Bool(),
testing::Bool(),
+ testing::Bool(),
testing::Bool()));
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc b/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
index f130eced5de..fa30a4353f0 100644
--- a/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
+++ b/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
@@ -207,7 +207,7 @@ ExtensionFunction::ResponseAction SessionsGetRecentlyClosedFunction::Run() {
TabRestoreServiceFactory::GetForProfile(
Profile::FromBrowserContext(browser_context()));
- // TabRestoreServiceFactory::GetForProfile() can return NULL (i.e., when in
+ // TabRestoreServiceFactory::GetForProfile() can return nullptr (i.e., when in
// incognito mode)
if (!tab_restore_service) {
DCHECK(browser_context()->IsOffTheRecord())
@@ -521,7 +521,7 @@ ExtensionFunction::ResponseValue SessionsRestoreFunction::RestoreForeignSession(
if (!open_tabs)
return Error(kSessionSyncError);
- const sessions::SessionTab* tab = NULL;
+ const sessions::SessionTab* tab = nullptr;
if (open_tabs->GetForeignTab(session_id.session_tag(),
SessionID::FromSerializedValue(session_id.id()),
&tab)) {
@@ -583,7 +583,7 @@ ExtensionFunction::ResponseAction SessionsRestoreFunction::Run() {
SessionsEventRouter::SessionsEventRouter(Profile* profile)
: profile_(profile),
tab_restore_service_(TabRestoreServiceFactory::GetForProfile(profile)) {
- // TabRestoreServiceFactory::GetForProfile() can return NULL (i.e., when in
+ // TabRestoreServiceFactory::GetForProfile() can return nullptr (i.e., when in
// incognito mode)
if (tab_restore_service_) {
tab_restore_service_->LoadTabsFromLastSession();
@@ -606,7 +606,7 @@ void SessionsEventRouter::TabRestoreServiceChanged(
void SessionsEventRouter::TabRestoreServiceDestroyed(
sessions::TabRestoreService* service) {
- tab_restore_service_ = NULL;
+ tab_restore_service_ = nullptr;
}
SessionsAPI::SessionsAPI(content::BrowserContext* context)
diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
index 36e74916715..71097a37fc8 100644
--- a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
@@ -297,9 +297,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSessionsTest, GetDevicesListEmpty) {
EXPECT_EQ(0u, devices->GetSize());
}
-// Flaky timeout: http://crbug.com/278372
-IN_PROC_BROWSER_TEST_F(ExtensionSessionsTest,
- DISABLED_RestoreForeignSessionWindow) {
+IN_PROC_BROWSER_TEST_F(ExtensionSessionsTest, RestoreForeignSessionWindow) {
CreateSessionModels();
std::unique_ptr<base::DictionaryValue> restored_window_session(
diff --git a/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc b/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc
index 18323cfb6a8..dbaadf5b940 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.cc
@@ -69,7 +69,7 @@ SetPrefResult GeneratedResolveTimezoneByGeolocationMethodShort::SetPref(
// Check if preference is policy or primary-user controlled.
if (chromeos::system::TimeZoneResolverManager::
IsTimeZoneResolutionPolicyControlled() ||
- !profile_->IsSameProfile(ProfileManager::GetPrimaryUserProfile())) {
+ !profile_->IsSameOrParent(ProfileManager::GetPrimaryUserProfile())) {
return SetPrefResult::PREF_NOT_MODIFIABLE;
}
diff --git a/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc b/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc
index 3eec3a7ea37..edd89c470e1 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc
@@ -73,7 +73,7 @@ SetPrefResult GeneratedResolveTimezoneByGeolocationOnOff::SetPref(
// cannot deactivate automatic timezone.
if (chromeos::system::TimeZoneResolverManager::
IsTimeZoneResolutionPolicyControlled() ||
- !profile_->IsSameProfile(ProfileManager::GetPrimaryUserProfile())) {
+ !profile_->IsSameOrParent(ProfileManager::GetPrimaryUserProfile())) {
return SetPrefResult::PREF_NOT_MODIFIABLE;
}
diff --git a/chromium/chrome/browser/extensions/api/settings_private/generated_pref.cc b/chromium/chrome/browser/extensions/api/settings_private/generated_pref.cc
index b0308f67c07..4fd337bf131 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/generated_pref.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/generated_pref.cc
@@ -4,6 +4,10 @@
#include "chrome/browser/extensions/api/settings_private/generated_pref.h"
+#include "chrome/common/extensions/api/settings_private.h"
+
+namespace settings_api = extensions::api::settings_private;
+
namespace extensions {
namespace settings_private {
@@ -26,5 +30,30 @@ void GeneratedPref::NotifyObservers(const std::string& pref_name) {
observer.OnGeneratedPrefChanged(pref_name);
}
+/* static */
+void GeneratedPref::ApplyControlledByFromPref(
+ api::settings_private::PrefObject* pref_object,
+ const PrefService::Preference* pref) {
+ if (pref->IsManaged()) {
+ pref_object->controlled_by =
+ settings_api::ControlledBy::CONTROLLED_BY_DEVICE_POLICY;
+ return;
+ }
+
+ if (pref->IsExtensionControlled()) {
+ pref_object->controlled_by =
+ settings_api::ControlledBy::CONTROLLED_BY_EXTENSION;
+ return;
+ }
+
+ if (pref->IsManagedByCustodian()) {
+ pref_object->controlled_by =
+ settings_api::ControlledBy::CONTROLLED_BY_CHILD_RESTRICTION;
+ return;
+ }
+
+ NOTREACHED();
+}
+
} // namespace settings_private
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h b/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h
index 3222055de56..00264766f61 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h
+++ b/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "chrome/browser/extensions/api/settings_private/prefs_util_enums.h"
+#include "components/prefs/pref_service.h"
namespace base {
class Value;
@@ -62,6 +63,12 @@ class GeneratedPref {
// Call this when the pref value changes.
void NotifyObservers(const std::string& pref_name);
+ // Sets controlled_by for |pref_object| based on provided |pref| for a limited
+ // subset of controlled_by sources relevant to generated pref use cases.
+ static void ApplyControlledByFromPref(
+ api::settings_private::PrefObject* pref_object,
+ const PrefService::Preference* pref);
+
private:
base::ObserverList<Observer>::Unchecked observers_;
diff --git a/chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.cc b/chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.cc
new file mode 100644
index 00000000000..505519b2c08
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.cc
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/settings_private/generated_pref_test_base.h"
+
+namespace extensions {
+namespace settings_private {
+
+void TestGeneratedPrefObserver::OnGeneratedPrefChanged(
+ const std::string& pref_name) {
+ updated_pref_name_ = pref_name;
+}
+
+} // namespace settings_private
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.h b/chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.h
new file mode 100644
index 00000000000..7036ad4ea2f
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/settings_private/generated_pref_test_base.h
@@ -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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_SETTINGS_PRIVATE_GENERATED_PREF_TEST_BASE_H_
+#define CHROME_BROWSER_EXTENSIONS_API_SETTINGS_PRIVATE_GENERATED_PREF_TEST_BASE_H_
+
+#include "chrome/browser/extensions/api/settings_private/generated_pref.h"
+#include "chrome/common/extensions/api/settings_private.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace settings_api = extensions::api::settings_private;
+
+namespace extensions {
+namespace settings_private {
+
+// 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,
+};
+
+class TestGeneratedPrefObserver : public GeneratedPref::Observer {
+ public:
+ void OnGeneratedPrefChanged(const std::string& pref_name) override;
+
+ void Reset() { updated_pref_name_ = ""; }
+ std::string GetUpdatedPrefName() { return updated_pref_name_; }
+
+ protected:
+ std::string updated_pref_name_;
+};
+
+class GeneratedPrefTestBase : public testing::Test {
+ protected:
+ TestingProfile* profile() { return &profile_; }
+
+ sync_preferences::TestingPrefServiceSyncable* prefs() {
+ return profile()->GetTestingPrefService();
+ }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ TestingProfile profile_;
+};
+
+} // namespace settings_private
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_SETTINGS_PRIVATE_GENERATED_PREF_TEST_BASE_H_
diff --git a/chromium/chrome/browser/extensions/api/settings_private/generated_prefs.cc b/chromium/chrome/browser/extensions/api/settings_private/generated_prefs.cc
index dff08441a4e..708717077ca 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/generated_prefs.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/generated_prefs.cc
@@ -6,9 +6,12 @@
#include "base/callback.h"
#include "build/build_config.h"
+#include "chrome/browser/content_settings/generated_cookie_prefs.h"
#include "chrome/browser/extensions/api/settings_private/generated_pref.h"
#include "chrome/browser/extensions/api/settings_private/prefs_util_enums.h"
+#include "chrome/browser/safe_browsing/generated_safe_browsing_pref.h"
#include "chrome/common/extensions/api/settings_private.h"
+#include "components/content_settings/core/common/pref_names.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_method_short.h"
@@ -25,6 +28,14 @@ GeneratedPrefs::GeneratedPrefs(Profile* profile) {
prefs_[kResolveTimezoneByGeolocationMethodShort] =
CreateGeneratedResolveTimezoneByGeolocationMethodShort(profile);
#endif
+ prefs_[content_settings::kCookiePrimarySetting] =
+ std::make_unique<content_settings::GeneratedCookiePrimarySettingPref>(
+ profile);
+ prefs_[content_settings::kCookieSessionOnly] =
+ std::make_unique<content_settings::GeneratedCookieSessionOnlyPref>(
+ profile);
+ prefs_[safe_browsing::kGeneratedSafeBrowsingPref] =
+ std::make_unique<safe_browsing::GeneratedSafeBrowsingPref>(profile);
}
GeneratedPrefs::~GeneratedPrefs() = default;
diff --git a/chromium/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc b/chromium/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc
index 92dd63b50f5..b6838f04b5c 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc
@@ -51,7 +51,7 @@ void GeneratedTimeZonePrefBase::UpdateTimeZonePrefControlledBy(
} else {
out_pref->enforcement = settings_api::ENFORCEMENT_ENFORCED;
}
- } else if (!profile_->IsSameProfile(
+ } else if (!profile_->IsSameOrParent(
ProfileManager::GetPrimaryUserProfile())) {
out_pref->controlled_by = settings_api::CONTROLLED_BY_PRIMARY_USER;
out_pref->controlled_by_name = std::make_unique<std::string>(
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 ea48a66ba88..a6d8479abd9 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -9,9 +9,11 @@
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/content_settings/generated_cookie_prefs.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/settings_api_helpers.h"
+#include "chrome/browser/nearby_sharing/nearby_sharing_prefs.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
@@ -286,13 +288,29 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
#if defined(OS_CHROMEOS)
(*s_whitelist)[::prefs::kLanguageImeMenuActivated] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[chromeos::prefs::kAssistPersonalInfoEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[chromeos::prefs::kEmojiSuggestionEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::prefs::kLanguageInputMethodSpecificSettings] =
+ settings_api::PrefType::PREF_TYPE_DICTIONARY;
#endif
+ // Nearby Share.
+ (*s_whitelist)[::prefs::kNearbySharingEnabledPrefName] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::prefs::kNearbySharingActiveProfilePrefName] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+
// Search page.
(*s_whitelist)[DefaultSearchManager::kDefaultSearchProviderDataPrefName] =
settings_api::PrefType::PREF_TYPE_DICTIONARY;
// Site Settings prefs.
+ (*s_whitelist)[::content_settings::kCookiePrimarySetting] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
+ (*s_whitelist)[::content_settings::kCookieSessionOnly] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kBlockThirdPartyCookies] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kCookieControlsMode] =
@@ -355,6 +373,10 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
(*s_whitelist)[::prefs::kLiveCaptionEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
#endif
+#if !defined(OS_CHROMEOS)
+ (*s_whitelist)[::prefs::kAccessibilityFocusHighlightEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+#endif
#if defined(OS_CHROMEOS)
// Accounts / Users / People.
@@ -407,6 +429,10 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[ash::prefs::kAccessibilityLargeCursorDipSize] =
settings_api::PrefType::PREF_TYPE_NUMBER;
+ (*s_whitelist)[ash::prefs::kAccessibilityCursorColorEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[ash::prefs::kAccessibilityCursorColor] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[ash::prefs::kAccessibilityScreenMagnifierEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[ash::prefs::kAccessibilityScreenMagnifierScale] =
@@ -471,8 +497,6 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[plugin_vm::prefs::kPluginVmPrintersAllowed] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[plugin_vm::prefs::kPluginVmCameraSharing] =
- settings_api::PrefType::PREF_TYPE_BOOLEAN;
// Android Apps.
(*s_whitelist)[arc::prefs::kArcEnabled] =
@@ -511,12 +535,12 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[chromeos::kStatsReportingPref] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::chromeos::prefs::kSuggestedContentEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[chromeos::kAttestationForContentProtectionEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[prefs::kRestoreLastLockScreenNote] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kSettingsShowBrowserBanner] =
- settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kSettingsShowOSBanner] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
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 bca4048309d..47c59642146 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
@@ -11,11 +11,15 @@
#include "base/run_loop.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.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/extension_apitest.h"
#include "chrome/common/extensions/api/settings_private.h"
#include "chrome/common/pref_names.h"
+#include "components/content_settings/core/browser/host_content_settings_map.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/keyed_service/core/keyed_service.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
@@ -102,6 +106,25 @@ IN_PROC_BROWSER_TEST_F(SettingsPrivateApiTest, GetRecommendedPref) {
EXPECT_TRUE(RunSettingsSubtest("getRecommendedPref")) << message_;
}
+IN_PROC_BROWSER_TEST_F(SettingsPrivateApiTest, GetDisabledPref) {
+ HostContentSettingsMapFactory::GetForProfile(profile())
+ ->SetDefaultContentSetting(ContentSettingsType::COOKIES,
+ ContentSetting::CONTENT_SETTING_BLOCK);
+ EXPECT_TRUE(RunSettingsSubtest("getDisabledPref")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(SettingsPrivateApiTest, GetPartiallyManagedPref) {
+ auto provider = std::make_unique<content_settings::MockProvider>();
+ provider->SetWebsiteSetting(
+ ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
+ ContentSettingsType::COOKIES, std::string(),
+ std::make_unique<base::Value>(ContentSetting::CONTENT_SETTING_ALLOW));
+ content_settings::TestUtils::OverrideProvider(
+ HostContentSettingsMapFactory::GetForProfile(profile()),
+ std::move(provider), HostContentSettingsMap::POLICY_PROVIDER);
+ EXPECT_TRUE(RunSettingsSubtest("getPartiallyManagedPref")) << message_;
+}
+
IN_PROC_BROWSER_TEST_F(SettingsPrivateApiTest, GetAllPrefs) {
EXPECT_TRUE(RunSettingsSubtest("getAllPrefs")) << message_;
}
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 beb1efb4780..bd741debea0 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
@@ -15,7 +15,6 @@
#include "base/memory/weak_ptr.h"
#include "base/one_shot_event.h"
#include "base/scoped_observer.h"
-#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/storage/policy_value_store.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/schema_registry_service.h"
@@ -203,8 +202,8 @@ void ManagedValueStoreCache::ExtensionTracker::LoadSchemasOnFileTaskRunner(
(*components)[(*it)->id()] = schema;
}
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&ExtensionTracker::Register, self,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ExtensionTracker::Register, self,
base::Owned(components.release())));
}
diff --git a/chromium/chrome/browser/extensions/api/storage/policy_value_store.cc b/chromium/chrome/browser/extensions/api/storage/policy_value_store.cc
index 51b4e2fb2cb..264828c2308 100644
--- a/chromium/chrome/browser/extensions/api/storage/policy_value_store.cc
+++ b/chromium/chrome/browser/extensions/api/storage/policy_value_store.cc
@@ -43,7 +43,7 @@ void PolicyValueStore::SetCurrentPolicy(const policy::PolicyMap& policy) {
for (auto it = policy.begin(); it != policy.end(); ++it) {
if (it->second.level == policy::POLICY_LEVEL_MANDATORY) {
current_policy.SetWithoutPathExpansion(
- it->first, it->second.value->CreateDeepCopy());
+ it->first, it->second.value()->CreateDeepCopy());
}
}
diff --git a/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc b/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc
index 7ab45ab303f..6c17d73a9ed 100644
--- a/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc
@@ -339,9 +339,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
}
-// Disabled, see crbug.com/101110
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
- DISABLED_OnChangedNotificationsFromSync) {
+ OnChangedNotificationsFromSync) {
// We need 2 ResultCatchers because we'll be running the same test in both
// regular and incognito mode.
ResultCatcher catcher, catcher_incognito;
@@ -381,12 +380,10 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
}
-// Disabled, see crbug.com/101110
-//
// TODO: boring test, already done in the unit tests. What we really should be
// be testing is that the areas don't overlap.
IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
- DISABLED_OnChangedNotificationsFromSyncNotSentToLocal) {
+ OnChangedNotificationsFromSyncNotSentToLocal) {
// We need 2 ResultCatchers because we'll be running the same test in both
// regular and incognito mode.
ResultCatcher catcher, catcher_incognito;
@@ -517,6 +514,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ManagedStorage) {
extensions::DictionaryBuilder()
.Set("string-policy", "value")
.Set("string-enum-policy", "value-1")
+ .Set("another-string-policy", 123) // Test invalid policy value.
.Set("int-policy", -123)
.Set("int-enum-policy", 1)
.Set("double-policy", 456e7)
@@ -544,8 +542,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ManagedStorage) {
ASSERT_TRUE(RunExtensionTest("settings/managed_storage")) << message_;
}
-IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
- DISABLED_PRE_ManagedStorageEvents) {
+IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, PRE_ManagedStorageEvents) {
ResultCatcher catcher;
// This test starts without any test extensions installed.
@@ -579,8 +576,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
-IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
- DISABLED_ManagedStorageEvents) {
+IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ManagedStorageEvents) {
// This test runs after PRE_ManagedStorageEvents without having deleted the
// profile, so the extension is still around. While the browser restarted the
// policy went back to the empty default, and so the extension should receive
diff --git a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_api.cc b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_api.cc
index 576c14641c4..4947eede0b4 100644
--- a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_api.cc
+++ b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_api.cc
@@ -39,8 +39,10 @@ ExtensionFunction::ResponseAction SystemIndicatorSetIconFunction::Run() {
if (const base::Value* canvas_set = set_icon_details.FindKeyOfType(
"imageData", base::Value::Type::DICTIONARY)) {
gfx::ImageSkia icon;
- EXTENSION_FUNCTION_VALIDATE(ExtensionAction::ParseIconFromCanvasDictionary(
- static_cast<const base::DictionaryValue&>(*canvas_set), &icon));
+ EXTENSION_FUNCTION_VALIDATE(
+ ExtensionAction::ParseIconFromCanvasDictionary(
+ static_cast<const base::DictionaryValue&>(*canvas_set), &icon) ==
+ ExtensionAction::IconParseResult::kSuccess);
if (icon.isNull())
return RespondNow(Error("Icon invalid."));
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
index f4d183ab977..38c40a7e868 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -919,7 +919,7 @@ ExtensionFunction::ResponseAction TabsQueryFunction::Run() {
Browser* current_browser =
ChromeExtensionFunctionDetails(this).GetCurrentBrowser();
for (auto* browser : *BrowserList::GetInstance()) {
- if (!profile->IsSameProfile(browser->profile()))
+ if (!profile->IsSameOrParent(browser->profile()))
continue;
if (!browser->window())
@@ -1211,8 +1211,7 @@ bool TabsHighlightFunction::HighlightTab(TabStripModel* tabstrip,
return true;
}
-TabsUpdateFunction::TabsUpdateFunction() : web_contents_(NULL) {
-}
+TabsUpdateFunction::TabsUpdateFunction() : web_contents_(nullptr) {}
ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
std::unique_ptr<tabs::Update::Params> params(
@@ -1580,20 +1579,10 @@ ExtensionFunction::ResponseAction TabsReloadFunction::Run() {
}
}
- if (web_contents->ShowingInterstitialPage()) {
- // This does as same as Browser::ReloadInternal.
- NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
- GURL reload_url = entry ? entry->GetURL() : GURL(url::kAboutBlankURL);
- OpenURLParams params(reload_url, Referrer(),
- WindowOpenDisposition::CURRENT_TAB,
- ui::PAGE_TRANSITION_RELOAD, false);
- current_browser->OpenURL(params);
- } else {
- web_contents->GetController().Reload(
- bypass_cache ? content::ReloadType::BYPASSING_CACHE
- : content::ReloadType::NORMAL,
- true);
- }
+ web_contents->GetController().Reload(
+ bypass_cache ? content::ReloadType::BYPASSING_CACHE
+ : content::ReloadType::NORMAL,
+ true);
return RespondNow(NoArguments());
}
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 fd2ff75a3af..517e299ae20 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
@@ -177,7 +177,7 @@ TabsEventRouter::~TabsEventRouter() {
}
bool TabsEventRouter::ShouldTrackBrowser(Browser* browser) {
- return profile_->IsSameProfile(browser->profile()) &&
+ return profile_->IsSameOrParent(browser->profile()) &&
ExtensionTabUtil::BrowserSupportsTabs(browser);
}
@@ -571,7 +571,7 @@ void TabsEventRouter::DispatchEvent(
std::unique_ptr<base::ListValue> args,
EventRouter::UserGestureState user_gesture) {
EventRouter* event_router = EventRouter::Get(profile);
- if (!profile_->IsSameProfile(profile) || !event_router)
+ if (!profile_->IsSameOrParent(profile) || !event_router)
return;
auto event = std::make_unique<Event>(histogram_value, event_name,
diff --git a/chromium/chrome/browser/extensions/api/tabs/windows_event_router.cc b/chromium/chrome/browser/extensions/api/tabs/windows_event_router.cc
index 5f41fa24c34..05b785e9ac0 100644
--- a/chromium/chrome/browser/extensions/api/tabs/windows_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/windows_event_router.cc
@@ -180,14 +180,14 @@ WindowsEventRouter::~WindowsEventRouter() {
}
void WindowsEventRouter::OnAppWindowAdded(extensions::AppWindow* app_window) {
- if (!profile_->IsSameProfile(
+ if (!profile_->IsSameOrParent(
Profile::FromBrowserContext(app_window->browser_context())))
return;
AddAppWindow(app_window);
}
void WindowsEventRouter::OnAppWindowRemoved(extensions::AppWindow* app_window) {
- if (!profile_->IsSameProfile(
+ if (!profile_->IsSameOrParent(
Profile::FromBrowserContext(app_window->browser_context())))
return;
@@ -206,7 +206,7 @@ void WindowsEventRouter::OnWindowControllerAdded(
WindowController* window_controller) {
if (!HasEventListener(windows::OnCreated::kEventName))
return;
- if (!profile_->IsSameProfile(window_controller->profile()))
+ if (!profile_->IsSameOrParent(window_controller->profile()))
return;
// Ignore any windows without an associated browser (e.g., AppWindows).
if (!window_controller->GetBrowser())
@@ -228,7 +228,7 @@ void WindowsEventRouter::OnWindowControllerRemoved(
WindowController* window_controller) {
if (!HasEventListener(windows::OnRemoved::kEventName))
return;
- if (!profile_->IsSameProfile(window_controller->profile()))
+ if (!profile_->IsSameOrParent(window_controller->profile()))
return;
// Ignore any windows without an associated browser (e.g., AppWindows).
if (!window_controller->GetBrowser())
@@ -263,7 +263,7 @@ void WindowsEventRouter::OnActiveWindowChanged(
Profile* window_profile = nullptr;
int window_id = extension_misc::kUnknownWindowId;
if (window_controller &&
- profile_->IsSameProfile(window_controller->profile())) {
+ profile_->IsSameOrParent(window_controller->profile())) {
window_profile = window_controller->profile();
window_id = window_controller->GetWindowId();
}
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 e7d31651cd9..46b9d08c181 100644
--- a/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
+++ b/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
@@ -12,7 +12,6 @@
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
-#include "base/task/post_task.h"
#include "base/time/time.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/dbus/util/version_loader.h"
@@ -79,8 +78,8 @@ void CrostiniStartupStatus::ShowProgressAtInterval() {
PrintProgress();
}
++spinner_index_;
- base::PostDelayedTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostDelayedTask(
+ FROM_HERE,
base::BindOnce(&CrostiniStartupStatus::ShowProgressAtInterval,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(300));
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 f17fccee02c..e2d7220cd38 100644
--- a/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -17,7 +17,6 @@
#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"
@@ -93,8 +92,8 @@ void NotifyProcessOutput(content::BrowserContext* browser_context,
const std::string& output_type,
const std::string& output) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&NotifyProcessOutput, browser_context, tab_id,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&NotifyProcessOutput, browser_context, tab_id,
terminal_id, output_type, output));
return;
}
@@ -249,12 +248,10 @@ TerminalPrivateOpenTerminalProcessFunction::OpenProcess(
GetSwitch(&params_args, &vmshell_cmd, kSwitchTargetContainer,
crostini::kCrostiniDefaultContainerName);
std::string startup_id = params_args.GetSwitchValueASCII(kSwitchStartupId);
+ crostini::ContainerId container_id(vm_name, container_name);
auto* mgr = crostini::CrostiniManager::GetForProfile(profile);
- bool verbose =
- !mgr->GetContainerInfo(crostini::kCrostiniDefaultVmName,
- crostini::kCrostiniDefaultContainerName)
- .has_value();
+ bool verbose = !mgr->GetContainerInfo(container_id).has_value();
auto observer = std::make_unique<CrostiniStartupStatus>(
base::BindRepeating(&NotifyProcessOutput, browser_context(), tab_id,
startup_id,
@@ -265,7 +262,7 @@ TerminalPrivateOpenTerminalProcessFunction::OpenProcess(
CrostiniStartupStatus* observer_ptr = observer.get();
observer->ShowProgressAtInterval();
mgr->RestartCrostini(
- vm_name, container_name,
+ container_id,
base::BindOnce(
&TerminalPrivateOpenTerminalProcessFunction::OnCrostiniRestarted,
this, std::move(observer), user_id_hash, tab_id,
@@ -331,8 +328,8 @@ void TerminalPrivateOpenTerminalProcessFunction::OpenOnRegistryTaskRunner(
bool success = registry->OpenProcess(cmdline, user_id_hash, output_callback,
&terminal_id);
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(callback, success, terminal_id));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(callback, success, terminal_id));
}
TerminalPrivateOpenVmshellProcessFunction::
@@ -379,8 +376,8 @@ void TerminalPrivateSendInputFunction::SendInputOnRegistryTaskRunner(
bool success =
chromeos::ProcessProxyRegistry::Get()->SendInput(terminal_id, text);
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&TerminalPrivateSendInputFunction::RespondOnUIThread, this,
success));
}
@@ -412,8 +409,8 @@ void TerminalPrivateCloseTerminalProcessFunction::CloseOnRegistryTaskRunner(
bool success =
chromeos::ProcessProxyRegistry::Get()->CloseProcess(terminal_id);
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&TerminalPrivateCloseTerminalProcessFunction::RespondOnUIThread, this,
success));
@@ -450,8 +447,8 @@ void TerminalPrivateOnTerminalResizeFunction::OnResizeOnRegistryTaskRunner(
bool success = chromeos::ProcessProxyRegistry::Get()->OnTerminalResize(
terminal_id, width, height);
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&TerminalPrivateOnTerminalResizeFunction::RespondOnUIThread, this,
success));
@@ -537,8 +534,8 @@ void TerminalPrivateGetCroshSettingsFunction::AsyncRunWithStorage(
ExtensionFunction::ResponseValue response =
result.status().ok() ? OneArgument(result.PassSettings())
: Error(result.status().message);
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&TerminalPrivateGetCroshSettingsFunction::Respond, this,
std::move(response)));
}
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 906e695f21f..dccb0b244d9 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
@@ -34,8 +34,8 @@
#include "media/audio/audio_system.h"
#include "ui/aura/event_injector.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/base/ime/chromeos/ime_bridge.h"
#include "ui/base/ime/constants.h"
-#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ui_base_features.h"
@@ -409,10 +409,9 @@ void ChromeVirtualKeyboardDelegate::OnHasInputDevices(
features->AppendString(GenerateFeatureFlag(
"mozcinputlogic",
base::FeatureList::IsEnabled(chromeos::features::kImeInputLogicMozc)));
- // Flag used to enable decoder Mojo APIs instead of NaCl APIs.
+ // Flag used to enable UIL Mojo APIs instead of NaCl APIs.
features->AppendString(GenerateFeatureFlag(
- "usemojodecoder", base::FeatureList::IsEnabled(
- chromeos::features::kImeDecoderWithSandbox)));
+ "usemojodecoder", chromeos::features::IsImeSandboxEnabled()));
features->AppendString(GenerateFeatureFlag(
"borderedkey", base::FeatureList::IsEnabled(
chromeos::features::kVirtualKeyboardBorderedKey)));
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 edd6f2da449..34bc26bb443 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
@@ -80,7 +80,7 @@ WebNavigationEventRouter::WebNavigationEventRouter(Profile* profile)
WebNavigationEventRouter::~WebNavigationEventRouter() = default;
bool WebNavigationEventRouter::ShouldTrackBrowser(Browser* browser) {
- return profile_->IsSameProfile(browser->profile());
+ return profile_->IsSameOrParent(browser->profile());
}
void WebNavigationEventRouter::OnTabStripModelChanged(
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index c0ad861dd45..2d5c8d6d994 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -46,6 +46,7 @@
#include "extensions/browser/api/web_request/web_request_api_constants.h"
#include "extensions/browser/api/web_request/web_request_api_helpers.h"
#include "extensions/browser/api/web_request/web_request_info.h"
+#include "extensions/common/api/declarative_net_request.h"
#include "extensions/common/api/web_request.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_messages.h"
@@ -746,6 +747,8 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses4) {
EXPECT_EQ(GURL(), effective_new_url);
}
+// TODO(crbug.com/1099066): Separate this test into subtests to improve
+// readability.
TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
net::HttpRequestHeaders base_headers;
base_headers.SetHeader("key1", "value 1");
@@ -766,9 +769,10 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
WebRequestInfoInitParams info_params;
WebRequestInfo info(std::move(info_params));
info.dnr_actions = std::vector<DNRRequestAction>();
- MergeOnBeforeSendHeadersResponses(info, deltas, &headers0, &ignored_actions,
- &ignore1, &ignore2,
- &request_headers_modified0);
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers0, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified0, &matched_dnr_actions);
ASSERT_TRUE(headers0.GetHeader("key1", &header_value));
EXPECT_EQ("value 1", header_value);
ASSERT_TRUE(headers0.GetHeader("key2", &header_value));
@@ -791,9 +795,9 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
bool request_headers_modified1;
net::HttpRequestHeaders headers1;
headers1.MergeFrom(base_headers);
- MergeOnBeforeSendHeadersResponses(info, deltas, &headers1, &ignored_actions,
- &ignore1, &ignore2,
- &request_headers_modified1);
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers1, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified1, &matched_dnr_actions);
EXPECT_FALSE(headers1.HasHeader("key1"));
ASSERT_TRUE(headers1.GetHeader("key2", &header_value));
EXPECT_EQ("value 3", header_value);
@@ -818,9 +822,9 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
bool request_headers_modified2;
net::HttpRequestHeaders headers2;
headers2.MergeFrom(base_headers);
- MergeOnBeforeSendHeadersResponses(info, deltas, &headers2, &ignored_actions,
- &ignore1, &ignore2,
- &request_headers_modified2);
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers2, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified2, &matched_dnr_actions);
EXPECT_FALSE(headers2.HasHeader("key1"));
ASSERT_TRUE(headers2.GetHeader("key2", &header_value));
EXPECT_EQ("value 3", header_value);
@@ -849,9 +853,9 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
bool request_headers_modified3;
net::HttpRequestHeaders headers3;
headers3.MergeFrom(base_headers);
- MergeOnBeforeSendHeadersResponses(info, deltas, &headers3, &ignored_actions,
- &ignore1, &ignore2,
- &request_headers_modified3);
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers3, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified3, &matched_dnr_actions);
EXPECT_FALSE(headers3.HasHeader("key1"));
ASSERT_TRUE(headers3.GetHeader("key2", &header_value));
EXPECT_EQ("value 3", header_value);
@@ -864,6 +868,157 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
HasIgnoredAction(ignored_actions, "extid2",
web_request::IGNORED_ACTION_TYPE_REQUEST_HEADERS));
EXPECT_TRUE(request_headers_modified3);
+
+ // Check that headers removed by Declarative Net Request API can't be modified
+ // and result in a conflict.
+ ignored_actions.clear();
+ ignore1.clear();
+ ignore2.clear();
+ bool request_headers_modified4 = false;
+ net::HttpRequestHeaders headers4;
+ headers4.MergeFrom(base_headers);
+
+ DNRRequestAction modify_headers_action =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ modify_headers_action.request_headers_to_modify = {
+ DNRRequestAction::HeaderInfo(
+ "key5", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt)};
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ info.dnr_actions->push_back(std::move(modify_headers_action));
+
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers4, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified4, &matched_dnr_actions);
+ // Deleted by |d1|.
+ EXPECT_FALSE(headers4.HasHeader("key1"));
+ // Added by |d1|.
+ ASSERT_TRUE(headers4.GetHeader("key2", &header_value));
+ EXPECT_EQ("value 3", header_value);
+ // Removed by Declarative Net Request API.
+ EXPECT_FALSE(headers4.HasHeader("key5"));
+
+ EXPECT_EQ(2u, ignored_actions.size());
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_REQUEST_HEADERS));
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid3",
+ web_request::IGNORED_ACTION_TYPE_REQUEST_HEADERS));
+ EXPECT_TRUE(request_headers_modified4);
+
+ // Check that headers set by Declarative Net Request API can't be further
+ // modified and result in a conflict.
+ ignored_actions.clear();
+ ignore1.clear();
+ ignore2.clear();
+ bool request_headers_modified5 = false;
+ net::HttpRequestHeaders headers5;
+ headers5.MergeFrom(base_headers);
+
+ DNRRequestAction set_headers_action =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+
+ // Since key2 is set to "value 3" by both |set_headers_action| and
+ // |extid1|, |extid1| should not be ignored.
+ // Conversely, |set_headers_action| and |extid3| set different values for
+ // key5, therefore |extid4| should be ignored.
+ set_headers_action.request_headers_to_modify = {
+ DNRRequestAction::HeaderInfo(
+ "key2", api::declarative_net_request::HEADER_OPERATION_SET,
+ "value 3"),
+ DNRRequestAction::HeaderInfo(
+ "key5", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_value")};
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ info.dnr_actions->push_back(std::move(set_headers_action));
+
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers5, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified5, &matched_dnr_actions);
+ // Deleted by |d1|.
+ EXPECT_FALSE(headers5.HasHeader("key1"));
+ // Added by |d1| (same value as added by Declarative Net Request API).
+ ASSERT_TRUE(headers5.GetHeader("key2", &header_value));
+ EXPECT_EQ("value 3", header_value);
+ // Set by Declarative Net Request API.
+ ASSERT_TRUE(headers5.GetHeader("key5", &header_value));
+ EXPECT_EQ("dnr_value", header_value);
+
+ EXPECT_EQ(2u, ignored_actions.size());
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_REQUEST_HEADERS));
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid3",
+ web_request::IGNORED_ACTION_TYPE_REQUEST_HEADERS));
+ EXPECT_TRUE(request_headers_modified4);
+}
+
+// Test conflict resolution for declarative net request actions from the same
+// extension modifying the same request header.
+TEST(ExtensionWebRequestHelpersTest,
+ TestMergeOnBeforeSendHeadersResponses_DeclarativeNetRequest) {
+ DNRRequestAction action_1 =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ action_1.request_headers_to_modify = {
+ DNRRequestAction::HeaderInfo(
+ "key1", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_1"),
+ DNRRequestAction::HeaderInfo(
+ "key2", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_1"),
+ DNRRequestAction::HeaderInfo(
+ "key3", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt)};
+
+ DNRRequestAction action_2 =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ action_2.request_headers_to_modify = {
+ DNRRequestAction::HeaderInfo(
+ "key1", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ DNRRequestAction::HeaderInfo(
+ "key2", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_2"),
+ DNRRequestAction::HeaderInfo(
+ "key3", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_2")};
+
+ WebRequestInfoInitParams info_params;
+ WebRequestInfo info(std::move(info_params));
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ info.dnr_actions->push_back(std::move(action_1));
+ info.dnr_actions->push_back(std::move(action_2));
+
+ net::HttpRequestHeaders base_headers;
+ base_headers.SetHeader("key3", "value 3");
+ helpers::IgnoredActions ignored_actions;
+ std::string header_value;
+ EventResponseDeltas deltas;
+ bool request_headers_modified;
+ std::set<std::string> ignore1, ignore2;
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
+
+ // Header modifications specified by |action1| are processed before those
+ // specified by |action2|.
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &base_headers, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified, &matched_dnr_actions);
+ // Header set by a prior action cannot be removed by a subsequent action.
+ ASSERT_TRUE(base_headers.GetHeader("key1", &header_value));
+ EXPECT_EQ("dnr_action_1", header_value);
+
+ // Header set by a prior action cannot be set to a different value by a
+ // subsequent action.
+ ASSERT_TRUE(base_headers.GetHeader("key2", &header_value));
+ EXPECT_EQ("dnr_action_1", header_value);
+
+ // Header removed by a prior action cannot be set by a subsequent action.
+ EXPECT_FALSE(base_headers.HasHeader("key3"));
+
+ EXPECT_EQ(0u, ignored_actions.size());
+ EXPECT_TRUE(request_headers_modified);
}
// Ensure conflicts between different extensions are handled correctly with
@@ -897,9 +1052,10 @@ TEST(ExtensionWebRequestHelpersTest,
net::HttpRequestHeaders headers;
headers.SetHeader("key1", "value 1");
- MergeOnBeforeSendHeadersResponses(info, deltas, &headers, &ignored_actions,
- &removed_headers, &set_headers,
- &request_headers_modified);
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers, &ignored_actions, &removed_headers, &set_headers,
+ &request_headers_modified, &matched_dnr_actions);
std::string header_value;
ASSERT_TRUE(headers.GetHeader("key1", &header_value));
@@ -962,9 +1118,11 @@ TEST(ExtensionWebRequestHelpersTest,
WebRequestInfoInitParams info_params;
WebRequestInfo info(std::move(info_params));
- MergeOnBeforeSendHeadersResponses(info, deltas, &headers1, &ignored_actions,
- &ignore1, &ignore2,
- &request_headers_modified1);
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
+ MergeOnBeforeSendHeadersResponses(
+ info, deltas, &headers1, &ignored_actions, &ignore1, &ignore2,
+ &request_headers_modified1, &matched_dnr_actions);
EXPECT_TRUE(headers1.HasHeader("Cookie"));
ASSERT_TRUE(headers1.GetHeader("Cookie", &header_value));
EXPECT_EQ("name=new value; name2=new value; name4=\"value 4\"", header_value);
@@ -1217,6 +1375,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
"HTTP/1.0 200 OK\r\n"
"Key1: Value1\r\n"
"Key2: Value2, Foo\r\n"
+ "Key4: Value4\r\n"
"\r\n";
auto base_headers = base::MakeRefCounted<net::HttpResponseHeaders>(
net::HttpUtil::AssembleRawHeaders(base_headers_string));
@@ -1233,11 +1392,12 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
info_params.url = GURL(kExampleUrl);
WebRequestInfo info(std::move(info_params));
info.dnr_actions = std::vector<DNRRequestAction>();
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
MergeOnHeadersReceivedResponses(
info, deltas, base_headers.get(), &new_headers0,
&preserve_fragment_on_redirect_url0, &ignored_actions,
- &response_headers_modified0);
+ &response_headers_modified0, &matched_dnr_actions);
EXPECT_FALSE(new_headers0.get());
EXPECT_TRUE(preserve_fragment_on_redirect_url0.is_empty());
EXPECT_EQ(0u, ignored_actions.size());
@@ -1260,12 +1420,13 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
MergeOnHeadersReceivedResponses(
info, deltas, base_headers.get(), &new_headers1,
&preserve_fragment_on_redirect_url1, &ignored_actions,
- &response_headers_modified1);
+ &response_headers_modified1, &matched_dnr_actions);
ASSERT_TRUE(new_headers1.get());
EXPECT_TRUE(preserve_fragment_on_redirect_url1.is_empty());
std::multimap<std::string, std::string> expected1;
- expected1.insert(std::pair<std::string, std::string>("Key2", "Value3"));
- expected1.insert(std::pair<std::string, std::string>("Key3", "Foo"));
+ expected1.emplace("Key2", "Value3");
+ expected1.emplace("Key3", "Foo");
+ expected1.emplace("Key4", "Value4");
size_t iter = 0;
std::string name;
std::string value;
@@ -1295,7 +1456,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
MergeOnHeadersReceivedResponses(
info, deltas, base_headers.get(), &new_headers2,
&preserve_fragment_on_redirect_url2, &ignored_actions,
- &response_headers_modified2);
+ &response_headers_modified2, &matched_dnr_actions);
ASSERT_TRUE(new_headers2.get());
EXPECT_TRUE(preserve_fragment_on_redirect_url2.is_empty());
iter = 0;
@@ -1309,6 +1470,108 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
HasIgnoredAction(ignored_actions, "extid2",
web_request::IGNORED_ACTION_TYPE_RESPONSE_HEADERS));
EXPECT_TRUE(response_headers_modified2);
+
+ // Ensure headers removed by Declarative Net Request API can't be added by web
+ // request extensions and result in a conflict.
+ DNRRequestAction modify_headers_action =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ modify_headers_action.response_headers_to_modify = {
+ DNRRequestAction::HeaderInfo(
+ "key3", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt)};
+
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ info.dnr_actions->push_back(std::move(modify_headers_action));
+
+ ignored_actions.clear();
+ bool response_headers_modified3 = false;
+ scoped_refptr<net::HttpResponseHeaders> new_headers3;
+ GURL preserve_fragment_on_redirect_url3;
+ MergeOnHeadersReceivedResponses(
+ info, deltas, base_headers.get(), &new_headers3,
+ &preserve_fragment_on_redirect_url3, &ignored_actions,
+ &response_headers_modified3, &matched_dnr_actions);
+ ASSERT_TRUE(new_headers3.get());
+ EXPECT_TRUE(preserve_fragment_on_redirect_url3.is_empty());
+ iter = 0;
+ std::multimap<std::string, std::string> actual3;
+ while (new_headers3->EnumerateHeaderLines(&iter, &name, &value))
+ actual3.emplace(name, value);
+ std::multimap<std::string, std::string> expected3;
+ expected3.emplace("Key2", "Value4");
+ expected3.emplace("Key1", "Value1");
+ expected3.emplace("Key4", "Value4");
+ EXPECT_EQ(expected3, actual3);
+ EXPECT_EQ(1u, ignored_actions.size());
+
+ // The action specified by extid1 is ignored since it conflicted with
+ // |modify_headers_action| for the key3 header.
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid1",
+ web_request::IGNORED_ACTION_TYPE_RESPONSE_HEADERS));
+ EXPECT_TRUE(response_headers_modified3);
+
+ // Ensure headers appended by Declarative Net Request API can't be removed by
+ // web request extensions and result in a conflict, but can be further
+ // appended by web request extensions.
+ {
+ EventResponseDelta d3("extid3", base::Time::FromInternalValue(1000));
+ d3.deleted_response_headers.push_back(ResponseHeader("Key4", "Value4"));
+ deltas.push_back(std::move(d3));
+ }
+ deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
+
+ modify_headers_action =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ modify_headers_action.response_headers_to_modify = {
+ DNRRequestAction::HeaderInfo(
+ "key3", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_value_3"),
+ DNRRequestAction::HeaderInfo(
+ "key4", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_value_4")};
+
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ info.dnr_actions->push_back(std::move(modify_headers_action));
+
+ ignored_actions.clear();
+ bool response_headers_modified4 = false;
+ scoped_refptr<net::HttpResponseHeaders> new_headers4;
+ GURL preserve_fragment_on_redirect_url4;
+ MergeOnHeadersReceivedResponses(
+ info, deltas, base_headers.get(), &new_headers4,
+ &preserve_fragment_on_redirect_url4, &ignored_actions,
+ &response_headers_modified4, &matched_dnr_actions);
+ ASSERT_TRUE(new_headers4.get());
+ EXPECT_TRUE(preserve_fragment_on_redirect_url4.is_empty());
+
+ iter = 0;
+ std::multimap<std::string, std::string> actual4;
+ while (new_headers4->EnumerateHeaderLines(&iter, &name, &value))
+ actual4.emplace(name, value);
+ std::multimap<std::string, std::string> expected4;
+
+ expected4.emplace("Key2", "Value3");
+ expected4.emplace("Key3", "Foo");
+ expected4.emplace("key3", "dnr_value_3");
+ expected4.emplace("Key4", "Value4");
+ expected4.emplace("key4", "dnr_value_4");
+ EXPECT_EQ(expected4, actual4);
+ EXPECT_EQ(2u, ignored_actions.size());
+
+ // The action specified by extid1 is not ignored since it adds to the same
+ // header that the Declarative Net Request appends. The action specified by
+ // extid2 is ignored since it tries to replace the same header replaced by
+ // extid1.
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_RESPONSE_HEADERS));
+ // The action specified by extid3 is ignored since it tries to remove Key4,
+ // which was appended by the Declarative Net Request API.
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid3",
+ web_request::IGNORED_ACTION_TYPE_RESPONSE_HEADERS));
+ EXPECT_TRUE(response_headers_modified4);
}
// Check that we do not delete too much
@@ -1341,11 +1604,12 @@ TEST(ExtensionWebRequestHelpersTest,
info_params.url = GURL(kExampleUrl);
WebRequestInfo info(std::move(info_params));
info.dnr_actions = std::vector<DNRRequestAction>();
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
MergeOnHeadersReceivedResponses(
info, deltas, base_headers.get(), &new_headers1,
&preserve_fragment_on_redirect_url1, &ignored_actions,
- &response_headers_modified1);
+ &response_headers_modified1, &matched_dnr_actions);
ASSERT_TRUE(new_headers1.get());
EXPECT_TRUE(preserve_fragment_on_redirect_url1.is_empty());
std::multimap<std::string, std::string> expected1;
@@ -1390,11 +1654,13 @@ TEST(ExtensionWebRequestHelpersTest,
WebRequestInfoInitParams info_params;
info_params.url = GURL(kExampleUrl);
WebRequestInfo info(std::move(info_params));
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
MergeOnHeadersReceivedResponses(
info, deltas, base_headers.get(), &new_headers0,
&preserve_fragment_on_redirect_url0, &ignored_actions,
- &response_headers_modified0);
+ &response_headers_modified0, &matched_dnr_actions);
EXPECT_FALSE(new_headers0.get());
EXPECT_TRUE(preserve_fragment_on_redirect_url0.is_empty());
EXPECT_EQ(0u, ignored_actions.size());
@@ -1415,7 +1681,7 @@ TEST(ExtensionWebRequestHelpersTest,
MergeOnHeadersReceivedResponses(
info, deltas, base_headers.get(), &new_headers1,
&preserve_fragment_on_redirect_url1, &ignored_actions,
- &response_headers_modified1);
+ &response_headers_modified1, &matched_dnr_actions);
EXPECT_TRUE(new_headers1.get());
EXPECT_TRUE(new_headers1->HasHeaderValue("Location", new_url_1.spec()));
@@ -1424,6 +1690,143 @@ TEST(ExtensionWebRequestHelpersTest,
EXPECT_FALSE(response_headers_modified1);
}
+// Test conflict resolution for declarative net request actions modifying the
+// same response header.
+TEST(ExtensionWebRequestHelpersTest,
+ TestMergeOnHeadersReceivedResponses_DeclarativeNetRequest) {
+ using HeaderInfo = DNRRequestAction::HeaderInfo;
+ const ExtensionId ext_1 = "ext_1";
+ const ExtensionId ext_2 = "ext_2";
+
+ // Test every combination of operations for two RequestActions from different
+ // extensions modifying the same header.
+ DNRRequestAction action_1 =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ action_1.extension_id = ext_1;
+ action_1.response_headers_to_modify = {
+ HeaderInfo("key1", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_action_1"),
+ HeaderInfo("key2", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_action_1"),
+ HeaderInfo("key3", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_action_1"),
+
+ HeaderInfo("key4", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_1"),
+ HeaderInfo("key5", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_1"),
+ HeaderInfo("key6", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_1"),
+
+ HeaderInfo("key7", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ HeaderInfo("key8", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+
+ HeaderInfo("same_ext_key",
+ api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_1")};
+
+ DNRRequestAction action_2 =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ action_2.extension_id = ext_1;
+ action_2.response_headers_to_modify = {HeaderInfo(
+ "same_ext_key", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_action_2")};
+
+ DNRRequestAction action_3 =
+ CreateRequestActionForTesting(DNRRequestAction::Type::MODIFY_HEADERS);
+ action_3.extension_id = ext_2;
+ action_3.response_headers_to_modify = {
+ HeaderInfo("key1", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_action_3"),
+ HeaderInfo("key2", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_3"),
+ HeaderInfo("key3", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+
+ HeaderInfo("key4", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_action_3"),
+ HeaderInfo("key5", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_3"),
+ HeaderInfo("key6", api::declarative_net_request::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+
+ HeaderInfo("key7", api::declarative_net_request::HEADER_OPERATION_APPEND,
+ "dnr_action_3"),
+ HeaderInfo("key8", api::declarative_net_request::HEADER_OPERATION_SET,
+ "dnr_action_3")};
+
+ WebRequestInfoInitParams info_params;
+ info_params.url = GURL(kExampleUrl);
+ WebRequestInfo info(std::move(info_params));
+
+ info.dnr_actions = std::vector<DNRRequestAction>();
+ info.dnr_actions->push_back(std::move(action_1));
+ info.dnr_actions->push_back(std::move(action_2));
+ info.dnr_actions->push_back(std::move(action_3));
+
+ helpers::IgnoredActions ignored_actions;
+ std::string header_value;
+ EventResponseDeltas deltas;
+
+ char base_headers_string[] =
+ "HTTP/1.0 200 OK\r\n"
+ "key1: Value1\r\n"
+ "key4: Value4\r\n"
+ "key7: Value7\r\n"
+ "key8: Value8\r\n"
+ "\r\n";
+ auto base_headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+ net::HttpUtil::AssembleRawHeaders(base_headers_string));
+
+ bool response_headers_modified;
+ scoped_refptr<net::HttpResponseHeaders> new_headers;
+ GURL preserve_fragment_on_redirect_url;
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
+
+ MergeOnHeadersReceivedResponses(
+ info, deltas, base_headers.get(), &new_headers,
+ &preserve_fragment_on_redirect_url, &ignored_actions,
+ &response_headers_modified, &matched_dnr_actions);
+ EXPECT_TRUE(new_headers.get());
+ EXPECT_TRUE(response_headers_modified);
+
+ size_t iter = 0;
+ std::string name;
+ std::string value;
+ std::multimap<std::string, std::string> actual_headers;
+ while (new_headers->EnumerateHeaderLines(&iter, &name, &value))
+ actual_headers.emplace(name, value);
+
+ std::multimap<std::string, std::string> expected_headers;
+ // An append operation should allow subsequent appends, but not any other
+ // operations.
+ expected_headers.emplace("key1", "Value1");
+ expected_headers.emplace("key1", "dnr_action_1");
+ expected_headers.emplace("key1", "dnr_action_3");
+ expected_headers.emplace("key2", "dnr_action_1");
+ expected_headers.emplace("key3", "dnr_action_1");
+
+ // A set operation should not allow any subsequent operations from a different
+ // extension.
+ expected_headers.emplace("key4", "dnr_action_1");
+ expected_headers.emplace("key5", "dnr_action_1");
+ expected_headers.emplace("key6", "dnr_action_1");
+
+ // A remove operation should not allow any subsequent operations
+ // (key7 and key8 headers were removed by |action_1|).
+
+ // A {set, append} sequence is allowed if both operations are specified by the
+ // same extension.
+ expected_headers.emplace("same_ext_key", "dnr_action_1");
+ expected_headers.emplace("same_ext_key", "dnr_action_2");
+ EXPECT_EQ(expected_headers, actual_headers);
+
+ EXPECT_TRUE(preserve_fragment_on_redirect_url.is_empty());
+ EXPECT_EQ(0u, ignored_actions.size());
+}
+
TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
helpers::IgnoredActions ignored_actions;
EventResponseDeltas deltas;
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 1a8cccf02eb..a39706af881 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
@@ -58,6 +58,7 @@
#include "chrome/test/base/search_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/login/login_state/scoped_test_public_session_login_state.h"
+#include "components/embedder_support/switches.h"
#include "components/google/core/common/google_switches.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
@@ -131,6 +132,11 @@ namespace extensions {
namespace {
+// This is the public key of tools/origin_trials/eftest.key, used to validate
+// origin trial tokens generated by tools/origin_trials/generate_token.py.
+constexpr char kOriginTrialPublicKeyForTesting[] =
+ "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA=";
+
class CancelLoginDialog : public content::NotificationObserver {
public:
CancelLoginDialog() {
@@ -299,6 +305,8 @@ class ExtensionWebRequestApiTest : public ExtensionApiTest {
void SetUpCommandLine(base::CommandLine* command_line) override {
ExtensionApiTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(switches::kGaiaUrl, "http://gaia.com");
+ command_line->AppendSwitchASCII(embedder_support::kOriginTrialPublicKey,
+ kOriginTrialPublicKeyForTesting);
}
void RunPermissionTest(
@@ -2155,14 +2163,13 @@ IN_PROC_BROWSER_TEST_F(LocalNTPInterceptionWebRequestAPITest,
return result == "true";
};
- WebContents* web_contents =
- browser()->tab_strip_model()->GetActiveWebContents();
-
ASSERT_FALSE(GetAndResetOneGoogleBarRequestSeen());
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
- ASSERT_TRUE(search::IsInstantNTP(web_contents));
- ASSERT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
- web_contents->GetController().GetVisibleEntry()->GetURL());
+ ASSERT_EQ(local_ntp_test_utils::GetFinalNtpUrl(browser()->profile()),
+ browser()
+ ->tab_strip_model()
+ ->GetActiveWebContents()
+ ->GetLastCommittedURL());
WaitForOneGoogleBarDataUpdate();
ASSERT_TRUE(GetAndResetOneGoogleBarRequestSeen());
@@ -3084,11 +3091,11 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
}
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, AppCacheRequests) {
- embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
- ASSERT_TRUE(StartEmbeddedTestServer());
-
- GURL main_url = embedded_test_server()->GetURL(
- "/appcache/simple_page_with_manifest.html");
+ std::string origin = "http://127.0.0.1:8080";
+ std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor =
+ content::URLLoaderInterceptor::ServeFilesFromDirectoryAtOrigin(
+ "content/test/data", GURL(origin));
+ GURL main_url(origin + "/appcache/simple_page_with_manifest.html");
base::string16 expected_title = base::ASCIIToUTF16("AppCache updated");
@@ -3139,11 +3146,16 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, AppCacheRequests) {
// 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");
+ // Use the embedded test server to support server-redirect, but serve
+ // appcache from a fixed port using the url loader interceptor below
+ // so that the appcache origin trial works.
ASSERT_TRUE(StartEmbeddedTestServer());
- GURL main_url = embedded_test_server()->GetURL(
- "/appcache/simple_page_with_manifest.html");
+ std::string origin = "http://127.0.0.1:8080";
+ auto interceptor =
+ content::URLLoaderInterceptor::ServeFilesFromDirectoryAtOrigin(
+ "content/test/data", GURL(origin));
+ GURL main_url(origin + "/appcache/simple_page_with_manifest.html");
base::string16 expected_title = base::ASCIIToUTF16("AppCache updated");
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
index 2cdf1e053f9..f9336578432 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
@@ -80,3 +80,9 @@ IN_PROC_BROWSER_TEST_F(
<< message_;
}
#endif
+
+IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiBrowserTest, TestStartStopStart) {
+ ASSERT_TRUE(
+ RunPlatformAppTest("api_test/webrtc_logging_private/start_stop_start"))
+ << message_;
+}
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 8e3faa800be..2425cd15e51 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
@@ -16,18 +16,76 @@
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/manifest_constants.h"
+#include "extensions/common/permissions/permission_set.h"
namespace extensions {
+namespace {
+
+// A helper function to determine if an extension from web store with given
+// information should be blocked by enterprise policy. It checks extension's
+// installation mode, permission and manifest type.
+// Returns true if the extension |mode| is blocked, removed or allowed by
+// wildcard/update_url but blocked by |manifest type| or |required permissions|.
+bool IsExtensionInstallBlockedByPolicy(
+ ExtensionManagement* extension_management,
+ ExtensionManagement::InstallationMode mode,
+ const ExtensionId& extension_id,
+ const std::string& update_url,
+ Manifest::Type manifest_type,
+ const PermissionSet& required_permissions) {
+ switch (mode) {
+ case ExtensionManagement::INSTALLATION_BLOCKED:
+ case ExtensionManagement::INSTALLATION_REMOVED:
+ return true;
+ case ExtensionManagement::INSTALLATION_FORCED:
+ case ExtensionManagement::INSTALLATION_RECOMMENDED:
+ return false;
+ case ExtensionManagement::INSTALLATION_ALLOWED:
+ break;
+ }
+
+ if (extension_management->IsInstallationExplicitlyAllowed(extension_id))
+ return false;
+
+ // Extension is allowed by wildcard or update_url, checks required permissions
+ // and manifest type.
+ // TODO(crbug.com/1088021): Find out the right way to handle extension policy
+ // priority.
+ if (!extension_management->IsAllowedManifestType(manifest_type,
+ extension_id)) {
+ return true;
+ }
+
+ if (!extension_management->IsPermissionSetAllowed(extension_id, update_url,
+ required_permissions)) {
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
const ExtensionId& extension_id,
Profile* profile) {
+ return GetWebstoreExtensionInstallStatus(
+ extension_id, profile, Manifest::Type::TYPE_UNKNOWN, PermissionSet());
+}
+
+ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
+ const ExtensionId& extension_id,
+ Profile* profile,
+ const Manifest::Type manifest_type,
+ const PermissionSet& required_permission_set) {
DCHECK(crx_file::id_util::IdIsValid(extension_id));
if (ExtensionPrefs::Get(profile)->HasDisableReason(
extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED)) {
return kCustodianApprovalRequired;
}
+
+ const GURL update_url = extension_urls::GetWebstoreUpdateUrl();
ExtensionManagement* extension_management =
ExtensionManagementFactory::GetForBrowserContext(profile);
// Always use webstore update url to check the installation mode because this
@@ -35,8 +93,8 @@ ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
// |Extension| instance. Note that we don't handle the case where an offstore
// extension with an identical ID is installed.
ExtensionManagement::InstallationMode mode =
- extension_management->GetInstallationMode(
- extension_id, extension_urls::GetWebstoreUpdateUrl().spec());
+ extension_management->GetInstallationMode(extension_id,
+ update_url.spec());
if (mode == ExtensionManagement::INSTALLATION_FORCED ||
mode == ExtensionManagement::INSTALLATION_RECOMMENDED)
@@ -56,7 +114,9 @@ ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
// kBlockedByPolicy, kCanRequest or kRequestPending instead of kDisabled.
// By doing so, user can still request an installed and policy blocked
// extension.
- if (mode == ExtensionManagement::INSTALLATION_ALLOWED) {
+ if (!IsExtensionInstallBlockedByPolicy(
+ extension_management, mode, extension_id, update_url.spec(),
+ manifest_type, required_permission_set)) {
if (registry->disabled_extensions().Contains(extension_id))
return kDisabled;
return kInstallable;
@@ -67,6 +127,8 @@ ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
if (!profile->GetPrefs()->GetBoolean(prefs::kCloudExtensionRequestEnabled))
return kBlockedByPolicy;
+ // An extension which is explicitly blocked by enterprise policy can't be
+ // requested anymore.
if (extension_management->IsInstallationExplicitlyBlocked(extension_id))
return kBlockedByPolicy;
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 bdb89f3e109..8164ef616e1 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
@@ -6,11 +6,14 @@
#define CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_PRIVATE_EXTENSION_INSTALL_STATUS_H_
#include "extensions/common/extension_id.h"
+#include "extensions/common/manifest.h"
class Profile;
namespace extensions {
+class PermissionSet;
+
enum ExtensionInstallStatus {
// Extension is blocked by policy but can be requested.
kCanRequest,
@@ -34,12 +37,24 @@ enum ExtensionInstallStatus {
kForceInstalled
};
-// Returns the Extension install status for an Chrome web store extension with
-// |extension_id| in |profile|.
+// Returns the Extension install status for a Chrome web store extension with
+// |extension_id| in |profile|. Note that this function won't check whether the
+// extension's manifest type or required permissions are blocked by enterprise
+// policy. type blocking or permission blocking. Please use this function only
+// if manifest file is not available.
ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
const ExtensionId& extension_id,
Profile* profile);
+// Returns the Extension install status for a Chrome web store extension with
+// |extension_id| in |profile|. Also check if |manifest_type| or any permission
+// in |required_permission_set| is blocked by enterprise policy.
+ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
+ const ExtensionId& extension_id,
+ Profile* profile,
+ const Manifest::Type manifest_type,
+ const PermissionSet& required_permission_set);
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_PRIVATE_EXTENSION_INSTALL_STATUS_H_
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 d4cfc262b0a..9354e5382b6 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
@@ -20,6 +20,8 @@
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/extension_builder.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/permissions/permission_set.h"
namespace extensions {
namespace {
@@ -42,19 +44,6 @@ constexpr char kExtensionSettingsWithIdBlocked[] = R"({
}
})";
-constexpr char kExtensionSettingsWithIdAllowed[] = R"({
- "abcdefghijklmnopabcdefghijklmnop": {
- "installation_mode": "allowed"
- }
-})";
-
-constexpr char kExtensionSettingsWithIdForced[] = R"({
- "abcdefghijklmnopabcdefghijklmnop": {
- "installation_mode": "force_installed",
- "update_url":"https://clients2.google.com/service/update2/crx"
- }
-})";
-
} // namespace
class ExtensionInstallStatusTest : public BrowserWithTestWindowTest {
@@ -139,7 +128,12 @@ TEST_F(ExtensionInstallStatusTest, ExtensionAllowed) {
}
TEST_F(ExtensionInstallStatusTest, ExtensionForceInstalledByPolicy) {
- SetExtensionSettings(kExtensionSettingsWithIdForced);
+ SetExtensionSettings(R"({
+ "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "force_installed",
+ "update_url":"https://clients2.google.com/service/update2/crx"
+ }
+ })");
ExtensionRegistry::Get(profile())->AddEnabled(CreateExtension(kExtensionId));
EXPECT_EQ(ExtensionInstallStatus::kForceInstalled,
GetWebstoreExtensionInstallStatus(kExtensionId, profile()));
@@ -218,7 +212,11 @@ TEST_F(ExtensionInstallStatusTest, PendingExtenisonIsApproved) {
SetPolicy(prefs::kCloudExtensionRequestEnabled,
std::make_unique<base::Value>(true));
std::vector<ExtensionId> ids = {kExtensionId};
- SetExtensionSettings(kExtensionSettingsWithIdAllowed);
+ SetExtensionSettings(R"({
+ "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "allowed"
+ }
+ })");
EXPECT_EQ(ExtensionInstallStatus::kInstallable,
GetWebstoreExtensionInstallStatus(kExtensionId, profile()));
}
@@ -244,4 +242,282 @@ TEST_F(ExtensionInstallStatusTest, ExtensionCustodianApprovalRequired) {
GetWebstoreExtensionInstallStatus(kExtensionId, profile()));
}
+TEST_F(ExtensionInstallStatusTest, ExtensionBlockedByManifestType) {
+ // TYPE_EXTENSION is blocked by policy
+ // TYPE_THEME and TYPE_HOSTED_APP are allowed.
+ SetExtensionSettings(R"({
+ "*": {
+ "allowed_types": ["theme", "hosted_app"]
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kBlockedByPolicy,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_EXTENSION,
+ PermissionSet()));
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_THEME,
+ PermissionSet()));
+
+ SetPolicy(prefs::kCloudExtensionRequestEnabled,
+ std::make_unique<base::Value>(true));
+ EXPECT_EQ(ExtensionInstallStatus::kCanRequest,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_EXTENSION,
+ PermissionSet()));
+ EXPECT_EQ(ExtensionInstallStatus::kCanRequest,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_HOSTED_APP,
+ PermissionSet()));
+
+ // Request has been approved. Note that currently, manifest type blocking
+ // actually overrides per-id setup. We will find the right priority with
+ // crbug.com/1088016.
+ SetExtensionSettings(R"({
+ "*": {
+ "allowed_types": ["theme", "hosted_app"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "allowed"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_EXTENSION,
+ PermissionSet()));
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_HOSTED_APP,
+ PermissionSet()));
+
+ // Request has been rejected.
+ SetExtensionSettings(R"({
+ "*": {
+ "allowed_types": ["theme", "hosted_app"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "blocked"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kBlockedByPolicy,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_EXTENSION,
+ PermissionSet()));
+ EXPECT_EQ(ExtensionInstallStatus::kBlockedByPolicy,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_HOSTED_APP,
+ PermissionSet()));
+
+ // Request has been forced installed.
+ SetExtensionSettings(R"({
+ "*": {
+ "allowed_types": ["theme", "hosted_app"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "force_installed",
+ "update_url":"https://clients2.google.com/service/update2/crx"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kForceInstalled,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_EXTENSION,
+ PermissionSet()));
+ EXPECT_EQ(ExtensionInstallStatus::kForceInstalled,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile(),
+ Manifest::Type::TYPE_HOSTED_APP,
+ PermissionSet()));
+}
+
+TEST_F(ExtensionInstallStatusTest, ExtensionBlockedByPermissions) {
+ // Block 'storage' for all extensions.
+ SetExtensionSettings(R"({
+ "*": {
+ "blocked_permissions": ["storage"]
+ }
+ })");
+
+ // Extension with audio permission is still installable but not with storage.
+ APIPermissionSet api_permissions;
+ api_permissions.insert(APIPermission::kAudio);
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+ api_permissions.insert(APIPermission::kStorage);
+ EXPECT_EQ(ExtensionInstallStatus::kBlockedByPolicy,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // And they can be requested,
+ SetPolicy(prefs::kCloudExtensionRequestEnabled,
+ std::make_unique<base::Value>(true));
+ EXPECT_EQ(ExtensionInstallStatus::kCanRequest,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // Request has been approved.
+ SetExtensionSettings(R"({
+ "*": {
+ "blocked_permissions": ["storage"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "allowed"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // Request has been rejected.
+ SetExtensionSettings(R"({
+ "*": {
+ "blocked_permissions": ["storage"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "blocked"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kBlockedByPolicy,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // Request has been force installed.
+ SetExtensionSettings(R"({
+ "*": {
+ "blocked_permissions": ["storage"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "force_installed",
+ "update_url":"https://clients2.google.com/service/update2/crx"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kForceInstalled,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+}
+
+TEST_F(ExtensionInstallStatusTest, ExtensionBlockedByPermissionsWithUpdateUrl) {
+ // Block 'downloads' for all extensions from web store.
+ SetExtensionSettings(R"({
+ "update_url:https://clients2.google.com/service/update2/crx": {
+ "blocked_permissions": ["downloads"]
+ }
+ })");
+
+ APIPermissionSet api_permissions;
+ api_permissions.insert(APIPermission::kAudio);
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+ api_permissions.insert(APIPermission::kDownloads);
+ EXPECT_EQ(ExtensionInstallStatus::kBlockedByPolicy,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // And they can be requested,
+ SetPolicy(prefs::kCloudExtensionRequestEnabled,
+ std::make_unique<base::Value>(true));
+ EXPECT_EQ(ExtensionInstallStatus::kCanRequest,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // Request has been approved.
+ SetExtensionSettings(R"({
+ "update_url:https://clients2.google.com/service/update2/crx": {
+ "blocked_permissions": ["downloads"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "allowed"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // Request has been rejected.
+ SetExtensionSettings(R"({
+ "update_url:https://clients2.google.com/service/update2/crx": {
+ "blocked_permissions": ["downloads"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "blocked"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kBlockedByPolicy,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+
+ // Request has been force-installed.
+ SetExtensionSettings(R"({
+ "update_url:https://clients2.google.com/service/update2/crx": {
+ "blocked_permissions": ["downloads"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "force_installed",
+ "update_url":"https://clients2.google.com/service/update2/crx"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kForceInstalled,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+}
+
+TEST_F(ExtensionInstallStatusTest,
+ ExtensionBlockedByPermissionButWhitelistById) {
+ SetExtensionSettings(R"({
+ "*": {
+ "blocked_permissions": ["storage"]
+ }, "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode": "allowed"
+ }})");
+
+ // Per-id whitelisted has higher priority than blocked permissions.
+ APIPermissionSet api_permissions;
+ api_permissions.insert(APIPermission::kStorage);
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+}
+
+// Extension policies apply to non web store update url doesn't affect the
+// status here.
+TEST_F(ExtensionInstallStatusTest, NonWebstoreUpdateUrlPolicy) {
+ SetExtensionSettings(R"({
+ "update_url:https://other.extensions/webstore": {
+ "installation_mode": "blocked"
+ }
+ })");
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile()));
+
+ SetExtensionSettings(R"({
+ "update_url:https://other.extensions/webstore": {
+ "blocked_permissions": ["downloads"]
+ }
+ })");
+ APIPermissionSet api_permissions;
+ api_permissions.insert(APIPermission::kDownloads);
+ EXPECT_EQ(ExtensionInstallStatus::kInstallable,
+ GetWebstoreExtensionInstallStatus(
+ kExtensionId, profile(), Manifest::Type::TYPE_EXTENSION,
+ PermissionSet(api_permissions.Clone(), ManifestPermissionSet(),
+ URLPatternSet(), URLPatternSet())));
+}
+
} // 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 862650ef793..ebfeb3568a3 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
@@ -49,7 +49,10 @@
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
+#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
+#include "extensions/common/manifest_handlers/permissions_parser.h"
+#include "extensions/common/permissions/permission_set.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "ui/base/l10n/l10n_util.h"
@@ -118,7 +121,7 @@ std::unique_ptr<WebstoreInstaller::Approval> PendingApprovals::PopApproval(
const std::string& id) {
for (auto iter = approvals_.begin(); iter != approvals_.end(); ++iter) {
if (iter->get()->extension_id == id &&
- profile->IsSameProfile(iter->get()->profile)) {
+ profile->IsSameOrParent(iter->get()->profile)) {
std::unique_ptr<WebstoreInstaller::Approval> approval = std::move(*iter);
approvals_.erase(iter);
return approval;
@@ -267,6 +270,9 @@ ConvertExtensionInstallStatusForAPI(ExtensionInstallStatus status) {
// successfully. Otherwise, returns the initial extension install status.
ExtensionInstallStatus AddExtensionToPendingList(const ExtensionId& id,
Profile* profile) {
+ // There is no need to check whether the extension's required permissions or
+ // manifest type are blocked by the enterprise policy because extensions
+ // blocked by those are still requestable.
ExtensionInstallStatus status =
GetWebstoreExtensionInstallStatus(id, profile);
// We put the |id| into the pending request list if it can be requested.
@@ -447,8 +453,9 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess(
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
// Check the management policy before the installation process begins.
- ExtensionInstallStatus install_status =
- GetWebstoreExtensionInstallStatus(id, profile);
+ ExtensionInstallStatus install_status = GetWebstoreExtensionInstallStatus(
+ id, profile, dummy_extension_->manifest()->type(),
+ PermissionsParser::GetRequiredPermissions(dummy_extension_.get()));
if (install_status == kBlockedByPolicy) {
ShowBlockedByPolicyDialog(
dummy_extension_.get(), icon_, web_contents,
@@ -582,7 +589,7 @@ bool WebstorePrivateBeginInstallWithManifest3Function::
parent_permission_dialog_ =
ParentPermissionDialog::CreateParentPermissionDialogForExtension(
- profile, web_contents, web_contents->GetTopLevelNativeWindow(),
+ profile, web_contents->GetTopLevelNativeWindow(),
gfx::ImageSkia::CreateFrom1xBitmap(icon_), dummy_extension_.get(),
std::move(done_callback));
parent_permission_dialog_->ShowDialog();
@@ -697,12 +704,13 @@ void WebstorePrivateBeginInstallWithManifest3Function::HandleInstallAbort(
// The web store install histograms are a subset of the install histograms.
// We need to record both histograms here since CrxInstaller::InstallUIAbort
// is never called for web store install cancellations.
- std::string histogram_name = user_initiated ? "WebStoreInstallCancel"
- : "WebStoreInstallAbort";
- ExtensionService::RecordPermissionMessagesHistogram(dummy_extension_.get(),
- histogram_name.c_str());
+ if (user_initiated) {
+ ExtensionService::RecordPermissionMessagesHistogram(
+ dummy_extension_.get(), "WebStoreInstallCancel");
+ }
- histogram_name = user_initiated ? "InstallCancel" : "InstallAbort";
+ std::string histogram_name =
+ user_initiated ? "InstallCancel" : "InstallAbort";
ExtensionService::RecordPermissionMessagesHistogram(dummy_extension_.get(),
histogram_name.c_str());
@@ -1094,12 +1102,58 @@ WebstorePrivateGetExtensionStatusFunction::Run() {
return RespondNow(Error(kWebstoreInvalidIdError));
}
+ if (!params->manifest)
+ return RespondNow(BuildResponseWithoutManifest(extension_id, profile));
+
+ data_decoder::DataDecoder::ParseJsonIsolated(
+ *(params->manifest),
+ base::BindOnce(
+ &WebstorePrivateGetExtensionStatusFunction::OnManifestParsed, this,
+ extension_id));
+ return RespondLater();
+}
+
+ExtensionFunction::ResponseValue
+WebstorePrivateGetExtensionStatusFunction::BuildResponseWithoutManifest(
+ const ExtensionId& extension_id,
+ Profile* profile) {
ExtensionInstallStatus status =
GetWebstoreExtensionInstallStatus(extension_id, profile);
api::webstore_private::ExtensionInstallStatus api_status =
ConvertExtensionInstallStatusForAPI(status);
- return RespondNow(
- OneArgument(GetExtensionStatus::Results::Create(api_status)));
+ return ArgumentList(GetExtensionStatus::Results::Create(api_status));
+}
+
+void WebstorePrivateGetExtensionStatusFunction::OnManifestParsed(
+ const ExtensionId& extension_id,
+ data_decoder::DataDecoder::ValueOrError result) {
+ if (!result.value || !result.value->is_dict()) {
+ Respond(Error(kWebstoreInvalidManifestError));
+ return;
+ }
+
+ if (!g_browser_process->profile_manager()->IsValidProfile(
+ chrome_details_.GetProfile())) {
+ Respond(Error(kWebstoreUserCancelledError));
+ }
+
+ std::string error;
+ auto dummy_extension =
+ Extension::Create(base::FilePath(), Manifest::INTERNAL,
+ base::Value::AsDictionaryValue(*result.value),
+ Extension::FROM_WEBSTORE, extension_id, &error);
+
+ if (!dummy_extension) {
+ Respond(Error(kWebstoreInvalidManifestError));
+ return;
+ }
+
+ ExtensionInstallStatus status = GetWebstoreExtensionInstallStatus(
+ extension_id, chrome_details_.GetProfile(), dummy_extension->GetType(),
+ PermissionsParser::GetRequiredPermissions(dummy_extension.get()));
+ api::webstore_private::ExtensionInstallStatus api_status =
+ ConvertExtensionInstallStatusForAPI(status);
+ Respond(ArgumentList(GetExtensionStatus::Results::Create(api_status)));
}
WebstorePrivateRequestExtensionFunction::
@@ -1124,7 +1178,8 @@ WebstorePrivateRequestExtensionFunction::Run() {
api::webstore_private::ExtensionInstallStatus api_status =
ConvertExtensionInstallStatusForAPI(status);
- return RespondNow(OneArgument(RequestExtension::Results::Create(api_status)));
+ return RespondNow(
+ ArgumentList(RequestExtension::Results::Create(api_status)));
}
} // 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 d1bbb96b944..b4b3e646698 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
@@ -372,6 +372,12 @@ class WebstorePrivateGetExtensionStatusFunction : public ExtensionFunction {
private:
~WebstorePrivateGetExtensionStatusFunction() override;
+ ExtensionFunction::ResponseValue BuildResponseWithoutManifest(
+ const ExtensionId& extension_id,
+ Profile* profile);
+ void OnManifestParsed(const ExtensionId& extension_id,
+ data_decoder::DataDecoder::ValueOrError result);
+
// ExtensionFunction:
ExtensionFunction::ResponseAction Run() override;
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 09b988d79e9..4a1771a1d79 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
@@ -55,7 +55,7 @@
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_test_util.h"
#include "chrome/browser/ui/supervised_user/parent_permission_dialog.h"
-#include "chrome/browser/ui/views/parent_permission_dialog_view.h"
+#include "chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.h"
#include "components/account_id/account_id.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "extensions/common/extension_builder.h"
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 49e6ebbb3dc..1bff22cebc1 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
@@ -23,6 +23,7 @@
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/extension_builder.h"
+#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
namespace extensions {
namespace {
@@ -32,7 +33,10 @@ constexpr int kFakeTime = 12345;
constexpr char kExtensionManifest[] = R"({
\"name\" : \"Extension\",
\"manifest_version\": 3,
- \"version\": \"0.1\"})";
+ \"version\": \"0.1\",
+ \"permissions\": [ \"example.com\", \"downloads\"],
+ \"optional_permissions\" : [\"audio\"]})";
+
constexpr char kBlockAllExtensionSettings[] = R"({
"*": {
"installation_mode":"blocked",
@@ -57,6 +61,24 @@ constexpr char kBlockedExtensionSettings[] = R"({
}
})";
+constexpr char kBlockedManifestTypeExtensionSettings[] = R"({
+ "*": {
+ "allowed_types": ["theme", "hosted_app"]
+ }
+})";
+
+constexpr char kBlockedDownloadsPermissionsExtensionSettings[] = R"({
+ "*": {
+ "blocked_permissions": ["downloads"]
+ }
+})";
+
+constexpr char kBlockedAudioPermissionsExtensionSettings[] = R"({
+ "*": {
+ "blocked_permissions": ["audio"]
+ }
+})";
+
constexpr char kWebstoreUserCancelledError[] = "User cancelled install";
constexpr char kWebstoreBlockByPolicy[] =
"Extension installation is blocked by policy";
@@ -103,17 +125,18 @@ class WebstorePrivateExtensionInstallRequestBase : public ExtensionApiUnittest {
return base::StringPrintf(R"(["%s"])", id);
}
+ std::string GenerateArgs(const char* id, const char* manifest) {
+ return base::StringPrintf(R"(["%s", "%s"])", id, manifest);
+ }
+
scoped_refptr<const Extension> CreateExtension(const ExtensionId& id) {
return ExtensionBuilder("extension").SetID(id).Build();
}
void VerifyResponse(const ExtensionInstallStatus& expected_response,
const base::Value* actual_response) {
- ASSERT_TRUE(actual_response->is_list());
- const auto& actual_list = actual_response->GetList();
- ASSERT_EQ(1u, actual_list.size());
- ASSERT_TRUE(actual_list[0].is_string());
- EXPECT_EQ(ToString(expected_response), actual_list[0].GetString());
+ ASSERT_TRUE(actual_response->is_string());
+ EXPECT_EQ(ToString(expected_response), actual_response->GetString());
}
private:
@@ -121,7 +144,18 @@ class WebstorePrivateExtensionInstallRequestBase : public ExtensionApiUnittest {
};
class WebstorePrivateGetExtensionStatusTest
- : public WebstorePrivateExtensionInstallRequestBase {};
+ : public WebstorePrivateExtensionInstallRequestBase {
+ public:
+ void SetUp() override {
+ WebstorePrivateExtensionInstallRequestBase::SetUp();
+ in_process_data_decoder_ =
+ std::make_unique<data_decoder::test::InProcessDataDecoder>();
+ }
+
+ private:
+ std::unique_ptr<data_decoder::test::InProcessDataDecoder>
+ in_process_data_decoder_;
+};
TEST_F(WebstorePrivateGetExtensionStatusTest, InvalidExtensionId) {
auto function =
@@ -141,6 +175,49 @@ TEST_F(WebstorePrivateGetExtensionStatusTest, ExtensionEnabled) {
response.get());
}
+TEST_F(WebstorePrivateGetExtensionStatusTest, InvalidManifest) {
+ auto function =
+ base::MakeRefCounted<WebstorePrivateGetExtensionStatusFunction>();
+ EXPECT_EQ(
+ "Invalid manifest",
+ RunFunctionAndReturnError(
+ function.get(), GenerateArgs(kExtensionId, "invalid-manifest")));
+}
+
+TEST_F(WebstorePrivateGetExtensionStatusTest, ExtensionBlockdedByManifestType) {
+ SetExtensionSettings(kBlockedManifestTypeExtensionSettings, profile());
+ auto function =
+ base::MakeRefCounted<WebstorePrivateGetExtensionStatusFunction>();
+ std::unique_ptr<base::Value> response = RunFunctionAndReturnValue(
+ function.get(), GenerateArgs(kExtensionId, kExtensionManifest));
+ VerifyResponse(
+ ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_BLOCKED_BY_POLICY,
+ response.get());
+}
+
+TEST_F(WebstorePrivateGetExtensionStatusTest, ExtensionBlockdedByPermission) {
+ SetExtensionSettings(kBlockedDownloadsPermissionsExtensionSettings,
+ profile());
+ auto function =
+ base::MakeRefCounted<WebstorePrivateGetExtensionStatusFunction>();
+ std::unique_ptr<base::Value> response = RunFunctionAndReturnValue(
+ function.get(), GenerateArgs(kExtensionId, kExtensionManifest));
+ VerifyResponse(
+ ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_BLOCKED_BY_POLICY,
+ response.get());
+}
+
+TEST_F(WebstorePrivateGetExtensionStatusTest,
+ ExtensionNotBlockdedByOptionalPermission) {
+ SetExtensionSettings(kBlockedAudioPermissionsExtensionSettings, profile());
+ auto function =
+ base::MakeRefCounted<WebstorePrivateGetExtensionStatusFunction>();
+ std::unique_ptr<base::Value> response = RunFunctionAndReturnValue(
+ function.get(), GenerateArgs(kExtensionId, kExtensionManifest));
+ VerifyResponse(ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_INSTALLABLE,
+ response.get());
+}
+
class WebstorePrivateRequestExtensionTest
: public WebstorePrivateExtensionInstallRequestBase {
public:
@@ -434,4 +511,57 @@ TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
VerifyBlockedByPolicyFunctionResult(function.get(), base::string16());
}
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
+ ExtensionBlockdedByManifestType) {
+ SetExtensionSettings(kBlockedManifestTypeExtensionSettings);
+
+ 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::string16());
+}
+
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
+ ExtensionBlockdedByPermission) {
+ SetExtensionSettings(kBlockedDownloadsPermissionsExtensionSettings);
+
+ 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::string16());
+}
+
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
+ ExtensionNotBlockdedByOptionalPermission) {
+ SetExtensionSettings(kBlockedAudioPermissionsExtensionSettings);
+
+ 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);
+
+ std::unique_ptr<base::Value> response = RunFunctionAndReturnValue(
+ function.get(), GenerateArgs(kExtensionId, kExtensionManifest));
+ // The API returns empty string when extension is installed successfully.
+ ASSERT_TRUE(response);
+ ASSERT_TRUE(response->is_string());
+ EXPECT_EQ(std::string(), response->GetString());
+}
+
} // namespace extensions