summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-12 14:07:37 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-07-17 10:29:26 +0000
commitec02ee4181c49b61fce1c8fb99292dbb8139cc90 (patch)
tree25cde714b2b71eb639d1cd53f5a22e9ba76e14ef /chromium/chrome/browser
parentbb09965444b5bb20b096a291445170876225268d (diff)
BASELINE: Update Chromium to 59.0.3071.134
Change-Id: Id02ef6fb2204c5fd21668a1c3e6911c83b17585a Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/chrome/browser')
-rw-r--r--chromium/chrome/browser/BUILD.gn297
-rw-r--r--chromium/chrome/browser/android/vr_shell/BUILD.gn55
-rw-r--r--chromium/chrome/browser/apps/BUILD.gn56
-rw-r--r--chromium/chrome/browser/browser_resources.grd52
-rw-r--r--chromium/chrome/browser/chrome_content_browser_manifest_overlay.json12
-rw-r--r--chromium/chrome/browser/chrome_content_renderer_manifest_overlay.json3
-rw-r--r--chromium/chrome/browser/chrome_content_utility_manifest_overlay.json5
-rw-r--r--chromium/chrome/browser/chrome_notification_types.h6
-rw-r--r--chromium/chrome/browser/chromeos/BUILD.gn48
-rw-r--r--chromium/chrome/browser/devtools/BUILD.gn2
-rw-r--r--chromium/chrome/browser/engagement/BUILD.gn (renamed from chromium/chrome/browser/ui/webui/engagement/BUILD.gn)2
-rw-r--r--chromium/chrome/browser/engagement/site_engagement_details.mojom23
-rw-r--r--chromium/chrome/browser/extensions/BUILD.gn59
-rw-r--r--chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/automation/automation_apitest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/bluetooth_low_energy/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_display_private_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc91
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc265
-rw-r--r--chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h3
-rw-r--r--chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/commands/OWNERS3
-rw-r--r--chromium/chrome/browser/extensions/api/commands/command_service.cc31
-rw-r--r--chromium/chrome/browser/extensions/api/commands/command_service_browsertest.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h5
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_api.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h6
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_unittest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/debugger/debugger_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc17
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/content_action.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc61
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc179
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h49
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc292
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/dial/device_description_fetcher.cc150
-rw-r--r--chromium/chrome/browser/extensions/api/dial/device_description_fetcher.h73
-rw-r--r--chromium/chrome/browser/extensions/api/dial/device_description_fetcher_unittest.cc178
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_api.cc66
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_api.h49
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_apitest.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_device_data.cc67
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_device_data.h109
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_device_data_unittest.cc108
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_registry.cc359
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_registry.h202
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_registry_unittest.cc383
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_service.cc626
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_service.h299
-rw-r--r--chromium/chrome/browser/extensions/api/dial/dial_service_unittest.cc239
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc17
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h4
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc2
-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_api_unittest.cc85
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc57
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h16
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc35
-rw-r--r--chromium/chrome/browser/extensions/api/feedback_private/OWNERS4
-rw-r--r--chromium/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc17
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/file_system_api.cc47
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/file_system_api.h5
-rw-r--r--chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc18
-rw-r--r--chromium/chrome/browser/extensions/api/gcm/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/gcm/gcm_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/history/history_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_apitest.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc38
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h5
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/idltest/idltest_api.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc43
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.h10
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc41
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc30
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h1
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/instance_id/OWNERS4
-rw-r--r--chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h2
-rw-r--r--chromium/chrome/browser/extensions/api/mdns/mdns_api.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/extension_message_port.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/incognito_connectability.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/incognito_connectability.h9
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/message_service.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest_unittest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/metrics_private/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/module/module.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc231
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h52
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc236
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h131
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc158
-rw-r--r--chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc243
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h64
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc161
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc218
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc78
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc30
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h28
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/OWNERS3
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc95
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.h72
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.cc49
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h46
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.h25
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/notifications_api.cc50
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/notifications_api.h6
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc151
-rw-r--r--chromium/chrome/browser/extensions/api/omnibox/omnibox_api.cc27
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc38
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h7
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc97
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h6
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h2
-rw-r--r--chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc32
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/preference/chrome_direct_setting.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_api.cc76
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_api.h5
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc63
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_helpers.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/processes/processes_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api.cc24
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api.h10
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h3
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc76
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/sessions/sessions_api.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc63
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/prefs_util.h5
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.h6
-rw-r--r--chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h1
-rw-r--r--chromium/chrome/browser/extensions/api/spellcheck/spellcheck_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/storage/policy_value_store.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/storage/settings_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc132
-rw-r--r--chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h4
-rw-r--r--chromium/chrome/browser/extensions/api/system_indicator/OWNERS3
-rw-r--r--chromium/chrome/browser/extensions/api/system_private/system_private_api.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h6
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/app_window_controller.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_api.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc49
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_test.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_windows_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/virtual_keyboard_private/OWNERS1
-rw-r--r--chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc17
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc88
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h23
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc55
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc42
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc70
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h22
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc22
-rw-r--r--chromium/chrome/browser/media/router/BUILD.gn34
-rw-r--r--chromium/chrome/browser/media/router/discovery/BUILD.gn30
-rw-r--r--chromium/chrome/browser/media/router/mojo/media_controller.mojom35
-rw-r--r--chromium/chrome/browser/media/router/mojo/media_router.mojom55
-rw-r--r--chromium/chrome/browser/media/router/mojo/media_router.typemap8
-rw-r--r--chromium/chrome/browser/media/router/mojo/media_router_traits_test_service.mojom14
-rw-r--r--chromium/chrome/browser/media/router/mojo/media_status.mojom60
-rw-r--r--chromium/chrome/browser/media/router/mojo/media_status.typemap12
-rw-r--r--chromium/chrome/browser/media/router/mojo/typemaps.gni5
-rw-r--r--chromium/chrome/browser/ntp_snippets/BUILD.gn13
-rw-r--r--chromium/chrome/browser/prefs/forwarder_manifest.json16
-rw-r--r--chromium/chrome/browser/prefs/preferences_manifest.json13
-rw-r--r--chromium/chrome/browser/printing/background_printing_manager.cc16
-rw-r--r--chromium/chrome/browser/printing/background_printing_manager.h5
-rw-r--r--chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.cc28
-rw-r--r--chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.h13
-rw-r--r--chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list_unittest.cc10
-rw-r--r--chromium/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc54
-rw-r--r--chromium/chrome/browser/printing/cloud_print/gcd_api_flow.cc13
-rw-r--r--chromium/chrome/browser/printing/cloud_print/gcd_api_flow.h26
-rw-r--r--chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc77
-rw-r--r--chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.h8
-rw-r--r--chromium/chrome/browser/printing/cloud_print/gcd_api_flow_unittest.cc10
-rw-r--r--chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.cc26
-rw-r--r--chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.h11
-rw-r--r--chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow_unittest.cc2
-rw-r--r--chromium/chrome/browser/printing/cloud_print/privet_http_impl.cc27
-rw-r--r--chromium/chrome/browser/printing/pdf_to_emf_converter.cc5
-rw-r--r--chromium/chrome/browser/printing/print_job.cc4
-rw-r--r--chromium/chrome/browser/printing/print_view_manager.cc10
-rw-r--r--chromium/chrome/browser/printing/pwg_raster_converter.cc2
-rw-r--r--chromium/chrome/browser/printing/pwg_raster_converter.h1
-rw-r--r--chromium/chrome/browser/resources/.clang-format8
-rw-r--r--chromium/chrome/browser/resources/BUILD.gn55
-rw-r--r--chromium/chrome/browser/resources/PRESUBMIT.py7
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn9
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json37
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/strings/BUILD.gn1
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd44
-rw-r--r--chromium/chrome/browser/resources/chromeos/crosh_builtin/manifest.json4
-rw-r--r--chromium/chrome/browser/resources/chromeos/first_run/app/manifest.json1
-rw-r--r--chromium/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn7
-rw-r--r--chromium/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp15
-rw-r--r--chromium/chrome/browser/resources/chromeos/select_to_speak/strings/BUILD.gn73
-rw-r--r--chromium/chrome/browser/resources/chromeos/select_to_speak/strings/select_to_speak_strings.grd158
-rw-r--r--chromium/chrome/browser/resources/chromeos/switch_access/BUILD.gn28
-rw-r--r--chromium/chrome/browser/resources/chromeos/switch_access/compiled_resources2.gyp62
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/cleanup.html36
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/cleanup_browser_proxy.html (renamed from chromium/chrome/browser/resources/settings/animation/animation_group.html)2
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/cleanup_browser_proxy.js50
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/compiled_resources2.gyp33
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/icons.html19
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/manager.html145
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/manager.js117
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/toolbar.html26
-rw-r--r--chromium/chrome/browser/resources/cleanup_tool/toolbar.js11
-rw-r--r--chromium/chrome/browser/resources/component_extension_resources.grd8
-rw-r--r--chromium/chrome/browser/resources/device_log_ui/device_log_ui.css2
-rw-r--r--chromium/chrome/browser/resources/device_log_ui/device_log_ui.html4
-rw-r--r--chromium/chrome/browser/resources/easy_unlock/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/engagement/site_engagement.html4
-rw-r--r--chromium/chrome/browser/resources/engagement/site_engagement.js47
-rw-r--r--chromium/chrome/browser/resources/extensions/OWNERS3
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_options_overlay.html3
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions.js3
-rw-r--r--chromium/chrome/browser/resources/feedback/OWNERS4
-rw-r--r--chromium/chrome/browser/resources/feedback/css/feedback.css12
-rw-r--r--chromium/chrome/browser/resources/feedback/html/default.html2
-rw-r--r--chromium/chrome/browser/resources/feedback/js/feedback.js3
-rw-r--r--chromium/chrome/browser/resources/google_now/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/google_now/background.js1504
-rw-r--r--chromium/chrome/browser/resources/google_now/background_test_util.js32
-rw-r--r--chromium/chrome/browser/resources/google_now/background_unittest.gtestjs1354
-rw-r--r--chromium/chrome/browser/resources/google_now/cards.js387
-rw-r--r--chromium/chrome/browser/resources/google_now/cards_unittest.gtestjs646
-rw-r--r--chromium/chrome/browser/resources/google_now/common_test_util.js205
-rw-r--r--chromium/chrome/browser/resources/google_now/images/icon128.pngbin1999 -> 0 bytes
-rw-r--r--chromium/chrome/browser/resources/google_now/images/icon16.pngbin401 -> 0 bytes
-rw-r--r--chromium/chrome/browser/resources/google_now/images/icon48.pngbin1082 -> 0 bytes
-rw-r--r--chromium/chrome/browser/resources/google_now/manifest.json40
-rw-r--r--chromium/chrome/browser/resources/google_now/utility.js1072
-rw-r--r--chromium/chrome/browser/resources/google_now/utility_test_util.js27
-rw-r--r--chromium/chrome/browser/resources/google_now/utility_unittest.gtestjs995
-rw-r--r--chromium/chrome/browser/resources/hangout_services/manifest.json2
-rw-r--r--chromium/chrome/browser/resources/hangout_services/thunk.js6
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_single.js131
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js4
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_util.js19
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/actions.html2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/actions.js215
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/api_listener.html5
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/api_listener.js94
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/app.html36
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/app.js117
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp117
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/constants.html1
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/constants.js25
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js624
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/edit_dialog.html40
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js139
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/folder_node.html71
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/folder_node.js117
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/item.html11
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/item.js78
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/list.html53
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/list.js70
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/reducers.html3
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/reducers.js432
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/router.html2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/router.js67
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/shared_style.html32
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/shared_vars.html12
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/sidebar.html9
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/sidebar.js12
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/store.html12
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/store.js519
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/store_client.html4
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/store_client.js98
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/toolbar.html20
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/toolbar.js50
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/types.js92
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/util.html2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/util.js176
-rw-r--r--chromium/chrome/browser/resources/md_downloads/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/md_downloads/downloads.html19
-rw-r--r--chromium/chrome/browser/resources/md_downloads/focus_row.js47
-rw-r--r--chromium/chrome/browser/resources/md_downloads/item.html1
-rw-r--r--chromium/chrome/browser/resources/md_downloads/manager.html4
-rw-r--r--chromium/chrome/browser/resources/md_downloads/manager.js5
-rw-r--r--chromium/chrome/browser/resources/md_downloads/toolbar.html3
-rw-r--r--chromium/chrome/browser/resources/md_extensions/OWNERS3
-rw-r--r--chromium/chrome/browser/resources/md_extensions/animation_helper.js81
-rw-r--r--chromium/chrome/browser/resources/md_extensions/code_section.html4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/code_section.js24
-rw-r--r--chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp30
-rw-r--r--chromium/chrome/browser/resources/md_extensions/detail_view.html179
-rw-r--r--chromium/chrome/browser/resources/md_extensions/detail_view.js60
-rw-r--r--chromium/chrome/browser/resources/md_extensions/error_page.html2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/error_page.js4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item.html41
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item.js58
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_list.js4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_source.js52
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_util.html (renamed from chromium/chrome/browser/resources/md_extensions/item_source.html)2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_util.js123
-rw-r--r--chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/load_error.html119
-rw-r--r--chromium/chrome/browser/resources/md_extensions/load_error.js69
-rw-r--r--chromium/chrome/browser/resources/md_extensions/manager.html32
-rw-r--r--chromium/chrome/browser/resources/md_extensions/manager.js42
-rw-r--r--chromium/chrome/browser/resources/md_extensions/pack_dialog.html39
-rw-r--r--chromium/chrome/browser/resources/md_extensions/service.js37
-rw-r--r--chromium/chrome/browser/resources/md_extensions/sidebar.html86
-rw-r--r--chromium/chrome/browser/resources/md_extensions/sidebar.js55
-rw-r--r--chromium/chrome/browser/resources/md_extensions/toolbar.html86
-rw-r--r--chromium/chrome/browser/resources/md_extensions/toolbar.js68
-rw-r--r--chromium/chrome/browser/resources/md_history/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/md_history/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/md_history/history.html1
-rw-r--r--chromium/chrome/browser/resources/md_history/history_item.html2
-rw-r--r--chromium/chrome/browser/resources/md_history/history_list.html2
-rw-r--r--chromium/chrome/browser/resources/md_history/history_list.js6
-rw-r--r--chromium/chrome/browser/resources/md_history/history_toolbar.html135
-rw-r--r--chromium/chrome/browser/resources/md_history/history_toolbar.js18
-rw-r--r--chromium/chrome/browser/resources/md_history/lazy_load.html1
-rw-r--r--chromium/chrome/browser/resources/md_history/shared_vars.html2
-rw-r--r--chromium/chrome/browser/resources/md_history/side_bar.html12
-rw-r--r--chromium/chrome/browser/resources/md_history/side_bar.js14
-rw-r--r--chromium/chrome/browser/resources/md_history/synced_device_card.html3
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js2
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_details/route_details.css5
-rw-r--r--chromium/chrome/browser/resources/media_router/icons/media_router_icons.html1
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_data.js5
-rw-r--r--chromium/chrome/browser/resources/net_internals/dns_view.html3
-rw-r--r--chromium/chrome/browser/resources/net_internals/dns_view.js35
-rw-r--r--chromium/chrome/browser/resources/net_internals/sdch_view.js4
-rw-r--r--chromium/chrome/browser/resources/net_internals/source_entry.js1
-rw-r--r--chromium/chrome/browser/resources/ntp4/OWNERS3
-rw-r--r--chromium/chrome/browser/resources/options/browser_options.js2
-rw-r--r--chromium/chrome/browser/resources/options/compiled_resources.gyp2
-rw-r--r--chromium/chrome/browser/resources/options/controlled_setting.js10
-rw-r--r--chromium/chrome/browser/resources/options/i18n_setup.html6
-rw-r--r--chromium/chrome/browser/resources/options/import_data_overlay.html22
-rw-r--r--chromium/chrome/browser/resources/options/import_data_overlay.js10
-rw-r--r--chromium/chrome/browser/resources/options/options.html2
-rw-r--r--chromium/chrome/browser/resources/options/options.js3
-rw-r--r--chromium/chrome/browser/resources/options_resources.grd108
-rw-r--r--chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json6
-rw-r--r--chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json6
-rw-r--r--chromium/chrome/browser/resources/plugin_metadata/plugins_win.json6
-rw-r--r--chromium/chrome/browser/resources/predictors/predictors.css4
-rw-r--r--chromium/chrome/browser/resources/predictors/resource_prefetch_predictor.js5
-rw-r--r--chromium/chrome/browser/resources/print_preview/common/search_box.css6
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination_store.js23
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js18
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js56
-rw-r--r--chromium/chrome/browser/resources/print_preview/native_layer.js8
-rw-r--r--chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js19
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.css16
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.html1
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.html10
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.js142
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/destination_list.js11
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/destination_list_item.css13
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/destination_list_item.html11
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/destination_list_item.js88
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/destination_search.css18
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/destination_search.js114
-rw-r--r--chromium/chrome/browser/resources/print_preview/settings/page_settings.css6
-rw-r--r--chromium/chrome/browser/resources/quota_internals_resources.grd6
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb12
-rw-r--r--chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.html45
-rw-r--r--chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.js139
-rw-r--r--chromium/chrome/browser/resources/settings/BUILD.gn53
-rw-r--r--chromium/chrome/browser/resources/settings/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html39
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/a11y_page.js16
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html70
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js16
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.html6
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.js12
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html20
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/detailed_build_info.js41
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.html27
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.js45
-rw-r--r--chromium/chrome/browser/resources/settings/android_apps_page/android_apps_browser_proxy.js8
-rw-r--r--chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.html99
-rw-r--r--chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.js90
-rw-r--r--chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html53
-rw-r--r--chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.js109
-rw-r--r--chromium/chrome/browser/resources/settings/android_apps_page/compiled_resources2.gyp14
-rw-r--r--chromium/chrome/browser/resources/settings/animation/animation_group.js49
-rw-r--r--chromium/chrome/browser/resources/settings/animation/compiled_resources2.gyp6
-rw-r--r--chromium/chrome/browser/resources/settings/animation/fade_animations.html3
-rw-r--r--chromium/chrome/browser/resources/settings/animation/fade_animations.js51
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js11
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html182
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js44
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html73
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js63
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp13
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/home_url_input.html36
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js141
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.html20
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.js26
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.js2
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html24
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js42
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html22
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js25
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.html8
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.js8
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_delete_confirmation_dialog.js8
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_entry.html8
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_list.js42
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_page.js36
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_types.js15
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.html6
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.js17
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.html2
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.js17
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.js5
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html26
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html6
-rw-r--r--chromium/chrome/browser/resources/settings/compiled_resources2.gyp5
-rw-r--r--chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp18
-rw-r--r--chromium/chrome/browser/resources/settings/controls/controlled_button.html9
-rw-r--r--chromium/chrome/browser/resources/settings/controls/controlled_button.js14
-rw-r--r--chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html106
-rw-r--r--chromium/chrome/browser/resources/settings/controls/controlled_radio_button.js57
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.js3
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_checkbox.html13
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html16
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js13
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_idle_load.html (renamed from chromium/chrome/browser/resources/settings/controls/settings_idle_render.html)2
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_idle_load.js88
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_idle_render.js76
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_input.html32
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_input.js128
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_radio_group.js4
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_slider.html74
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_slider.js139
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html26
-rw-r--r--chromium/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/date_time_page/date_time_page.html12
-rw-r--r--chromium/chrome/browser/resources/settings/date_time_page/date_time_page.js28
-rw-r--r--chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.html14
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp2
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page.html9
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page.js21
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js2
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display.html130
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display.js146
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/keyboard.html30
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/layout_behavior.js8
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/pointers.html21
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/pointers.js29
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/power.html5
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/storage.html3
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/storage.js5
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/stylus.html11
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html5
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js4
-rw-r--r--chromium/chrome/browser/resources/settings/focus_row_behavior.html2
-rw-r--r--chromium/chrome/browser/resources/settings/focus_row_behavior.js172
-rw-r--r--chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.html1
-rw-r--r--chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.js56
-rw-r--r--chromium/chrome/browser/resources/settings/icons.html11
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp11
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html171
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js96
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html72
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js42
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.html1
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.js13
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html15
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js22
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html3
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_ip_config.html3
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_ip_config.js80
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html12
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_property_list.html4
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy.html56
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy.js61
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.js2
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html31
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js60
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html20
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js13
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html80
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.js81
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html44
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js80
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html48
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.js29
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages.js23
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages_page.html25
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages_page.js20
-rw-r--r--chromium/chrome/browser/resources/settings/lazy_load.html15
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/on_startup_page.html13
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html3
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.js9
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html8
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js7
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html6
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js24
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html66
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js2
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html28
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js26
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp3
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html35
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html30
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js14
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html30
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js35
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html59
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js63
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html5
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/change_picture.html2
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/change_picture.js4
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp81
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/fingerprint_browser_proxy.js10
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html16
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js50
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/import_data_dialog.html13
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/import_data_dialog.js18
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_screen.html106
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_screen.js178
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/manage_profile.html1
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/manage_profile.js32
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.js34
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html21
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js6
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.html248
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.js147
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html21
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js9
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.html28
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.html105
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.js26
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/user_list.html10
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/user_list.js28
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.html13
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.js16
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/users_page.html34
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/users_page.js5
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cloud_printers.html8
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html82
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js2
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html15
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_printers.html7
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_printers.js5
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/printing_page.html3
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/printing_page.js16
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html75
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js98
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html3
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_page.html8
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_page.js2
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html13
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js11
-rw-r--r--chromium/chrome/browser/resources/settings/route.html1
-rw-r--r--chromium/chrome/browser/resources/settings/route.js34
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/compiled_resources2.gyp4
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html7
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js6
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html23
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js9
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html13
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js3
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html26
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.js31
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.html8
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.js17
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.html41
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.js40
-rw-r--r--chromium/chrome/browser/resources/settings/search_settings.js124
-rw-r--r--chromium/chrome/browser/resources/settings/settings.html18
-rw-r--r--chromium/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp4
-rw-r--r--chromium/chrome/browser/resources/settings/settings_main/settings_main.html2
-rw-r--r--chromium/chrome/browser/resources/settings/settings_main/settings_main.js28
-rw-r--r--chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html5
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.js77
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html6
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js64
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html14
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html19
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.js4
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page_css.html8
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources.grd64
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd2
-rw-r--r--chromium/chrome/browser/resources/settings/settings_shared_css.html47
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html61
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js43
-rw-r--r--chromium/chrome/browser/resources/settings/settings_vars_css.html24
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.html8
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.js31
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/category_default_setting.html26
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js39
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html9
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js12
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp3
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/constants.js5
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html10
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js33
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/media_picker.html3
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/media_picker.js3
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/pdf_documents.html6
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html6
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data.html8
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data.js29
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js20
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.html2
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html1
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.html29
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.js228
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.js44
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js44
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/usb_devices.html4
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html14
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html82
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js56
-rw-r--r--chromium/chrome/browser/resources/settings/system_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/system_page/system_page.html19
-rw-r--r--chromium/chrome/browser/resources/settings/system_page/system_page.js38
-rw-r--r--chromium/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js8
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html30
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js10
-rw-r--r--chromium/chrome/browser/resources/snippets_internals.js4
-rw-r--r--chromium/chrome/browser/resources/uber/OWNERS2
-rwxr-xr-xchromium/chrome/browser/resources/unpack_pak.py14
-rw-r--r--chromium/chrome/browser/resources/vr_shell/OWNERS4
-rw-r--r--chromium/chrome/browser/resources/vr_shell/compiled_resources2.gyp37
-rw-r--r--chromium/chrome/browser/resources/vr_shell/vk.css124
-rw-r--r--chromium/chrome/browser/resources/vr_shell/vk.js437
-rw-r--r--chromium/chrome/browser/resources/vr_shell/vr_shell_ui.css311
-rw-r--r--chromium/chrome/browser/resources/vr_shell/vr_shell_ui.html109
-rw-r--r--chromium/chrome/browser/resources/vr_shell/vr_shell_ui.js1073
-rw-r--r--chromium/chrome/browser/resources/vr_shell/vr_shell_ui_api.js679
-rw-r--r--chromium/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js167
-rw-r--r--chromium/chrome/browser/resources/vulcanize.gni23
-rwxr-xr-xchromium/chrome/browser/resources/vulcanize_gn.py30
-rw-r--r--chromium/chrome/browser/resources/webapks/about_webapks.css6
-rw-r--r--chromium/chrome/browser/resources/webapks/about_webapks.js62
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_factory.cc3
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_message_filter_platform_mac_browsertest.cc21
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc23
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_service.cc4
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc16
-rw-r--r--chromium/chrome/browser/ui/BUILD.gn298
-rw-r--r--chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn3
-rw-r--r--chromium/chrome/browser/ui/libgtkui/BUILD.gn1
-rw-r--r--chromium/chrome/browser/ui/webui/engagement/site_engagement.mojom17
743 files changed, 15941 insertions, 19012 deletions
diff --git a/chromium/chrome/browser/BUILD.gn b/chromium/chrome/browser/BUILD.gn
index 7c663752f6e..bcf00f91d5c 100644
--- a/chromium/chrome/browser/BUILD.gn
+++ b/chromium/chrome/browser/BUILD.gn
@@ -10,6 +10,7 @@ import("//build/split_static_library.gni")
import("//chrome/common/features.gni")
import("//components/os_crypt/features.gni")
import("//components/spellcheck/spellcheck_build_features.gni")
+import("//device/vr/features.gni")
import("//extensions/features/features.gni")
import("//media/media_options.gni")
import("//net/features.gni")
@@ -54,9 +55,11 @@ if (is_win) {
# Use a static library here because many test binaries depend on this but don't
# require many files from it. This makes linking more efficient.
split_static_library("browser") {
- # Split into multiple static libraries on Windows official builds, where we
- # run into a 2GB max size limit.
- if (is_win && is_official_build) {
+ # Split into multiple static libraries on Windows builds. We have hit size
+ # limits on Windows official builds and on goma builds when symbol_level = 2
+ # is selected. Always splitting on Windows builds is simpler than trying to
+ # perfectly calculate the scenarios where it is required.
+ if (is_win) {
split_count = 5
} else {
split_count = 1
@@ -81,8 +84,6 @@ split_static_library("browser") {
"autocomplete/in_memory_url_index_factory.h",
"autocomplete/shortcuts_backend_factory.cc",
"autocomplete/shortcuts_backend_factory.h",
- "autocomplete/shortcuts_extensions_manager.cc",
- "autocomplete/shortcuts_extensions_manager.h",
"autofill/personal_data_manager_factory.cc",
"autofill/personal_data_manager_factory.h",
"autofill/risk_util.cc",
@@ -187,6 +188,10 @@ split_static_library("browser") {
"browsing_data/local_data_container.h",
"browsing_data/media_licenses_counter.cc",
"browsing_data/media_licenses_counter.h",
+ "browsing_data/site_data_counter.cc",
+ "browsing_data/site_data_counter.h",
+ "browsing_data/site_data_counting_helper.cc",
+ "browsing_data/site_data_counting_helper.h",
"browsing_data/site_data_size_collector.cc",
"browsing_data/site_data_size_collector.h",
"budget_service/budget_database.cc",
@@ -236,6 +241,8 @@ split_static_library("browser") {
"component_updater/component_updater_resource_throttle.h",
"component_updater/component_updater_utils.cc",
"component_updater/component_updater_utils.h",
+ "component_updater/cros_component_installer.cc",
+ "component_updater/cros_component_installer.h",
"component_updater/ev_whitelist_component_installer.cc",
"component_updater/ev_whitelist_component_installer.h",
"component_updater/file_type_policies_component_installer.cc",
@@ -256,8 +263,6 @@ split_static_library("browser") {
"component_updater/supervised_user_whitelist_installer.h",
"component_updater/sw_reporter_installer_win.cc",
"component_updater/sw_reporter_installer_win.h",
- "component_updater/swiftshader_component_installer.cc",
- "component_updater/swiftshader_component_installer.h",
"conflicts/module_database_win.cc",
"conflicts/module_database_win.h",
"conflicts/module_event_sink_impl_win.cc",
@@ -266,6 +271,8 @@ split_static_library("browser") {
"conflicts/module_info_util_win.h",
"conflicts/module_info_win.cc",
"conflicts/module_info_win.h",
+ "conflicts/module_inspector_win.cc",
+ "conflicts/module_inspector_win.h",
"content_settings/chrome_content_settings_utils.cc",
"content_settings/chrome_content_settings_utils.h",
"content_settings/cookie_settings_factory.cc",
@@ -314,10 +321,14 @@ split_static_library("browser") {
"dom_distiller/tab_utils.h",
"domain_reliability/service_factory.cc",
"domain_reliability/service_factory.h",
+ "doodle/doodle_service_factory.cc",
+ "doodle/doodle_service_factory.h",
"download/all_download_item_notifier.cc",
"download/all_download_item_notifier.h",
"download/chrome_download_manager_delegate.cc",
"download/chrome_download_manager_delegate.h",
+ "download/download_confirmation_reason.h",
+ "download/download_confirmation_result.h",
"download/download_crx_util_android.cc",
"download/download_file_picker.cc",
"download/download_file_picker.h",
@@ -351,6 +362,7 @@ split_static_library("browser") {
"download/download_target_determiner.cc",
"download/download_target_determiner.h",
"download/download_target_determiner_delegate.h",
+ "download/download_target_info.cc",
"download/download_target_info.h",
"download/download_ui_controller.cc",
"download/download_ui_controller.h",
@@ -371,6 +383,8 @@ split_static_library("browser") {
"engagement/site_engagement_service.h",
"engagement/site_engagement_service_factory.cc",
"engagement/site_engagement_service_factory.h",
+ "experiments/memory_ablation_experiment.cc",
+ "experiments/memory_ablation_experiment.h",
# Oh hey, all the cool browser/extensions files are hanging out in
# //chrome/browser/extensions/BUILD.gn
@@ -392,13 +406,11 @@ split_static_library("browser") {
"favicon/favicon_utils.h",
"favicon/large_icon_service_factory.cc",
"favicon/large_icon_service_factory.h",
- "features.cc",
- "features.h",
- "field_trial_recorder.cc",
- "field_trial_recorder.h",
"file_select_helper.cc",
"file_select_helper.h",
"file_select_helper_mac.mm",
+ "flag_descriptions.cc",
+ "flag_descriptions.h",
"fullscreen.h",
"fullscreen_chromeos.cc",
"fullscreen_mac.mm",
@@ -491,6 +503,8 @@ split_static_library("browser") {
"installable/installable_logging.h",
"installable/installable_manager.cc",
"installable/installable_manager.h",
+ "installable/installable_metrics.cc",
+ "installable/installable_metrics.h",
"internal_auth.cc",
"internal_auth.h",
"interstitials/chrome_controller_client.cc",
@@ -540,6 +554,7 @@ split_static_library("browser") {
"manifest/manifest_icon_downloader.h",
"manifest/manifest_icon_selector.cc",
"manifest/manifest_icon_selector.h",
+ "media/media_access_handler.cc",
"media/media_access_handler.h",
"media/media_device_id_salt.cc",
"media/media_device_id_salt.h",
@@ -559,8 +574,6 @@ split_static_library("browser") {
"media/webrtc/desktop_streams_registry.h",
"media/webrtc/media_capture_devices_dispatcher.cc",
"media/webrtc/media_capture_devices_dispatcher.h",
- "media/webrtc/media_permission.cc",
- "media/webrtc/media_permission.h",
"media/webrtc/media_stream_capture_indicator.cc",
"media/webrtc/media_stream_capture_indicator.h",
"media/webrtc/media_stream_device_permission_context.cc",
@@ -618,6 +631,10 @@ split_static_library("browser") {
"metrics/network_quality_estimator_provider_impl.h",
"metrics/perf/perf_provider_chromeos.cc",
"metrics/perf/perf_provider_chromeos.h",
+ "metrics/renderer_uptime_tracker.cc",
+ "metrics/renderer_uptime_tracker.h",
+ "metrics/renderer_uptime_web_contents_observer.cc",
+ "metrics/renderer_uptime_web_contents_observer.h",
"metrics/sampling_metrics_provider.cc",
"metrics/sampling_metrics_provider.h",
"metrics/subprocess_metrics_provider.cc",
@@ -765,8 +782,12 @@ split_static_library("browser") {
"ntp_tiles/chrome_most_visited_sites_factory.h",
"ntp_tiles/chrome_popular_sites_factory.cc",
"ntp_tiles/chrome_popular_sites_factory.h",
+ "offline_items_collection/offline_content_aggregator_factory.cc",
+ "offline_items_collection/offline_content_aggregator_factory.h",
"page_load_metrics/browser_page_track_decider.cc",
"page_load_metrics/browser_page_track_decider.h",
+ "page_load_metrics/experiments/delay_navigation_throttle.cc",
+ "page_load_metrics/experiments/delay_navigation_throttle.h",
"page_load_metrics/metrics_navigation_throttle.cc",
"page_load_metrics/metrics_navigation_throttle.h",
"page_load_metrics/metrics_web_contents_observer.cc",
@@ -781,6 +802,8 @@ split_static_library("browser") {
"page_load_metrics/observers/css_scanning_page_load_metrics_observer.h",
"page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc",
"page_load_metrics/observers/data_reduction_proxy_metrics_observer.h",
+ "page_load_metrics/observers/delay_navigation_page_load_metrics_observer.cc",
+ "page_load_metrics/observers/delay_navigation_page_load_metrics_observer.h",
"page_load_metrics/observers/document_write_page_load_metrics_observer.cc",
"page_load_metrics/observers/document_write_page_load_metrics_observer.h",
"page_load_metrics/observers/from_gws_page_load_metrics_observer.cc",
@@ -793,6 +816,8 @@ split_static_library("browser") {
"page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h",
"page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.cc",
"page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h",
+ "page_load_metrics/observers/media_page_load_metrics_observer.cc",
+ "page_load_metrics/observers/media_page_load_metrics_observer.h",
"page_load_metrics/observers/no_state_prefetch_page_load_metrics_observer.cc",
"page_load_metrics/observers/no_state_prefetch_page_load_metrics_observer.h",
"page_load_metrics/observers/omnibox_suggestion_used_page_load_metrics_observer.cc",
@@ -849,8 +874,6 @@ split_static_library("browser") {
"performance_monitor/process_metrics_history.h",
"permissions/chooser_context_base.cc",
"permissions/chooser_context_base.h",
- "permissions/delegation_tracker.cc",
- "permissions/delegation_tracker.h",
"permissions/permission_blacklist_client.cc",
"permissions/permission_blacklist_client.h",
"permissions/permission_context_base.cc",
@@ -960,10 +983,6 @@ split_static_library("browser") {
"prefs/pref_metrics_service.h",
"prefs/pref_service_syncable_util.cc",
"prefs/pref_service_syncable_util.h",
- "prefs/preferences_connection_manager.cc",
- "prefs/preferences_connection_manager.h",
- "prefs/preferences_service.cc",
- "prefs/preferences_service.h",
"prefs/profile_pref_store_manager.cc",
"prefs/profile_pref_store_manager.h",
"prefs/session_startup_pref.cc",
@@ -1107,6 +1126,8 @@ split_static_library("browser") {
"resources_util.h",
"safe_browsing/safe_browsing_tab_observer.cc",
"safe_browsing/safe_browsing_tab_observer.h",
+ "safe_browsing/srt_chrome_prompt_impl.cc",
+ "safe_browsing/srt_chrome_prompt_impl.h",
"safe_browsing/srt_client_info_win.cc",
"safe_browsing/srt_client_info_win.h",
"safe_browsing/srt_fetcher_win.cc",
@@ -1151,6 +1172,8 @@ split_static_library("browser") {
"search_engines/ui_thread_search_terms_data.h",
"search_engines/ui_thread_search_terms_data_android.cc",
"search_engines/ui_thread_search_terms_data_android.h",
+ "sessions/chrome_serialized_navigation_driver.cc",
+ "sessions/chrome_serialized_navigation_driver.h",
"sessions/chrome_tab_restore_service_client.cc",
"sessions/chrome_tab_restore_service_client.h",
"sessions/restore_on_startup_policy_handler.cc",
@@ -1207,6 +1230,8 @@ split_static_library("browser") {
"signin/signin_status_metrics_provider_chromeos.h",
"signin/signin_tracker_factory.cc",
"signin/signin_tracker_factory.h",
+ "signin/signin_util.cc",
+ "signin/signin_util.h",
"site_details.cc",
"site_details.h",
"speech/chrome_speech_recognition_manager_delegate.cc",
@@ -1256,6 +1281,12 @@ split_static_library("browser") {
"storage/storage_info_fetcher.h",
"subresource_filter/chrome_subresource_filter_client.cc",
"subresource_filter/chrome_subresource_filter_client.h",
+ "subresource_filter/navigation_throttle_util.cc",
+ "subresource_filter/navigation_throttle_util.h",
+ "subresource_filter/subresource_filter_content_settings_manager.cc",
+ "subresource_filter/subresource_filter_content_settings_manager.h",
+ "subresource_filter/subresource_filter_content_settings_manager_factory.cc",
+ "subresource_filter/subresource_filter_content_settings_manager_factory.h",
"sync/chrome_sync_client.cc",
"sync/chrome_sync_client.h",
"sync/glue/extensions_activity_monitor.cc",
@@ -1264,8 +1295,12 @@ split_static_library("browser") {
"sync/glue/sync_start_util.h",
"sync/profile_sync_service_factory.cc",
"sync/profile_sync_service_factory.h",
- "sync/sessions/notification_service_sessions_router.cc",
- "sync/sessions/notification_service_sessions_router.h",
+ "sync/sessions/sync_sessions_router_tab_helper.cc",
+ "sync/sessions/sync_sessions_router_tab_helper.h",
+ "sync/sessions/sync_sessions_web_contents_router.cc",
+ "sync/sessions/sync_sessions_web_contents_router.h",
+ "sync/sessions/sync_sessions_web_contents_router_factory.cc",
+ "sync/sessions/sync_sessions_web_contents_router_factory.h",
"sync/supervised_user_signin_manager_wrapper.cc",
"sync/supervised_user_signin_manager_wrapper.h",
"sync/sync_startup_tracker.cc",
@@ -1309,12 +1344,18 @@ split_static_library("browser") {
"tracing/crash_service_uploader.h",
"tracing/navigation_tracing.cc",
"tracing/navigation_tracing.h",
+ "translate/android/translate_utils.cc",
+ "translate/android/translate_utils.h",
"translate/chrome_translate_client.cc",
"translate/chrome_translate_client.h",
"translate/language_model_factory.cc",
"translate/language_model_factory.h",
"translate/translate_accept_languages_factory.cc",
"translate/translate_accept_languages_factory.h",
+ "translate/translate_ranker_factory.cc",
+ "translate/translate_ranker_factory.h",
+ "translate/translate_ranker_metrics_provider.cc",
+ "translate/translate_ranker_metrics_provider.h",
"translate/translate_service.cc",
"translate/translate_service.h",
"undo/bookmark_undo_service_factory.cc",
@@ -1351,6 +1392,8 @@ split_static_library("browser") {
"win/jumplist.h",
"win/jumplist_factory.cc",
"win/jumplist_factory.h",
+ "win/jumplist_file_util.cc",
+ "win/jumplist_file_util.h",
"win/jumplist_updater.cc",
"win/jumplist_updater.h",
"win/settings_app_monitor.cc",
@@ -1377,6 +1420,7 @@ split_static_library("browser") {
"//components/payments/core",
"//components/sync",
"//content/public/browser",
+ "//ipc",
"//sql",
]
deps = [
@@ -1407,6 +1451,7 @@ split_static_library("browser") {
"//components/captive_portal",
"//components/certificate_reporting",
"//components/certificate_transparency",
+ "//components/chrome_cleaner/public/interfaces",
"//components/cloud_devices/common",
"//components/component_updater",
"//components/content_settings/core/browser",
@@ -1422,6 +1467,7 @@ split_static_library("browser") {
"//components/device_event_log",
"//components/dom_distiller/content/browser",
"//components/domain_reliability",
+ "//components/doodle",
"//components/error_page/common",
"//components/favicon/content",
"//components/favicon/core",
@@ -1454,6 +1500,7 @@ split_static_library("browser") {
"//components/network_time",
"//components/ntp_snippets",
"//components/ntp_tiles",
+ "//components/offline_items_collection/core",
"//components/offline_pages/content/background_loader",
"//components/offline_pages/core",
"//components/offline_pages/core/background:background_offliner",
@@ -1467,11 +1514,13 @@ split_static_library("browser") {
"//components/password_manager/core/browser",
"//components/password_manager/core/common",
"//components/password_manager/sync/browser",
- "//components/payments/content:payment_app",
- "//components/payments/content:payment_request",
+ "//components/payments/content:mojom",
+ "//components/payments/content:mojom_payment_app",
+ "//components/physical_web/eddystone",
"//components/policy:generated",
"//components/policy/core/browser",
"//components/policy/proto",
+ "//components/precache/core",
"//components/prefs:prefs",
"//components/previews/core",
"//components/profile_metrics",
@@ -1520,7 +1569,6 @@ split_static_library("browser") {
"//components/url_formatter",
"//components/url_matcher",
"//components/user_prefs",
- "//components/user_prefs/tracked:user_prefs_tracked",
"//components/variations",
"//components/variations/field_trial_config",
"//components/variations/net",
@@ -1546,11 +1594,11 @@ split_static_library("browser") {
"//device/power_save_blocker",
"//device/usb/mojo",
"//device/usb/public/interfaces",
+ "//device/vr:features",
"//extensions/features",
"//gin:gin_features",
"//google_apis",
"//gpu/config",
- "//ipc",
"//media",
"//media:media_features",
"//media/midi",
@@ -1562,8 +1610,14 @@ split_static_library("browser") {
"//ppapi/features",
"//printing/features",
"//rlz/features",
- "//services/image_decoder/public/cpp",
- "//services/preferences/public/interfaces/",
+ "//services/data_decoder/public/cpp",
+ "//services/device/public/cpp:device_features",
+ "//services/identity:lib",
+ "//services/preferences/public/cpp",
+ "//services/preferences/public/cpp:service_main",
+ "//services/preferences/public/cpp/tracked",
+ "//services/preferences/public/interfaces",
+ "//services/preferences/tracked",
"//services/service_manager/public/cpp",
"//services/shape_detection/public/interfaces",
"//skia",
@@ -1618,6 +1672,10 @@ split_static_library("browser") {
"//net:net",
"//ui/vector_icons",
]
+ sources += [
+ "sync/sessions/browser_list_router_helper.cc",
+ "sync/sessions/browser_list_router_helper.h",
+ ]
}
if (is_chromeos && use_cras) {
@@ -1670,6 +1728,8 @@ split_static_library("browser") {
"accessibility/animation_policy_prefs.h",
"autocomplete/keyword_extensions_delegate_impl.cc",
"autocomplete/keyword_extensions_delegate_impl.h",
+ "autocomplete/shortcuts_extensions_manager.cc",
+ "autocomplete/shortcuts_extensions_manager.h",
"browsing_data/hosted_apps_counter.cc",
"browsing_data/hosted_apps_counter.h",
"content_settings/content_settings_internal_extension_provider.cc",
@@ -1718,6 +1778,8 @@ split_static_library("browser") {
"safe_browsing/settings_reset_prompt/settings_reset_prompt_model.h",
"safe_browsing/settings_reset_prompt/settings_reset_prompt_prefs_manager.cc",
"safe_browsing/settings_reset_prompt/settings_reset_prompt_prefs_manager.h",
+ "safe_browsing/srt_prompt_controller.cc",
+ "safe_browsing/srt_prompt_controller.h",
"search/hotword_audio_history_handler.cc",
"search/hotword_audio_history_handler.h",
"search/hotword_client.h",
@@ -1874,14 +1936,19 @@ split_static_library("browser") {
"media/cast_transport_host_filter.h",
]
}
- public_deps += [ "//chrome/browser/extensions" ]
- allow_circular_includes_from += [ "//chrome/browser/extensions" ]
+ public_deps += [
+ "//chrome/browser/apps",
+ "//chrome/browser/extensions",
+ ]
+ allow_circular_includes_from += [
+ "//chrome/browser/apps",
+ "//chrome/browser/extensions",
+ ]
deps += [
"//chrome/browser/sync_file_system/drive_backend:sync_file_system_drive_proto",
"//chrome/common/extensions/api",
"//chrome/common/extensions/api:api_registration",
"//chrome/common/extensions/api:extensions_features",
- "//components/cryptauth",
"//components/drive",
"//components/proximity_auth/ble",
"//extensions/components/javascript_dialog_extensions_client",
@@ -1945,7 +2012,6 @@ split_static_library("browser") {
}
if (enable_plugins) {
- # See also the plugin_installation_sources list below.
sources += [
"browsing_data/browsing_data_flash_lso_helper.cc",
"browsing_data/browsing_data_flash_lso_helper.h",
@@ -1977,6 +2043,10 @@ split_static_library("browser") {
"plugins/plugin_info_message_filter.h",
"plugins/plugin_infobar_delegates.cc",
"plugins/plugin_infobar_delegates.h",
+ "plugins/plugin_installer.cc",
+ "plugins/plugin_installer.h",
+ "plugins/plugin_installer_observer.cc",
+ "plugins/plugin_installer_observer.h",
"plugins/plugin_metadata.cc",
"plugins/plugin_metadata.h",
"plugins/plugin_observer.cc",
@@ -1993,6 +2063,8 @@ split_static_library("browser") {
"plugins/plugin_utils.h",
"plugins/plugins_field_trial.cc",
"plugins/plugins_field_trial.h",
+ "plugins/plugins_resource_service.cc",
+ "plugins/plugins_resource_service.h",
"renderer_host/pepper/chrome_browser_pepper_host_factory.cc",
"renderer_host/pepper/chrome_browser_pepper_host_factory.h",
"renderer_host/pepper/device_id_fetcher.cc",
@@ -2033,6 +2105,8 @@ split_static_library("browser") {
"safe_browsing/certificate_reporting_service.h",
"safe_browsing/certificate_reporting_service_factory.cc",
"safe_browsing/certificate_reporting_service_factory.h",
+ "safe_browsing/chrome_password_protection_service.cc",
+ "safe_browsing/chrome_password_protection_service.h",
"safe_browsing/notification_image_reporter.cc",
"safe_browsing/notification_image_reporter.h",
"safe_browsing/permission_reporter.cc",
@@ -2064,6 +2138,7 @@ split_static_library("browser") {
deps += [
"//chrome/browser/safe_browsing:chunk_proto",
"//chrome/common/safe_browsing:proto",
+ "//components/safe_browsing:csd_proto",
"//components/safe_browsing:safe_browsing",
"//components/safe_browsing/common:common",
"//components/safe_browsing/password_protection",
@@ -2098,7 +2173,9 @@ split_static_library("browser") {
"safe_browsing/incident_reporting/binary_integrity_analyzer.cc",
"safe_browsing/incident_reporting/binary_integrity_analyzer.h",
"safe_browsing/incident_reporting/binary_integrity_analyzer_mac.cc",
+ "safe_browsing/incident_reporting/binary_integrity_analyzer_mac.h",
"safe_browsing/incident_reporting/binary_integrity_analyzer_win.cc",
+ "safe_browsing/incident_reporting/binary_integrity_analyzer_win.h",
"safe_browsing/incident_reporting/binary_integrity_incident.cc",
"safe_browsing/incident_reporting/binary_integrity_incident.h",
"safe_browsing/incident_reporting/blacklist_load_analyzer.cc",
@@ -2231,6 +2308,8 @@ split_static_library("browser") {
"download/notification/download_notification.h",
"download/notification/download_notification_manager.cc",
"download/notification/download_notification_manager.h",
+ "media/chromeos_login_media_access_handler.cc",
+ "media/chromeos_login_media_access_handler.h",
"media/public_session_media_access_handler.cc",
"media/public_session_media_access_handler.h",
"media/public_session_tab_capture_access_handler.cc",
@@ -2254,6 +2333,8 @@ split_static_library("browser") {
"metrics/perf/windowed_incognito_observer.h",
"policy/default_geolocation_policy_handler.cc",
"policy/default_geolocation_policy_handler.h",
+ "prefs/active_profile_pref_service.cc",
+ "prefs/active_profile_pref_service.h",
"task_manager/providers/arc/arc_process_filter.cc",
"task_manager/providers/arc/arc_process_filter.h",
"task_manager/providers/arc/arc_process_task.cc",
@@ -2313,9 +2394,6 @@ split_static_library("browser") {
"//ui/views/mus",
]
}
- if (ui_compositor_image_transport) {
- deps += [ "//ui/gl" ]
- }
if (use_ash) {
# Cross-platform Ash sources.
@@ -2519,6 +2597,8 @@ split_static_library("browser") {
"profiles/profile_statistics_common.h",
"profiles/profile_statistics_factory.cc",
"profiles/profile_statistics_factory.h",
+ "signin/force_signin_verifier.cc",
+ "signin/force_signin_verifier.h",
"signin/signin_global_error.cc",
"signin/signin_global_error.h",
"signin/signin_global_error_factory.cc",
@@ -2564,6 +2644,8 @@ split_static_library("browser") {
"android/bookmarks/partner_bookmarks_shim.h",
"android/bottombar/overlay_panel_content.cc",
"android/bottombar/overlay_panel_content.h",
+ "android/browsing_data/browsing_data_bridge.cc",
+ "android/browsing_data/browsing_data_bridge.h",
"android/browsing_data/browsing_data_counter_bridge.cc",
"android/browsing_data/browsing_data_counter_bridge.h",
"android/browsing_data/url_filter_bridge.cc",
@@ -2573,6 +2655,7 @@ split_static_library("browser") {
"android/chrome_backup_agent.cc",
"android/chrome_backup_agent.h",
"android/chrome_backup_watcher.cc",
+ "android/chrome_backup_watcher.h",
"android/chrome_context_util.cc",
"android/chrome_context_util.h",
"android/chrome_feature_list.cc",
@@ -2589,8 +2672,6 @@ split_static_library("browser") {
"android/compositor/layer/content_layer.h",
"android/compositor/layer/contextual_search_layer.cc",
"android/compositor/layer/contextual_search_layer.h",
- "android/compositor/layer/crushed_sprite_layer.cc",
- "android/compositor/layer/crushed_sprite_layer.h",
"android/compositor/layer/layer.h",
"android/compositor/layer/overlay_panel_layer.cc",
"android/compositor/layer/overlay_panel_layer.h",
@@ -2606,6 +2687,10 @@ split_static_library("browser") {
"android/compositor/layer/toolbar_layer.h",
"android/compositor/layer_title_cache.cc",
"android/compositor/layer_title_cache.h",
+ "android/compositor/resources/resource_factory.cc",
+ "android/compositor/resources/resource_factory.h",
+ "android/compositor/resources/toolbar_resource.cc",
+ "android/compositor/resources/toolbar_resource.h",
"android/compositor/scene_layer/contextual_search_scene_layer.cc",
"android/compositor/scene_layer/contextual_search_scene_layer.h",
"android/compositor/scene_layer/reader_mode_scene_layer.cc",
@@ -2663,6 +2748,7 @@ split_static_library("browser") {
"android/devtools_server.cc",
"android/devtools_server.h",
"android/document/document_web_contents_delegate.cc",
+ "android/document/document_web_contents_delegate.h",
"android/dom_distiller/distiller_ui_handle_android.cc",
"android/dom_distiller/distiller_ui_handle_android.h",
"android/download/android_download_manager_duplicate_infobar_delegate.cc",
@@ -2683,12 +2769,14 @@ split_static_library("browser") {
"android/download/duplicate_download_infobar_delegate.h",
"android/download/intercept_download_resource_throttle.cc",
"android/download/intercept_download_resource_throttle.h",
- "android/download/mock_download_controller.cc",
- "android/download/mock_download_controller.h",
+ "android/download/items/offline_content_aggregator_factory_android.cc",
+ "android/download/items/offline_content_aggregator_factory_android.h",
"android/download/ui/thumbnail_provider.cc",
"android/download/ui/thumbnail_provider.h",
"android/favicon_helper.cc",
"android/favicon_helper.h",
+ "android/feature_engagement_tracker/feature_engagement_tracker_factory_android.cc",
+ "android/feature_engagement_tracker/feature_engagement_tracker_factory_android.h",
"android/feature_utilities.cc",
"android/feature_utilities.h",
"android/feedback/connectivity_checker.cc",
@@ -2742,8 +2830,6 @@ split_static_library("browser") {
"android/logo_bridge.h",
"android/logo_service.cc",
"android/logo_service.h",
- "android/media/media_throttle_infobar_delegate.cc",
- "android/media/media_throttle_infobar_delegate.h",
"android/metrics/launch_metrics.cc",
"android/metrics/launch_metrics.h",
"android/metrics/uma_session_stats.cc",
@@ -2819,10 +2905,14 @@ split_static_library("browser") {
"android/omnibox/autocomplete_controller_android.h",
"android/omnibox/omnibox_prerender.cc",
"android/omnibox/omnibox_prerender.h",
+ "android/partner_browser_customizations.cc",
+ "android/partner_browser_customizations.h",
"android/password_ui_view_android.cc",
"android/password_ui_view_android.h",
"android/payments/service_worker_payment_app_bridge.cc",
"android/payments/service_worker_payment_app_bridge.h",
+ "android/physical_web/eddystone_encoder_bridge.cc",
+ "android/physical_web/eddystone_encoder_bridge.h",
"android/physical_web/physical_web_data_source_android.cc",
"android/physical_web/physical_web_data_source_android.h",
"android/policy/policy_auditor.cc",
@@ -2833,8 +2923,12 @@ split_static_library("browser") {
"android/preferences/autofill/autofill_profile_bridge.h",
"android/preferences/browser_prefs_android.cc",
"android/preferences/browser_prefs_android.h",
+ "android/preferences/clipboard_android.cc",
+ "android/preferences/clipboard_android.h",
"android/preferences/pref_service_bridge.cc",
"android/preferences/pref_service_bridge.h",
+ "android/preferences/preferences_launcher.cc",
+ "android/preferences/preferences_launcher.h",
"android/preferences/website_preference_bridge.cc",
"android/preferences/website_preference_bridge.h",
"android/profiles/profile_downloader_android.cc",
@@ -2931,6 +3025,8 @@ split_static_library("browser") {
"android/webapps/webapp_registry.h",
"autofill/android/personal_data_manager_android.cc",
"autofill/android/personal_data_manager_android.h",
+ "autofill/android/phone_number_util_android.cc",
+ "autofill/android/phone_number_util_android.h",
"chrome_browser_field_trials_mobile.cc",
"chrome_browser_field_trials_mobile.h",
"dom_distiller/dom_distiller_service_factory_android.cc",
@@ -2941,6 +3037,8 @@ split_static_library("browser") {
"download/download_request_infobar_delegate_android.h",
"engagement/site_engagement_service_android.cc",
"engagement/site_engagement_service_android.h",
+ "feature_engagement_tracker/feature_engagement_tracker_factory.cc",
+ "feature_engagement_tracker/feature_engagement_tracker_factory.h",
"geolocation/geolocation_infobar_delegate_android.cc",
"geolocation/geolocation_infobar_delegate_android.h",
"history/android/android_history_provider_service.cc",
@@ -2957,6 +3055,8 @@ split_static_library("browser") {
"lifetime/application_lifetime_android.h",
"media/android/cdm/media_drm_credential_manager.cc",
"media/android/cdm/media_drm_credential_manager.h",
+ "media/android/cdm/media_drm_storage_factory.cc",
+ "media/android/cdm/media_drm_storage_factory.h",
"media/android/remote/record_cast_action.cc",
"media/android/remote/record_cast_action.h",
"media/android/remote/remote_media_player_bridge.cc",
@@ -2965,6 +3065,8 @@ split_static_library("browser") {
"media/android/remote/remote_media_player_manager.h",
"media/android/router/media_router_android.cc",
"media/android/router/media_router_android.h",
+ "media/android/router/media_router_android_bridge.cc",
+ "media/android/router/media_router_android_bridge.h",
"media/android/router/media_router_dialog_controller_android.cc",
"media/android/router/media_router_dialog_controller_android.h",
"media/midi_permission_infobar_delegate_android.cc",
@@ -3003,6 +3105,10 @@ split_static_library("browser") {
"password_manager/save_password_infobar_delegate_android.h",
"password_manager/update_password_infobar_delegate_android.cc",
"password_manager/update_password_infobar_delegate_android.h",
+ "payments/android/chrome_payments_jni_registrar.cc",
+ "payments/android/chrome_payments_jni_registrar.h",
+ "payments/android/journey_logger_android.cc",
+ "payments/android/journey_logger_android.h",
"permissions/grouped_permission_infobar_delegate_android.cc",
"permissions/grouped_permission_infobar_delegate_android.h",
"permissions/permission_dialog_delegate.cc",
@@ -3052,9 +3158,9 @@ split_static_library("browser") {
"//chrome/browser/android/webapk:proto",
"//components/cdm/browser",
"//components/data_usage/android",
+ "//components/feature_engagement_tracker",
"//components/payments/content/android",
"//components/precache/content",
- "//components/precache/core",
"//components/resources:components_resources",
"//components/safe_browsing_db",
"//components/toolbar",
@@ -3063,6 +3169,7 @@ split_static_library("browser") {
"//third_party/android_opengl/etc1",
"//third_party/android_tools:cpu_features",
"//third_party/libaddressinput:util",
+ "//third_party/libphonenumber",
"//third_party/smhasher:murmurhash2",
]
@@ -3111,6 +3218,10 @@ split_static_library("browser") {
"chrome_browser_main_posix.h",
"chrome_process_singleton.cc",
"chrome_process_singleton.h",
+ "cryptauth/chrome_cryptauth_service.cc",
+ "cryptauth/chrome_cryptauth_service.h",
+ "cryptauth/chrome_cryptauth_service_factory.cc",
+ "cryptauth/chrome_cryptauth_service_factory.h",
"custom_handlers/register_protocol_handler_permission_request.cc",
"custom_handlers/register_protocol_handler_permission_request.h",
"custom_home_pages_table_model.cc",
@@ -3310,8 +3421,6 @@ split_static_library("browser") {
"notifications/extension_welcome_notification_factory.h",
"notifications/fullscreen_notification_blocker.cc",
"notifications/fullscreen_notification_blocker.h",
- "notifications/google_now_notification_stats_collector.cc",
- "notifications/google_now_notification_stats_collector.h",
"notifications/message_center_notification_manager.cc",
"notifications/message_center_notification_manager.h",
"notifications/message_center_settings_controller.cc",
@@ -3336,8 +3445,6 @@ split_static_library("browser") {
"obsolete_system/obsolete_system_win.cc",
"pdf/pdf_extension_util.cc",
"pdf/pdf_extension_util.h",
- "power_usage_monitor/power_usage_monitor.cc",
- "power_usage_monitor/power_usage_monitor.h",
"process_singleton_modal_dialog_lock.cc",
"process_singleton_modal_dialog_lock.h",
"process_singleton_posix.cc",
@@ -3378,8 +3485,11 @@ split_static_library("browser") {
"repost_form_warning_controller.h",
"search/local_ntp_source.cc",
"search/local_ntp_source.h",
- "search/search_terms_tracker.cc",
- "search/search_terms_tracker.h",
+ "search/one_google_bar/one_google_bar_data.cc",
+ "search/one_google_bar/one_google_bar_data.h",
+ "search/one_google_bar/one_google_bar_fetcher.h",
+ "search/one_google_bar/one_google_bar_fetcher_impl.cc",
+ "search/one_google_bar/one_google_bar_fetcher_impl.h",
"signin/signin_promo.cc",
"signin/signin_promo.h",
"signin/signin_ui_util.cc",
@@ -3492,6 +3602,8 @@ split_static_library("browser") {
"//chrome/browser/policy:path_parser",
"//chrome/browser/profile_resetter:profile_reset_report_proto",
"//chrome/common/importer:interfaces",
+ "//components/cryptauth",
+ "//components/cryptauth/proto",
"//components/feedback",
"//components/web_modal",
"//device/battery",
@@ -3513,9 +3625,11 @@ split_static_library("browser") {
]
}
- if (enable_webvr) {
- deps += [ "android/vr_shell:vr_common" ]
- configs += [ "//third_party/gvr-android-sdk:libgvr_config" ]
+ if (enable_vr) {
+ if (is_android) {
+ deps += [ "android/vr_shell:vr_common" ]
+ configs += [ "//third_party/gvr-android-sdk:libgvr_config" ]
+ }
}
if (is_mac) {
@@ -3568,6 +3682,7 @@ split_static_library("browser") {
"//chrome/chrome_watcher:client",
"//chrome/common:metrics_constants_util_win",
"//chrome/common:version_header",
+ "//chrome/install_static:install_static_util",
"//chrome_elf:blacklist",
"//chrome_elf:constants",
"//chrome_elf:dll_hash",
@@ -3626,7 +3741,7 @@ split_static_library("browser") {
"payments/payment_request_factory.cc",
"payments/payment_request_factory.h",
]
- deps += [ "//components/payments/content:payment_request_impl" ]
+ deps += [ "//components/payments/content" ]
}
if (is_linux || is_win) {
@@ -3679,6 +3794,14 @@ split_static_library("browser") {
deps += [ "//third_party/libsecret" ]
}
+ if (enable_native_notifications) {
+ sources += [
+ "notifications/notification_platform_bridge_linux.cc",
+ "notifications/notification_platform_bridge_linux.h",
+ ]
+ deps += [ "//build/linux/libgio" ]
+ }
+
if (use_ozone) {
sources += [
"fullscreen_ozone.cc",
@@ -3687,17 +3810,6 @@ split_static_library("browser") {
}
}
- if (enable_plugin_installation) {
- sources += [
- "plugins/plugin_installer.cc",
- "plugins/plugin_installer.h",
- "plugins/plugin_installer_observer.cc",
- "plugins/plugin_installer_observer.h",
- "plugins/plugins_resource_service.cc",
- "plugins/plugins_resource_service.h",
- ]
- }
-
if (enable_app_list) {
deps += [ "//ui/app_list" ]
}
@@ -3737,10 +3849,10 @@ split_static_library("browser") {
"supervised_user/supervised_user_interstitial.h",
"supervised_user/supervised_user_navigation_observer.cc",
"supervised_user/supervised_user_navigation_observer.h",
+ "supervised_user/supervised_user_navigation_throttle.cc",
+ "supervised_user/supervised_user_navigation_throttle.h",
"supervised_user/supervised_user_pref_store.cc",
"supervised_user/supervised_user_pref_store.h",
- "supervised_user/supervised_user_resource_throttle.cc",
- "supervised_user/supervised_user_resource_throttle.h",
"supervised_user/supervised_user_service.cc",
"supervised_user/supervised_user_service.h",
"supervised_user/supervised_user_service_factory.cc",
@@ -3938,6 +4050,7 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/ChromeBackupWatcher.java",
"../android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java",
"../android/java/src/org/chromium/chrome/browser/ChromeHttpAuthHandler.java",
+ "../android/java/src/org/chromium/chrome/browser/ChromeVersionInfo.java",
"../android/java/src/org/chromium/chrome/browser/DevToolsServer.java",
"../android/java/src/org/chromium/chrome/browser/IntentHelper.java",
"../android/java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java",
@@ -3960,6 +4073,7 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/autofill/CreditCardScannerBridge.java",
"../android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java",
"../android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java",
+ "../android/java/src/org/chromium/chrome/browser/autofill/PhoneNumberUtil.java",
"../android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java",
"../android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java",
"../android/java/src/org/chromium/chrome/browser/browsing_data/UrlFilterBridge.java",
@@ -3969,6 +4083,7 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java",
"../android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java",
"../android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java",
+ "../android/java/src/org/chromium/chrome/browser/compositor/resources/ResourceFactory.java",
"../android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java",
"../android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ReaderModeSceneLayer.java",
"../android/java/src/org/chromium/chrome/browser/compositor/scene_layer/SceneLayer.java",
@@ -3978,6 +4093,7 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java",
"../android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java",
"../android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java",
+ "../android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java",
"../android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java",
"../android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java",
"../android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java",
@@ -3996,10 +4112,12 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadItem.java",
"../android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
+ "../android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorFactory.java",
"../android/java/src/org/chromium/chrome/browser/download/ui/ThumbnailProviderImpl.java",
"../android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java",
"../android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java",
"../android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java",
+ "../android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/FeatureEngagementTrackerFactory.java",
"../android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java",
"../android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java",
"../android/java/src/org/chromium/chrome/browser/findinpage/FindInPageBridge.java",
@@ -4022,7 +4140,9 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java",
"../android/java/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBar.java",
"../android/java/src/org/chromium/chrome/browser/infobar/SimpleConfirmInfoBarBuilder.java",
+ "../android/java/src/org/chromium/chrome/browser/infobar/SubresourceFilterExperimentalInfoBar.java",
"../android/java/src/org/chromium/chrome/browser/infobar/SubresourceFilterInfoBar.java",
+ "../android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java",
"../android/java/src/org/chromium/chrome/browser/infobar/TranslateInfoBar.java",
"../android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java",
"../android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsSettings.java",
@@ -4061,24 +4181,28 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java",
"../android/java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java",
"../android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
- "../android/java/src/org/chromium/chrome/browser/pageinfo/CertificateChainHelper.java",
- "../android/java/src/org/chromium/chrome/browser/pageinfo/CertificateViewer.java",
- "../android/java/src/org/chromium/chrome/browser/pageinfo/ConnectionInfoPopup.java",
- "../android/java/src/org/chromium/chrome/browser/pageinfo/WebsiteSettingsPopup.java",
+ "../android/java/src/org/chromium/chrome/browser/page_info/CertificateChainHelper.java",
+ "../android/java/src/org/chromium/chrome/browser/page_info/CertificateViewer.java",
+ "../android/java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java",
+ "../android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java",
"../android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java",
+ "../android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java",
"../android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java",
"../android/java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java",
"../android/java/src/org/chromium/chrome/browser/password_manager/Credential.java",
- "../android/java/src/org/chromium/chrome/browser/payments/PaymentValidator.java",
+ "../android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java",
"../android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java",
"../android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogController.java",
"../android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogDelegate.java",
+ "../android/java/src/org/chromium/chrome/browser/physicalweb/PhysicalWebBroadcastService.java",
"../android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java",
"../android/java/src/org/chromium/chrome/browser/policy/PolicyAuditor.java",
"../android/java/src/org/chromium/chrome/browser/precache/PrecacheLauncher.java",
"../android/java/src/org/chromium/chrome/browser/preferences/LocationSettings.java",
"../android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java",
+ "../android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java",
"../android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfileBridge.java",
+ "../android/java/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataBridge.java",
"../android/java/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataCounterBridge.java",
"../android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java",
"../android/java/src/org/chromium/chrome/browser/prerender/ExternalPrerenderHandler.java",
@@ -4099,6 +4223,7 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/snackbar/smartlockautosignin/AutoSigninSnackbarController.java",
"../android/java/src/org/chromium/chrome/browser/ssl/SecurityStateModel.java",
"../android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java",
+ "../android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java",
"../android/java/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProvider.java",
"../android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java",
"../android/java/src/org/chromium/chrome/browser/sync/SyncSessionsMetrics.java",
@@ -4106,7 +4231,6 @@ if (is_android) {
"../android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java",
"../android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java",
"../android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
- "../android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java",
"../android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java",
"../android/java/src/org/chromium/chrome/browser/util/ChromeContextUtil.java",
"../android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java",
@@ -4168,7 +4292,6 @@ proto_library("resource_prefetch_predictor_proto") {
grit("resources") {
source = "browser_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
if (enable_hangout_services_extension) {
@@ -4195,7 +4318,7 @@ grit("resources") {
# Depend only on the generated mojo bindings since we read the .mojom.js
# file, rather than the whole mojo target which will link the C++ bindings.
"//chrome/app:chrome_content_manifest_overlays",
- "//chrome/browser/ui/webui/engagement:mojo_bindings__generator",
+ "//chrome/browser/engagement:mojo_bindings__generator",
"//chrome/browser/ui/webui/omnibox:mojo_bindings__generator",
"//chrome/browser/ui/webui/usb_internals:mojo_bindings__generator",
"//device/bluetooth/public/interfaces:experimental_interfaces__generator",
@@ -4267,8 +4390,8 @@ static_library("test_support") {
"browsing_data/mock_browsing_data_media_license_helper.h",
"browsing_data/mock_browsing_data_quota_helper.cc",
"browsing_data/mock_browsing_data_quota_helper.h",
- "browsing_data/mock_browsing_data_remover.cc",
- "browsing_data/mock_browsing_data_remover.h",
+ "browsing_data/mock_browsing_data_remover_delegate.cc",
+ "browsing_data/mock_browsing_data_remover_delegate.h",
"browsing_data/mock_browsing_data_service_worker_helper.cc",
"browsing_data/mock_browsing_data_service_worker_helper.h",
"download/download_test_file_activity_observer.cc",
@@ -4283,6 +4406,8 @@ static_library("test_support") {
"net/url_request_mock_util.h",
"notifications/notification_test_util.cc",
"notifications/notification_test_util.h",
+ "notifications/stub_notification_display_service.cc",
+ "notifications/stub_notification_display_service.h",
"notifications/stub_notification_platform_bridge.cc",
"notifications/stub_notification_platform_bridge.h",
"policy/test/local_policy_test_server.cc",
@@ -4333,23 +4458,29 @@ static_library("test_support") {
"//components/password_manager/core/browser:test_support",
"//components/policy/core/browser:test_support",
"//components/prefs:test_support",
+ "//components/safe_browsing:csd_proto",
"//components/search_engines:test_support",
"//components/sessions:test_support",
"//components/subresource_filter/core/browser:test_support",
"//components/subresource_filter/core/common:test_support",
"//components/sync_preferences:test_support",
"//components/ukm:test_support",
- "//components/user_prefs/tracked:user_prefs_tracked_test_support",
"//content/test:test_support",
"//google_apis:test_support",
"//net:test_support",
+ "//services/preferences/public/cpp/tracked:test_support",
"//skia",
"//testing/gmock",
"//testing/gtest",
"//ui/gfx",
]
- if (!is_android) {
+ if (is_android) {
+ sources += [
+ "android/download/mock_download_controller.cc",
+ "android/download/mock_download_controller.h",
+ ]
+ } else {
sources += [
"chooser_controller/mock_chooser_controller.cc",
"chooser_controller/mock_chooser_controller.h",
@@ -4502,8 +4633,6 @@ static_library("test_support_ui") {
visibility = [ "//chrome/test:test_support_ui" ]
sources = [
- "password_manager/password_manager_test_base.cc",
- "password_manager/password_manager_test_base.h",
"signin/token_revoker_test_utils.cc",
"signin/token_revoker_test_utils.h",
"ui/webui/signin/login_ui_test_utils.cc",
@@ -4512,6 +4641,8 @@ static_library("test_support_ui") {
if (!is_android) {
sources += [
+ "password_manager/password_manager_test_base.cc",
+ "password_manager/password_manager_test_base.h",
"ui/webui/web_ui_test_handler.cc",
"ui/webui/web_ui_test_handler.h",
]
@@ -4519,6 +4650,10 @@ static_library("test_support_ui") {
configs += [ "//build/config:precompiled_headers" ]
+ public_deps = [
+ "//net:test_support",
+ ]
+
deps = [
"//components/metrics:test_support",
"//components/password_manager/content/common:mojo_interfaces",
@@ -4558,7 +4693,7 @@ if (enable_pepper_cdms) {
}
}
-service_manifest("preferences_manifest") {
- name = "preferences"
- source = "prefs/preferences_manifest.json"
+service_manifest("preferences_forwarder_manifest") {
+ name = "preferences_forwarder"
+ source = "prefs/forwarder_manifest.json"
}
diff --git a/chromium/chrome/browser/android/vr_shell/BUILD.gn b/chromium/chrome/browser/android/vr_shell/BUILD.gn
index fd7b38e99d8..e43695690b9 100644
--- a/chromium/chrome/browser/android/vr_shell/BUILD.gn
+++ b/chromium/chrome/browser/android/vr_shell/BUILD.gn
@@ -4,9 +4,10 @@
import("//build/config/android/rules.gni")
import("//chrome/common/features.gni")
+import("//device/vr/features.gni")
import("//testing/test.gni")
-assert(enable_webvr)
+assert(enable_vr)
if (current_cpu == "arm" || current_cpu == "arm64") {
static_library("vr_common") {
@@ -19,18 +20,36 @@ if (current_cpu == "arm" || current_cpu == "arm64") {
"animation.h",
"easing.cc",
"easing.h",
+ "fps_meter.cc",
+ "fps_meter.h",
+ "gltf_asset.cc",
+ "gltf_asset.h",
+ "gltf_parser.cc",
+ "gltf_parser.h",
+ "mailbox_to_surface_bridge.cc",
+ "mailbox_to_surface_bridge.h",
"non_presenting_gvr_delegate.cc",
"non_presenting_gvr_delegate.h",
- "ui_elements.cc",
- "ui_elements.h",
+ "textures/insecure_content_permanent_texture.cc",
+ "textures/insecure_content_permanent_texture.h",
+ "textures/insecure_content_transient_texture.cc",
+ "textures/insecure_content_transient_texture.h",
+ "textures/ui_texture.cc",
+ "textures/ui_texture.h",
+ "ui_element.cc",
+ "ui_element.h",
"ui_interface.cc",
"ui_interface.h",
"ui_scene.cc",
"ui_scene.h",
+ "ui_scene_manager.cc",
+ "ui_scene_manager.h",
"vr_compositor.cc",
"vr_compositor.h",
"vr_controller.cc",
"vr_controller.h",
+ "vr_controller_model.cc",
+ "vr_controller_model.h",
"vr_gesture.h",
"vr_gl_thread.cc",
"vr_gl_thread.h",
@@ -38,10 +57,6 @@ if (current_cpu == "arm" || current_cpu == "arm64") {
"vr_gl_util.h",
"vr_input_manager.cc",
"vr_input_manager.h",
- "vr_math.cc",
- "vr_math.h",
- "vr_omnibox.cc",
- "vr_omnibox.h",
"vr_shell.cc",
"vr_shell.h",
"vr_shell_delegate.cc",
@@ -56,10 +71,6 @@ if (current_cpu == "arm" || current_cpu == "arm64") {
"vr_web_contents_observer.h",
]
- if (enable_vr_shell_ui_dev) {
- defines += [ "ENABLE_VR_SHELL_UI_DEV" ]
- }
-
deps = [
":vr_shell_jni_headers",
"//base",
@@ -72,17 +83,20 @@ if (current_cpu == "arm" || current_cpu == "arm64") {
"//content/public/common",
"//device/gamepad",
"//device/vr",
+ "//services/ui/public/cpp/gpu",
"//ui/android",
"//ui/base",
"//ui/display",
"//ui/gl",
"//ui/gl/init",
+ "//ui/vector_icons",
]
libs = [
"//third_party/gvr-android-sdk/libgvr_shim_static_${current_cpu}.a",
"android",
]
+
configs += [ "//third_party/gvr-android-sdk:libgvr_config" ]
}
@@ -95,10 +109,14 @@ if (current_cpu == "arm" || current_cpu == "arm64") {
}
}
-if (enable_webvr) {
+if (enable_vr) {
test("vr_shell_unittests") {
sources = [
- "ui_elements_unittest.cc",
+ "fps_meter_unittest.cc",
+ "gltf_parser_unittest.cc",
+ "test/paths.cc",
+ "test/paths.h",
+ "ui_element_unittest.cc",
"ui_scene_unittest.cc",
]
@@ -111,5 +129,16 @@ if (enable_webvr) {
"//third_party/WebKit/public:blink",
"//ui/gfx/geometry",
]
+
+ # Ensure libgvr static library appears before gcc library in linking order.
+ # See https://crbug.com/704305 for details.
+ libs =
+ [ "//third_party/gvr-android-sdk/libgvr_shim_static_${current_cpu}.a" ]
+
+ data = [
+ "test/data/sample_inline.gltf",
+ "test/data/sample_external.gltf",
+ "test/data/sample.bin",
+ ]
}
}
diff --git a/chromium/chrome/browser/apps/BUILD.gn b/chromium/chrome/browser/apps/BUILD.gn
new file mode 100644
index 00000000000..c56220320e1
--- /dev/null
+++ b/chromium/chrome/browser/apps/BUILD.gn
@@ -0,0 +1,56 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//extensions/features/features.gni")
+
+assert(enable_extensions)
+
+source_set("apps") {
+ sources = [
+ "app_launch_for_metro_restart_win.cc",
+ "app_launch_for_metro_restart_win.h",
+ "app_load_service.cc",
+ "app_load_service.h",
+ "app_load_service_factory.cc",
+ "app_load_service_factory.h",
+ "app_url_redirector.cc",
+ "app_url_redirector.h",
+ "app_window_registry_util.cc",
+ "app_window_registry_util.h",
+ "browser_context_keyed_service_factories.cc",
+ "browser_context_keyed_service_factories.h",
+ "install_chrome_app.cc",
+ "install_chrome_app.h",
+ "shortcut_manager.cc",
+ "shortcut_manager.h",
+ "shortcut_manager_factory.cc",
+ "shortcut_manager_factory.h",
+ ]
+
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
+ public_deps = [
+ "//apps",
+ ]
+
+ deps = [
+ "//chrome/app:command_ids",
+ "//chrome/browser/extensions",
+ "//chrome/browser/media/router/discovery",
+ "//chrome/common",
+ "//components/crx_file",
+ "//components/keyed_service/content",
+ "//components/navigation_interception",
+ "//components/pref_registry",
+ "//content/public/browser",
+ "//content/public/common",
+ "//extensions/browser",
+ "//extensions/common",
+ "//extensions/common/api",
+ "//net",
+ "//ui/gfx",
+ ]
+
+ allow_circular_includes_from = [ "//chrome/browser/extensions" ]
+}
diff --git a/chromium/chrome/browser/browser_resources.grd b/chromium/chrome/browser/browser_resources.grd
index c42abcaaa62..65959b76c08 100644
--- a/chromium/chrome/browser/browser_resources.grd
+++ b/chromium/chrome/browser/browser_resources.grd
@@ -13,6 +13,16 @@
<structure name="IDR_APP_LIST_START_PAGE_HTML" file="resources\app_list\start_page.html" flattenhtml="true" type="chrome_html" />
<structure name="IDR_APP_LIST_START_PAGE_JS" file="resources\app_list\start_page.js" flattenhtml="true" type="chrome_html" />
</if>
+ <if expr="is_win">
+ <structure name="IDR_CLEANUP_TOOL_BROWSER_PROXY_HTML" file="resources\cleanup_tool\cleanup_browser_proxy.html" type="chrome_html" />
+ <structure name="IDR_CLEANUP_TOOL_BROWSER_PROXY_JS" file="resources\cleanup_tool\cleanup_browser_proxy.js" type="chrome_html" />
+ <structure name="IDR_CLEANUP_TOOL_ICONS_HTML" file="resources\cleanup_tool\icons.html" type="chrome_html" />
+ <structure name="IDR_CLEANUP_TOOL_MANAGER_HTML" file="resources\cleanup_tool\manager.html" type="chrome_html" />
+ <structure name="IDR_CLEANUP_TOOL_MANAGER_JS" file="resources\cleanup_tool\manager.js" type="chrome_html" />
+ <structure name="IDR_CLEANUP_TOOL_HTML" file="resources\cleanup_tool\cleanup.html" type="chrome_html" />
+ <structure name="IDR_CLEANUP_TOOL_TOOLBAR_HTML" file="resources\cleanup_tool\toolbar.html" type="chrome_html" />
+ <structure name="IDR_CLEANUP_TOOL_TOOLBAR_JS" file="resources\cleanup_tool\toolbar.js" type="chrome_html" />
+ </if>
<if expr="enable_extensions">
<structure name="IDR_EXTENSIONS_HTML" file="resources\extensions\extensions.html" flattenhtml="true" type="chrome_html" />
<structure name="IDR_MD_EXTENSIONS_EXTENSIONS_HTML" file="resources\md_extensions\extensions.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
@@ -192,8 +202,10 @@
<include name="IDR_MD_EXTENSIONS_ITEM_JS" file="resources\md_extensions\item.js" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_ITEM_LIST_HTML" file="resources\md_extensions\item_list.html" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_ITEM_LIST_JS" file="resources\md_extensions\item_list.js" type="BINDATA" />
- <include name="IDR_MD_EXTENSIONS_ITEM_SOURCE_HTML" file="resources\md_extensions\item_source.html" type="BINDATA" />
- <include name="IDR_MD_EXTENSIONS_ITEM_SOURCE_JS" file="resources\md_extensions\item_source.js" type="BINDATA" />
+ <include name="IDR_MD_EXTENSIONS_ITEM_UTIL_HTML" file="resources\md_extensions\item_util.html" type="BINDATA" />
+ <include name="IDR_MD_EXTENSIONS_ITEM_UTIL_JS" file="resources\md_extensions\item_util.js" type="BINDATA" />
+ <include name="IDR_MD_EXTENSIONS_LOAD_ERROR_HTML" file="resources\md_extensions\load_error.html" type="BINDATA" />
+ <include name="IDR_MD_EXTENSIONS_LOAD_ERROR_JS" file="resources\md_extensions\load_error.js" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_OPTIONS_DIALOG_HTML" file="resources\md_extensions\options_dialog.html" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_OPTIONS_DIALOG_JS" file="resources\md_extensions\options_dialog.js" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_PACK_DIALOG_HTML" file="resources\md_extensions\pack_dialog.html" type="BINDATA" />
@@ -204,6 +216,8 @@
<include name="IDR_MD_EXTENSIONS_SHORTCUT_INPUT_JS" file="resources\md_extensions\shortcut_input.js" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_SIDEBAR_HTML" file="resources\md_extensions\sidebar.html" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_SIDEBAR_JS" file="resources\md_extensions\sidebar.js" type="BINDATA" />
+ <include name="IDR_MD_EXTENSIONS_TOOLBAR_HTML" file="resources\md_extensions\toolbar.html" type="BINDATA" />
+ <include name="IDR_MD_EXTENSIONS_TOOLBAR_JS" file="resources\md_extensions\toolbar.js" type="BINDATA" />
<include name="IDR_MD_EXTENSIONS_STRINGS_HTML" file="resources\md_extensions\strings.html" type="BINDATA" />
</if>
<include name="IDR_FEEDBACK_MANIFEST" file="resources\feedback\manifest.json" type="BINDATA" />
@@ -221,15 +235,6 @@
<include name="IDR_SNIPPETS_INTERNALS_HTML" file="resources\snippets_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_SNIPPETS_INTERNALS_CSS" file="resources\snippets_internals.css" compress="gzip" type="BINDATA" />
<include name="IDR_SNIPPETS_INTERNALS_JS" file="resources\snippets_internals.js" compress="gzip" type="BINDATA" />
- <if expr="enable_webvr">
- <include name="IDR_VR_SHELL_UI_HTML" file="resources\vr_shell\vr_shell_ui.html" allowexternalscript="true" flattenhtml="true" compress="gzip" type="BINDATA" />
- <include name="IDR_VR_SHELL_UI_CSS" file="resources\vr_shell\vr_shell_ui.css" compress="gzip" type="BINDATA" />
- <include name="IDR_VR_SHELL_UI_JS" file="resources\vr_shell\vr_shell_ui.js" compress="gzip" type="BINDATA" />
- <include name="IDR_VR_SHELL_UI_API_JS" file="resources\vr_shell\vr_shell_ui_api.js" compress="gzip" type="BINDATA" />
- <include name="IDR_VR_SHELL_UI_SCENE_JS" file="resources\vr_shell\vr_shell_ui_scene.js" compress="gzip" type="BINDATA" />
- <include name="IDR_VR_SHELL_UI_VK_CSS" file="resources\vr_shell\vk.css" compress="gzip" type="BINDATA" />
- <include name="IDR_VR_SHELL_UI_VK_JS" file="resources\vr_shell\vk.js" compress="gzip" type="BINDATA" />
- </if>
</if>
<include name="IDR_SUPERVISED_USER_INTERNALS_HTML" file="resources\supervised_user_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_SUPERVISED_USER_INTERNALS_CSS" file="resources\supervised_user_internals.css" compress="gzip" type="BINDATA" />
@@ -253,9 +258,19 @@
<if expr="not is_android and not is_ios">
<!-- MD Bookmarks. -->
+ <include name="IDR_MD_BOOKMARKS_ACTIONS_HTML" file="resources\md_bookmarks\actions.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_ACTIONS_JS" file="resources\md_bookmarks\actions.js" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_API_LISTENER_HTML" file="resources\md_bookmarks\api_listener.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_API_LISTENER_JS" file="resources\md_bookmarks\api_listener.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_APP_HTML" file="resources\md_bookmarks\app.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_APP_JS" file="resources\md_bookmarks\app.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_BOOKMARKS_HTML" file="resources\md_bookmarks\bookmarks.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_CONSTANTS_HTML" file="resources\md_bookmarks\constants.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_CONSTANTS_JS" file="resources\md_bookmarks\constants.js" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_DND_MANAGER_HTML" file="resources\md_bookmarks\dnd_manager.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_DND_MANAGER_JS" file="resources\md_bookmarks\dnd_manager.js" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_HTML" file="resources\md_bookmarks\edit_dialog.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_EDIT_DIALOG_JS" file="resources\md_bookmarks\edit_dialog.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_FOLDER_NODE_HTML" file="resources\md_bookmarks\folder_node.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_FOLDER_NODE_JS" file="resources\md_bookmarks\folder_node.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_ICONS_HTML" file="resources\md_bookmarks\icons.html" type="BINDATA" />
@@ -263,16 +278,22 @@
<include name="IDR_MD_BOOKMARKS_ITEM_JS" file="resources\md_bookmarks\item.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_LIST_HTML" file="resources\md_bookmarks\list.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_LIST_JS" file="resources\md_bookmarks\list.js" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_REDUCERS_HTML" file="resources\md_bookmarks\reducers.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_REDUCERS_JS" file="resources\md_bookmarks\reducers.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_ROUTER_HTML" file="resources\md_bookmarks\router.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_ROUTER_JS" file="resources\md_bookmarks\router.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_SHARED_STYLE_HTML" file="resources\md_bookmarks\shared_style.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_SHARED_VARS_HTML" file="resources\md_bookmarks\shared_vars.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_SIDEBAR_HTML" file="resources\md_bookmarks\sidebar.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_SIDEBAR_JS" file="resources\md_bookmarks\sidebar.js" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_HTML" file="resources\md_bookmarks\store_client.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_JS" file="resources\md_bookmarks\store_client.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_STORE_HTML" file="resources\md_bookmarks\store.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_STORE_JS" file="resources\md_bookmarks\store.js" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_TOOLBAR_HTML" file="resources\md_bookmarks\toolbar.html" type="BINDATA" />
<include name="IDR_MD_BOOKMARKS_TOOLBAR_JS" file="resources\md_bookmarks\toolbar.js" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_UTIL_HTML" file="resources\md_bookmarks\util.html" type="BINDATA" />
+ <include name="IDR_MD_BOOKMARKS_UTIL_JS" file="resources\md_bookmarks\util.js" type="BINDATA" />
<!-- MD History. -->
<include name="IDR_MD_HISTORY_CONSTANTS_HTML" file="resources\md_history\constants.html" type="BINDATA" />
@@ -421,12 +442,9 @@
</if>
<include name="IDR_PROFILER_HTML" file="resources\profiler\profiler.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_PROFILER_JS" file="resources\profiler\profiler.js" flattenhtml="true" type="BINDATA" compress="gzip" />
- <if expr="enable_google_now">
- <include name="IDR_GOOGLE_NOW_MANIFEST" file="resources\google_now\manifest.json" type="BINDATA" />
- </if>
<include name="IDR_SITE_ENGAGEMENT_HTML" file="resources\engagement\site_engagement.html" flattenhtml="true" type="BINDATA" compress="gzip" />
<include name="IDR_SITE_ENGAGEMENT_JS" file="resources\engagement\site_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SITE_ENGAGEMENT_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\engagement\site_engagement.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_SITE_ENGAGEMENT_MOJO_JS" file="${root_gen_dir}\chrome\browser\engagement\site_engagement_details.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_URL_MOJO_JS" file="${root_gen_dir}\url\mojo\url.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_SYNC_CONFIRMATION_CSS" file="resources\signin\sync_confirmation\sync_confirmation.css" type="BINDATA" />
<include name="IDR_SYNC_CONFIRMATION_HTML" file="resources\signin\sync_confirmation\sync_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
@@ -639,6 +657,10 @@
<if expr="not is_android and not is_ios">
<include name="IDR_SSL_ERROR_ASSISTANT_PB" file="${root_gen_dir}/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.pb" use_base_dir="false" type="BINDATA" />
</if>
+ <if expr="is_android or is_linux">
+ <include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals.js" type="BINDATA" compress="gzip" />
+ </if>
</includes>
</release>
</grit>
diff --git a/chromium/chrome/browser/chrome_content_browser_manifest_overlay.json b/chromium/chrome/browser/chrome_content_browser_manifest_overlay.json
index 7444d5b35cd..8ff62935810 100644
--- a/chromium/chrome/browser/chrome_content_browser_manifest_overlay.json
+++ b/chromium/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -8,7 +8,6 @@
"autofill::mojom::AutofillDriver",
"autofill::mojom::PasswordManagerDriver",
"chrome::mojom::NetBenchmarking",
- "chrome::mojom::FieldTrialRecorder",
"extensions::StashService",
"metrics::mojom::LeakDetector",
"mojom::ModuleEventSink",
@@ -24,11 +23,12 @@
"requires": {
"accessibility_autoclick": [ "ash:autoclick" ],
"ash": [ "ash" ],
- "image_decoder": [ "decode" ],
+ "identity": [ "identity_manager" ],
"nacl_broker": [ "browser" ],
"nacl_loader": [ "browser" ],
- "preferences": [ "preferences_manager" ],
- "ui": [ "display_controller", "ime_registrar" ]
+ "preferences_forwarder": [ "pref_client" ],
+ "preferences": [ "pref_client", "pref_control" ],
+ "ui": [ "display_controller", "ime_registrar", "window_manager" ]
}
},
"navigation:frame": {
@@ -36,9 +36,11 @@
"renderer": [
"autofill::mojom::AutofillDriver",
"autofill::mojom::PasswordManagerDriver",
+ "blink::mojom::InstalledAppProvider",
"blink::mojom::ShareService",
"bluetooth::mojom::AdapterFactory",
"chrome::mojom::PrerenderCanceler",
+ "chrome::mojom::OpenSearchDocumentDescriptionHandler",
"device::usb::ChooserService",
"device::usb::DeviceManager",
"contextual_search::mojom::ContextualSearchJsApiService",
@@ -53,7 +55,7 @@
// TODO(beng): These should be moved to a separate capability.
"mojom::OmniboxPageHandler",
"mojom::PluginsPageHandler",
- "mojom::SiteEngagementUIHandler",
+ "mojom::SiteEngagementDetailsProvider",
"mojom::UsbInternalsPageHandler"
]
}
diff --git a/chromium/chrome/browser/chrome_content_renderer_manifest_overlay.json b/chromium/chrome/browser/chrome_content_renderer_manifest_overlay.json
index e995d7b7503..ce8b9f139fb 100644
--- a/chromium/chrome/browser/chrome_content_renderer_manifest_overlay.json
+++ b/chromium/chrome/browser/chrome_content_renderer_manifest_overlay.json
@@ -14,7 +14,10 @@
"autofill::mojom::AutofillAgent",
"autofill::mojom::PasswordAutofillAgent",
"autofill::mojom::PasswordGenerationAgent",
+ "blink::mojom::document_metadata::CopylessPaste",
+ "chrome::mojom::ImageContextMenuRenderer",
"chrome::mojom::InsecureContentRenderer",
+ "chrome::mojom::ThumbnailCapturer",
"contextual_search::mojom::OverlayPageNotifierService",
"dom_distiller::mojom::DistillerPageNotifierService"
]
diff --git a/chromium/chrome/browser/chrome_content_utility_manifest_overlay.json b/chromium/chrome/browser/chrome_content_utility_manifest_overlay.json
index 3684bccdd49..df19464de55 100644
--- a/chromium/chrome/browser/chrome_content_utility_manifest_overlay.json
+++ b/chromium/chrome/browser/chrome_content_utility_manifest_overlay.json
@@ -4,15 +4,20 @@
"service_manager:connector": {
"provides": {
"browser": [
+ "chrome::mojom::DialDeviceDescriptionParser",
"chrome::mojom::FilePatcher",
"chrome::mojom::ProfileImport",
"chrome::mojom::ResourceUsageReporter",
+ "chrome::mojom::SafeArchiveAnalyzer",
"chrome::mojom::ShellHandler",
"chrome::mojom::ZipFileCreator",
+ "extensions::mojom::ExtensionUnpacker",
+ "extensions::mojom::ManifestParser",
"extensions::mojom::MediaParser",
"extensions::mojom::RemovableStorageWriter",
"extensions::mojom::WiFiCredentialsGetter",
"net::interfaces::ProxyResolverFactory",
+ "payments::mojom::PaymentManifestParser",
"safe_json::mojom::SafeJsonParser"
]
}
diff --git a/chromium/chrome/browser/chrome_notification_types.h b/chromium/chrome/browser/chrome_notification_types.h
index 39640ae75e3..6c46a7101f7 100644
--- a/chromium/chrome/browser/chrome_notification_types.h
+++ b/chromium/chrome/browser/chrome_notification_types.h
@@ -83,12 +83,6 @@ enum NotificationType {
// traversal. The source is the browser, there are no details.
NOTIFICATION_FOCUS_RETURNED_TO_BROWSER,
- // A new tab is created from an existing tab to serve as a target of a
- // navigation that is about to happen. The source will be a Source<Profile>
- // corresponding to the profile in which the new tab will live. Details in
- // the form of a RetargetingDetails object are provided.
- NOTIFICATION_RETARGETING,
-
// Application-wide ----------------------------------------------------------
// This message is sent when the application is terminating (the last
diff --git a/chromium/chrome/browser/chromeos/BUILD.gn b/chromium/chrome/browser/chromeos/BUILD.gn
index 02a4b6bac36..29650e6b380 100644
--- a/chromium/chrome/browser/chromeos/BUILD.gn
+++ b/chromium/chrome/browser/chromeos/BUILD.gn
@@ -69,6 +69,7 @@ source_set("chromeos") {
"//components/pairing",
"//components/policy:generated",
"//components/proxy_config",
+ "//components/safe_browsing:csd_proto",
"//components/safe_browsing_db:metadata_proto",
"//components/session_manager/core",
"//components/sync_wifi",
@@ -94,6 +95,7 @@ source_set("chromeos") {
"//net",
"//ppapi/proxy:ipc", # For PpapiMsg_LoadPlugin
"//services/service_manager/public/cpp",
+ "//services/service_manager/runner/common",
"//services/ui/public/interfaces/display",
# TODO: care about enable_basic_printing and enable_print_preview.
@@ -118,8 +120,10 @@ source_set("chromeos") {
"//ui/aura",
"//ui/base",
"//ui/chromeos",
+ "//ui/chromeos/events",
"//ui/compositor",
"//ui/display",
+ "//ui/display/manager",
"//ui/events:dom_keycode_converter",
"//ui/events/devices",
"//ui/events/platform",
@@ -131,7 +135,6 @@ source_set("chromeos") {
"//ui/views/controls/webview",
"//ui/web_dialogs",
"//url",
- "//v8",
]
data_deps = [
@@ -173,6 +176,8 @@ source_set("chromeos") {
"app_mode/app_launch_utils.h",
"app_mode/app_session.cc",
"app_mode/app_session.h",
+ "app_mode/arc/arc_kiosk_app_data.cc",
+ "app_mode/arc/arc_kiosk_app_data.h",
"app_mode/arc/arc_kiosk_app_launcher.cc",
"app_mode/arc/arc_kiosk_app_launcher.h",
"app_mode/arc/arc_kiosk_app_manager.cc",
@@ -185,9 +190,13 @@ source_set("chromeos") {
"app_mode/certificate_manager_dialog.h",
"app_mode/kiosk_app_data.cc",
"app_mode/kiosk_app_data.h",
+ "app_mode/kiosk_app_data_base.cc",
+ "app_mode/kiosk_app_data_base.h",
"app_mode/kiosk_app_data_delegate.h",
"app_mode/kiosk_app_external_loader.cc",
"app_mode/kiosk_app_external_loader.h",
+ "app_mode/kiosk_app_icon_loader.cc",
+ "app_mode/kiosk_app_icon_loader.h",
"app_mode/kiosk_app_launch_error.cc",
"app_mode/kiosk_app_launch_error.h",
"app_mode/kiosk_app_manager.cc",
@@ -295,7 +304,7 @@ source_set("chromeos") {
"arc/notification/arc_boot_error_notification.h",
"arc/optin/arc_optin_preference_handler.cc",
"arc/optin/arc_optin_preference_handler.h",
- "arc/optin/arc_optin_preference_handler_delegate.h",
+ "arc/optin/arc_optin_preference_handler_observer.h",
"arc/optin/arc_terms_of_service_default_negotiator.cc",
"arc/optin/arc_terms_of_service_default_negotiator.h",
"arc/optin/arc_terms_of_service_negotiator.cc",
@@ -315,12 +324,18 @@ source_set("chromeos") {
"arc/process/arc_process.h",
"arc/process/arc_process_service.cc",
"arc/process/arc_process_service.h",
+ "arc/tracing/arc_tracing_bridge.cc",
+ "arc/tracing/arc_tracing_bridge.h",
"arc/tts/arc_tts_service.cc",
"arc/tts/arc_tts_service.h",
"arc/video/gpu_arc_video_service_host.cc",
"arc/video/gpu_arc_video_service_host.h",
+ "arc/voice_interaction/arc_voice_interaction_framework_service.cc",
+ "arc/voice_interaction/arc_voice_interaction_framework_service.h",
"arc/wallpaper/arc_wallpaper_service.cc",
"arc/wallpaper/arc_wallpaper_service.h",
+ "ash_config.cc",
+ "ash_config.h",
"attestation/attestation_ca_client.cc",
"attestation/attestation_ca_client.h",
"attestation/attestation_policy_observer.cc",
@@ -369,8 +384,8 @@ source_set("chromeos") {
"dbus/chrome_console_service_provider_delegate.h",
"dbus/chrome_display_power_service_provider_delegate.cc",
"dbus/chrome_display_power_service_provider_delegate.h",
- "dbus/chrome_proxy_resolver_delegate.cc",
- "dbus/chrome_proxy_resolver_delegate.h",
+ "dbus/chrome_proxy_resolution_service_provider_delegate.cc",
+ "dbus/chrome_proxy_resolution_service_provider_delegate.h",
"dbus/kiosk_info_service_provider.cc",
"dbus/kiosk_info_service_provider.h",
"dbus/mus_console_service_provider_delegate.cc",
@@ -427,10 +442,10 @@ source_set("chromeos") {
"enrollment_dialog_view.h",
"eol_notification.cc",
"eol_notification.h",
- "events/event_rewriter.cc",
- "events/event_rewriter.h",
"events/event_rewriter_controller.cc",
"events/event_rewriter_controller.h",
+ "events/event_rewriter_delegate_impl.cc",
+ "events/event_rewriter_delegate_impl.h",
"events/keyboard_driven_event_rewriter.cc",
"events/keyboard_driven_event_rewriter.h",
"events/system_key_event_listener.cc",
@@ -467,6 +482,8 @@ source_set("chromeos") {
"extensions/launcher_search_provider.h",
"extensions/media_player_event_router.cc",
"extensions/media_player_event_router.h",
+ "extensions/permissions_updater_delegate_chromeos.cc",
+ "extensions/permissions_updater_delegate_chromeos.h",
"extensions/public_session_permission_helper.cc",
"extensions/public_session_permission_helper.h",
"extensions/signin_screen_policy_provider.cc",
@@ -810,6 +827,9 @@ source_set("chromeos") {
"login/screens/enable_debugging_screen.cc",
"login/screens/enable_debugging_screen.h",
"login/screens/enable_debugging_screen_view.h",
+ "login/screens/encryption_migration_screen.cc",
+ "login/screens/encryption_migration_screen.h",
+ "login/screens/encryption_migration_screen_view.h",
"login/screens/error_screen.cc",
"login/screens/error_screen.h",
"login/screens/error_screen_view_delegate.h",
@@ -1016,6 +1036,8 @@ source_set("chromeos") {
"net/network_throttling_observer.h",
"net/shill_error.cc",
"net/shill_error.h",
+ "net/tether_notification_presenter.cc",
+ "net/tether_notification_presenter.h",
"net/wake_on_wifi_connection_observer.cc",
"net/wake_on_wifi_connection_observer.h",
"net/wake_on_wifi_manager.cc",
@@ -1214,10 +1236,11 @@ source_set("chromeos") {
"printing/cups_print_job_notification.h",
"printing/cups_print_job_notification_manager.cc",
"printing/cups_print_job_notification_manager.h",
- "printing/fake_printer_discoverer.cc",
- "printing/fake_printer_discoverer.h",
"printing/ppd_provider_factory.cc",
"printing/ppd_provider_factory.h",
+ "printing/printer_configurer.cc",
+ "printing/printer_configurer.h",
+ "printing/printer_discoverer.cc",
"printing/printer_discoverer.h",
"printing/printers_manager.cc",
"printing/printers_manager.h",
@@ -1227,6 +1250,8 @@ source_set("chromeos") {
"printing/printers_sync_bridge.h",
"printing/specifics_translation.cc",
"printing/specifics_translation.h",
+ "printing/usb_printer_util.cc",
+ "printing/usb_printer_util.h",
"profiles/avatar_menu_actions_chromeos.cc",
"profiles/avatar_menu_actions_chromeos.h",
"profiles/avatar_menu_chromeos.cc",
@@ -1462,10 +1487,6 @@ source_set("chromeos") {
if (use_cras) {
defines = [ "USE_CRAS" ]
}
-
- if (ui_compositor_image_transport) {
- deps += [ "//ui/gl" ]
- }
}
static_library("arc_test_support") {
@@ -1558,6 +1579,7 @@ source_set("unit_tests") {
"extensions/file_manager/device_event_router_unittest.cc",
"extensions/file_manager/job_event_router_unittest.cc",
"extensions/gfx_utils_unittest.cc",
+ "extensions/permissions_updater_delegate_chromeos_unittest.cc",
"extensions/public_session_permission_helper_unittest.cc",
"extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc",
"extensions/signin_screen_policy_provider_unittest.cc",
@@ -1647,6 +1669,7 @@ source_set("unit_tests") {
"net/network_pref_state_observer_unittest.cc",
"net/network_state_notifier_unittest.cc",
"net/network_throttling_observer_unittest.cc",
+ "net/tether_notification_presenter_unittest.cc",
"net/wake_on_wifi_manager_unittest.cc",
"note_taking_helper_unittest.cc",
"options/network_property_ui_data_unittest.cc",
@@ -1772,6 +1795,7 @@ source_set("unit_tests") {
":device_policy_proto",
":test_support",
"//ash/resources",
+ "//components/cryptauth:test_support",
"//components/drive",
"//components/drive:test_support_chromeos",
"//components/invalidation/public",
diff --git a/chromium/chrome/browser/devtools/BUILD.gn b/chromium/chrome/browser/devtools/BUILD.gn
index 88bf81a5404..a09f5b493fa 100644
--- a/chromium/chrome/browser/devtools/BUILD.gn
+++ b/chromium/chrome/browser/devtools/BUILD.gn
@@ -130,6 +130,8 @@ static_library("devtools") {
"global_confirm_info_bar.h",
"remote_debugging_server.cc",
"remote_debugging_server.h",
+ "serialize_host_descriptions.cc",
+ "serialize_host_descriptions.h",
"url_constants.cc",
"url_constants.h",
]
diff --git a/chromium/chrome/browser/ui/webui/engagement/BUILD.gn b/chromium/chrome/browser/engagement/BUILD.gn
index d0da3192949..4315a90a48c 100644
--- a/chromium/chrome/browser/ui/webui/engagement/BUILD.gn
+++ b/chromium/chrome/browser/engagement/BUILD.gn
@@ -6,7 +6,7 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
sources = [
- "site_engagement.mojom",
+ "site_engagement_details.mojom",
]
public_deps = [
diff --git a/chromium/chrome/browser/engagement/site_engagement_details.mojom b/chromium/chrome/browser/engagement/site_engagement_details.mojom
new file mode 100644
index 00000000000..cf494996341
--- /dev/null
+++ b/chromium/chrome/browser/engagement/site_engagement_details.mojom
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojom;
+
+import "url/mojo/url.mojom";
+
+struct SiteEngagementDetails {
+ url.mojom.Url origin;
+ double total_score;
+
+ // Details of the components which make up |score|. Note that these may
+ // sum to a value greater than |score| if it exceeds the maximum.
+ double base_score;
+ double installed_bonus;
+ double notifications_bonus;
+};
+
+interface SiteEngagementDetailsProvider {
+ GetSiteEngagementDetails() => (array<SiteEngagementDetails> info);
+ SetSiteEngagementBaseScoreForUrl(url.mojom.Url url, double score);
+};
diff --git a/chromium/chrome/browser/extensions/BUILD.gn b/chromium/chrome/browser/extensions/BUILD.gn
index 94dee68a104..a47d285c67b 100644
--- a/chromium/chrome/browser/extensions/BUILD.gn
+++ b/chromium/chrome/browser/extensions/BUILD.gn
@@ -15,18 +15,6 @@ static_library("extensions") {
sources = [
# TODO These references to files in //chrome/browser/ should either be
# moved to the browser target or the files moved to this directory.
- "../apps/app_launch_for_metro_restart_win.cc",
- "../apps/app_launch_for_metro_restart_win.h",
- "../apps/app_url_redirector.cc",
- "../apps/app_url_redirector.h",
- "../apps/app_window_registry_util.cc",
- "../apps/app_window_registry_util.h",
- "../apps/install_chrome_app.cc",
- "../apps/install_chrome_app.h",
- "../apps/shortcut_manager.cc",
- "../apps/shortcut_manager.h",
- "../apps/shortcut_manager_factory.cc",
- "../apps/shortcut_manager_factory.h",
"../ui/app_icon_loader.cc",
"../ui/app_icon_loader.h",
"../ui/toolbar/toolbar_actions_model.cc",
@@ -175,18 +163,10 @@ static_library("extensions") {
"api/developer_private/inspectable_views_finder.h",
"api/developer_private/show_permissions_dialog_helper.cc",
"api/developer_private/show_permissions_dialog_helper.h",
- "api/dial/device_description_fetcher.cc",
- "api/dial/device_description_fetcher.h ",
"api/dial/dial_api.cc",
"api/dial/dial_api.h",
"api/dial/dial_api_factory.cc",
"api/dial/dial_api_factory.h",
- "api/dial/dial_device_data.cc",
- "api/dial/dial_device_data.h",
- "api/dial/dial_registry.cc",
- "api/dial/dial_registry.h",
- "api/dial/dial_service.cc",
- "api/dial/dial_service.h",
"api/downloads/downloads_api.cc",
"api/downloads/downloads_api.h",
"api/downloads_internal/downloads_internal_api.cc",
@@ -318,8 +298,12 @@ static_library("extensions") {
"api/networking_private/networking_private_ui_delegate_chromeos.h",
"api/networking_private/networking_private_ui_delegate_factory_impl.cc",
"api/networking_private/networking_private_ui_delegate_factory_impl.h",
- "api/networking_private/networking_private_verify_delegate_factory_impl.cc",
- "api/networking_private/networking_private_verify_delegate_factory_impl.h",
+ "api/notifications/extension_notification_display_helper.cc",
+ "api/notifications/extension_notification_display_helper.h",
+ "api/notifications/extension_notification_display_helper_factory.cc",
+ "api/notifications/extension_notification_display_helper_factory.h",
+ "api/notifications/extension_notification_handler.cc",
+ "api/notifications/extension_notification_handler.h",
"api/notifications/notifications_api.cc",
"api/notifications/notifications_api.h",
"api/omnibox/omnibox_api.cc",
@@ -467,6 +451,8 @@ static_library("extensions") {
"app_data_migrator.h",
"blacklist.cc",
"blacklist.h",
+ "blacklist_check.cc",
+ "blacklist_check.h",
"blacklist_factory.cc",
"blacklist_factory.h",
"blacklist_state_fetcher.cc",
@@ -507,8 +493,6 @@ static_library("extensions") {
"chrome_mojo_service_registration.h",
"chrome_process_manager_delegate.cc",
"chrome_process_manager_delegate.h",
- "chrome_requirements_checker.cc",
- "chrome_requirements_checker.h",
"chrome_url_request_util.cc",
"chrome_url_request_util.h",
"clipboard_extension_helper_chromeos.cc",
@@ -591,8 +575,6 @@ static_library("extensions") {
"extension_gcm_app_handler.h",
"extension_icon_manager.cc",
"extension_icon_manager.h",
- "extension_install_checker.cc",
- "extension_install_checker.h",
"extension_install_error_menu_item_id_provider.cc",
"extension_install_error_menu_item_id_provider.h",
"extension_install_prompt.cc",
@@ -641,6 +623,7 @@ static_library("extensions") {
"extension_uninstall_dialog.h",
"extension_util.cc",
"extension_util.h",
+ "extension_view.h",
"extension_view_host.cc",
"extension_view_host.h",
"extension_view_host_factory.cc",
@@ -698,8 +681,6 @@ static_library("extensions") {
"installed_loader.h",
"launch_util.cc",
"launch_util.h",
- "location_bar_controller.cc",
- "location_bar_controller.h",
"menu_manager.cc",
"menu_manager.h",
"menu_manager_factory.cc",
@@ -722,6 +703,8 @@ static_library("extensions") {
"permissions_updater.h",
"plugin_manager.cc",
"plugin_manager.h",
+ "policy_extension_reinstaller.cc",
+ "policy_extension_reinstaller.h",
"policy_handlers.cc",
"policy_handlers.h",
"proxy_overridden_bubble_delegate.cc",
@@ -820,6 +803,7 @@ static_library("extensions") {
"//content/public/browser",
]
deps = [
+ "//apps",
"//chrome:extra_resources",
"//chrome:resources",
"//chrome:strings",
@@ -829,6 +813,7 @@ static_library("extensions") {
"//chrome/app/theme:theme_resources",
"//chrome/app/vector_icons",
"//chrome/browser/devtools",
+ "//chrome/browser/media/router/discovery",
"//chrome/common",
"//chrome/common/extensions/api:api_registration",
"//chrome/common/extensions/api:extensions_features",
@@ -895,6 +880,7 @@ static_library("extensions") {
"//extensions:extensions_resources",
"//extensions/browser",
"//extensions/browser/api:api_registration",
+ "//extensions/common",
"//extensions/common/api",
"//extensions/features",
"//extensions/strings",
@@ -903,6 +889,9 @@ static_library("extensions") {
"//ppapi/features",
"//printing/features",
"//rlz/features",
+ "//services/identity/public/interfaces",
+ "//services/service_manager/public/cpp",
+ "//services/service_manager/public/interfaces",
"//skia",
"//sql",
"//storage/browser",
@@ -925,6 +914,7 @@ static_library("extensions") {
"//ui/resources",
"//ui/shell_dialogs",
"//ui/strings",
+ "//ui/vector_icons",
"//url",
]
@@ -965,8 +955,10 @@ static_library("extensions") {
"api/log_private/syslog_parser.cc",
"api/log_private/syslog_parser.h",
"api/messaging/native_message_host_chromeos.cc",
- "api/networking_private/crypto_verify_impl.cc",
- "api/networking_private/crypto_verify_impl.h",
+ "api/networking_cast_private/chrome_networking_cast_private_delegate.cc",
+ "api/networking_cast_private/chrome_networking_cast_private_delegate.h",
+ "api/networking_cast_private/networking_cast_private_api.cc",
+ "api/networking_cast_private/networking_cast_private_api.h",
"api/platform_keys/platform_keys_api.cc",
"api/platform_keys/platform_keys_api.h",
"api/platform_keys/verify_trust_api.cc",
@@ -1006,6 +998,7 @@ static_library("extensions") {
"//third_party/protobuf:protobuf_lite",
"//ui/app_list",
"//ui/chromeos",
+ "//ui/chromeos/events",
"//ui/file_manager",
"//ui/views/",
]
@@ -1069,8 +1062,10 @@ static_library("extensions") {
if (is_win || is_mac) {
sources += [
- "api/networking_private/crypto_verify_impl.cc",
- "api/networking_private/crypto_verify_impl.h",
+ "api/networking_cast_private/chrome_networking_cast_private_delegate.cc",
+ "api/networking_cast_private/chrome_networking_cast_private_delegate.h",
+ "api/networking_cast_private/networking_cast_private_api.cc",
+ "api/networking_cast_private/networking_cast_private_api.h",
"api/networking_private/networking_private_credentials_getter.h",
"api/networking_private/networking_private_credentials_getter_mac.cc",
"api/networking_private/networking_private_credentials_getter_win.cc",
diff --git a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
index 2da6ff04812..cfe4292d20c 100644
--- a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
@@ -32,8 +32,9 @@ using activity_log_private::ActivityResultSet;
using activity_log_private::ExtensionActivity;
using activity_log_private::Filter;
-static base::LazyInstance<BrowserContextKeyedAPIFactory<ActivityLogAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<ActivityLogAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<ActivityLogAPI>*
diff --git a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc
index d813ad5e695..e26a1bd0031 100644
--- a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc
@@ -8,7 +8,9 @@
#include <string>
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -28,8 +30,8 @@ typedef testing::Test ActivityLogApiUnitTest;
TEST_F(ActivityLogApiUnitTest, ConvertChromeApiAction) {
std::unique_ptr<base::ListValue> args(new base::ListValue());
- args->Set(0, new base::StringValue("hello"));
- args->Set(1, new base::StringValue("world"));
+ args->Set(0, base::MakeUnique<base::Value>("hello"));
+ args->Set(1, base::MakeUnique<base::Value>("world"));
scoped_refptr<Action> action(new Action(kExtensionId,
base::Time::Now(),
Action::ACTION_API_CALL,
@@ -46,8 +48,8 @@ TEST_F(ActivityLogApiUnitTest, ConvertChromeApiAction) {
TEST_F(ActivityLogApiUnitTest, ConvertDomAction) {
std::unique_ptr<base::ListValue> args(new base::ListValue());
- args->Set(0, new base::StringValue("hello"));
- args->Set(1, new base::StringValue("world"));
+ args->Set(0, base::MakeUnique<base::Value>("hello"));
+ args->Set(1, base::MakeUnique<base::Value>("world"));
scoped_refptr<Action> action(new Action(kExtensionId,
base::Time::Now(),
Action::ACTION_DOM_ACCESS,
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 72c7af103cb..0444ddc16c0 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
@@ -31,6 +31,9 @@ namespace {
static const char kSettingsOrigin[] = "Chrome settings";
static const char kErrorDataUnavailable[] = "Autofill data unavailable.";
+// TODO(mad): This does basically the same thing as
+// components/autofill/core/browser/autofill_address_util.cc, we
+// should refactor to use a single code path for this.
// Fills |components| with the address UI components that should be used to
// input an address for |country_code| when UI BCP 47 language code is
// |ui_language_code|.
diff --git a/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc b/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc
index b498453e2d3..0c1a5ee6e4b 100644
--- a/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -33,8 +33,8 @@
#include "ui/accessibility/tree_generator.h"
#if defined(OS_CHROMEOS)
-#include "ash/common/accelerators/accelerator_controller.h"
-#include "ash/common/wm_shell.h"
+#include "ash/accelerators/accelerator_controller.h"
+#include "ash/shell.h"
#include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
#endif
@@ -203,7 +203,7 @@ IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopFocusIframe) {
IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopFocusViews) {
AutomationManagerAura::GetInstance()->Enable(browser()->profile());
// Trigger the shelf subtree to be computed.
- ash::WmShell::Get()->accelerator_controller()->PerformActionIfEnabled(
+ ash::Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
ash::FOCUS_SHELF);
ASSERT_TRUE(
@@ -221,7 +221,7 @@ IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopNotRequested) {
IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopActions) {
AutomationManagerAura::GetInstance()->Enable(browser()->profile());
// Trigger the shelf subtree to be computed.
- ash::WmShell::Get()->accelerator_controller()->PerformActionIfEnabled(
+ ash::Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
ash::FOCUS_SHELF);
ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "actions.html"))
@@ -280,4 +280,10 @@ IN_PROC_BROWSER_TEST_F(AutomationApiTest, DocumentSelection) {
<< message_;
}
+IN_PROC_BROWSER_TEST_F(AutomationApiTest, HitTest) {
+ StartEmbeddedTestServer();
+ ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "hit_test.html"))
+ << message_;
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 108c09d772a..ced7dde6d03 100644
--- a/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -349,6 +349,19 @@ AutomationInternalPerformActionFunction::ConvertToAXActionData(
get_image_data_params.max_height);
break;
}
+ case api::automation_internal::ACTION_TYPE_HITTEST: {
+ api::automation_internal::HitTestParams hit_test_params;
+ EXTENSION_FUNCTION_VALIDATE(
+ api::automation_internal::HitTestParams::Populate(
+ params->opt_args.additional_properties, &hit_test_params));
+ action->action = ui::AX_ACTION_HIT_TEST;
+ action->target_point = gfx::Point(hit_test_params.x, hit_test_params.y);
+ action->hit_test_event_to_fire =
+ ui::ParseAXEvent(hit_test_params.event_to_fire);
+ if (action->hit_test_event_to_fire == ui::AX_EVENT_NONE)
+ return RespondNow(NoArguments());
+ break;
+ }
case api::automation_internal::ACTION_TYPE_MAKEVISIBLE:
action->action = ui::AX_ACTION_SCROLL_TO_MAKE_VISIBLE;
break;
diff --git a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
index 3583b207472..e50590e4ca2 100644
--- a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -10,16 +10,17 @@
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/autotest_private.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/browser/extension_util.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/manifest_handlers/options_page_info.h"
#include "extensions/common/permissions/api_permission_set.h"
@@ -40,13 +41,14 @@
namespace extensions {
namespace {
-base::ListValue* GetHostPermissions(const Extension* ext, bool effective_perm) {
+std::unique_ptr<base::ListValue> GetHostPermissions(const Extension* ext,
+ bool effective_perm) {
const PermissionsData* permissions_data = ext->permissions_data();
const URLPatternSet& pattern_set =
effective_perm ? permissions_data->GetEffectiveHostPermissions()
: permissions_data->active_permissions().explicit_hosts();
- base::ListValue* permissions = new base::ListValue;
+ auto permissions = base::MakeUnique<base::ListValue>();
for (URLPatternSet::const_iterator perm = pattern_set.begin();
perm != pattern_set.end();
++perm) {
@@ -56,13 +58,13 @@ base::ListValue* GetHostPermissions(const Extension* ext, bool effective_perm) {
return permissions;
}
-base::ListValue* GetAPIPermissions(const Extension* ext) {
- base::ListValue* permissions = new base::ListValue;
+std::unique_ptr<base::ListValue> GetAPIPermissions(const Extension* ext) {
+ auto permissions = base::MakeUnique<base::ListValue>();
std::set<std::string> perm_list =
ext->permissions_data()->active_permissions().GetAPIsAsStrings();
for (std::set<std::string>::const_iterator perm = perm_list.begin();
perm != perm_list.end(); ++perm) {
- permissions->AppendString(perm->c_str());
+ permissions->AppendString(*perm);
}
return permissions;
}
@@ -166,7 +168,7 @@ AutotestPrivateGetExtensionsInfoFunction::Run() {
ExtensionActionManager* extension_action_manager =
ExtensionActionManager::Get(browser_context());
- base::ListValue* extensions_values = new base::ListValue;
+ auto extensions_values = base::MakeUnique<base::ListValue>();
ExtensionList all;
all.insert(all.end(), extensions.begin(), extensions.end());
all.insert(all.end(), disabled_extensions.begin(), disabled_extensions.end());
@@ -212,7 +214,7 @@ AutotestPrivateGetExtensionsInfoFunction::Run() {
std::unique_ptr<base::DictionaryValue> return_value(
new base::DictionaryValue);
- return_value->Set("extensions", extensions_values);
+ return_value->Set("extensions", std::move(extensions_values));
return RespondNow(OneArgument(std::move(return_value)));
}
@@ -378,8 +380,8 @@ AutotestPrivateGetVisibleNotificationsFunction::Run() {
return RespondNow(OneArgument(std::move(values)));
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<AutotestPrivateAPI>*
diff --git a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/OWNERS b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/OWNERS
index 3ed331b322e..6a2cb03fd3e 100644
--- a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/OWNERS
+++ b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/OWNERS
@@ -1 +1 @@
-steel@chromium.org
+rkc@chromium.org
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 7cb0a30d441..7a33bae88a4 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
@@ -700,15 +700,15 @@ IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadCharacteristicValue) {
event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
- .Times(3)
+ .Times(4)
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
- .Times(3)
+ .Times(4)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
- .Times(3)
+ .Times(4)
.WillRepeatedly(Return(chrc0_.get()));
std::vector<uint8_t> value;
@@ -1144,10 +1144,11 @@ IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GattConnection) {
.WillRepeatedly(Return(device0_.get()));
EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress1))
.WillRepeatedly(Return(device1_.get()));
- static_assert(BluetoothDevice::NUM_CONNECT_ERROR_CODES == 15,
+ static_assert(
+ BluetoothDevice::NUM_CONNECT_ERROR_CODES == 8,
"Update required if the number of BluetoothDevice enums changes.");
EXPECT_CALL(*device0_, CreateGattConnection(_, _))
- .Times(16)
+ .Times(9)
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_FAILED))
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_INPROGRESS))
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_AUTH_FAILED))
@@ -1156,20 +1157,6 @@ IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GattConnection) {
.WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_AUTH_TIMEOUT))
.WillOnce(
InvokeCallbackArgument<1>(BluetoothDevice::ERROR_UNSUPPORTED_DEVICE))
- .WillOnce(InvokeCallbackArgument<1>(
- BluetoothDevice::ERROR_ATTRIBUTE_LENGTH_INVALID))
- .WillOnce(InvokeCallbackArgument<1>(
- BluetoothDevice::ERROR_CONNECTION_CONGESTED))
- .WillOnce(InvokeCallbackArgument<1>(
- BluetoothDevice::ERROR_INSUFFICIENT_ENCRYPTION))
- .WillOnce(
- InvokeCallbackArgument<1>(BluetoothDevice::ERROR_OFFSET_INVALID))
- .WillOnce(InvokeCallbackArgument<1>(
- BluetoothDevice::ERROR_READ_NOT_PERMITTED))
- .WillOnce(InvokeCallbackArgument<1>(
- BluetoothDevice::ERROR_REQUEST_NOT_SUPPORTED))
- .WillOnce(InvokeCallbackArgument<1>(
- BluetoothDevice::ERROR_WRITE_NOT_PERMITTED))
.WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
CreateGattConnection(mock_adapter_, kTestLeDeviceAddress0,
true /* expect_disconnect */)))
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 0b5be4644b1..94cd27a902a 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
@@ -269,8 +269,8 @@ void BookmarkManagerPrivateAPI::Shutdown() {
}
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<BookmarkManagerPrivateAPI>*
diff --git a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc
index c64ba831db1..b0f1c361663 100644
--- a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc
@@ -47,7 +47,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_BookmarkManager) {
list.Append(std::move(node));
node.reset(new base::DictionaryValue());
node->SetString("name", "Managed Folder");
- node->Set("children", new base::ListValue());
+ node->Set("children", base::MakeUnique<base::ListValue>());
list.Append(std::move(node));
profile->GetPrefs()->Set(bookmarks::prefs::kManagedBookmarks, list);
ASSERT_EQ(2, managed->managed_node()->child_count());
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
index e401e50be80..9cf5c20c80a 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
@@ -5,10 +5,14 @@
#include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h"
#include <math.h> // For floor()
+
+#include <utility>
#include <vector>
+#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
#include "chrome/common/extensions/api/bookmarks.h"
#include "components/bookmarks/browser/bookmark_model.h"
@@ -151,14 +155,14 @@ void GetMetaInfo(const BookmarkNode& node,
return;
const BookmarkNode::MetaInfoMap* meta_info = node.GetMetaInfoMap();
- base::DictionaryValue* value = new base::DictionaryValue();
+ auto value = base::MakeUnique<base::DictionaryValue>();
if (meta_info) {
BookmarkNode::MetaInfoMap::const_iterator itr;
for (itr = meta_info->begin(); itr != meta_info->end(); ++itr) {
value->SetStringWithoutPathExpansion(itr->first, itr->second);
}
}
- id_to_meta_info_map->Set(base::Int64ToString(node.id()), value);
+ id_to_meta_info_map->Set(base::Int64ToString(node.id()), std::move(value));
if (node.is_folder()) {
for (int i = 0; i < node.child_count(); ++i) {
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc
index 75fe94389b0..b841d5f5f9d 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc
@@ -5,6 +5,7 @@
#include <memory>
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -44,7 +45,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Bookmarks) {
list.Append(std::move(node));
node.reset(new base::DictionaryValue());
node->SetString("name", "Managed Folder");
- node->Set("children", new base::ListValue());
+ node->Set("children", base::MakeUnique<base::ListValue>());
list.Append(std::move(node));
profile->GetPrefs()->Set(bookmarks::prefs::kManagedBookmarks, list);
ASSERT_EQ(2, managed->managed_node()->child_count());
@@ -58,7 +59,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Bookmarks) {
list.Append(std::move(node));
node.reset(new base::DictionaryValue());
node->SetString("name", "Supervised Folder");
- node->Set("children", new base::ListValue());
+ node->Set("children", base::MakeUnique<base::ListValue>());
list.Append(std::move(node));
profile->GetPrefs()->Set(bookmarks::prefs::kSupervisedBookmarks, list);
ASSERT_EQ(2, managed->supervised_node()->child_count());
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
index a9e78ad8b92..63b27c876cf 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -403,8 +403,9 @@ void BookmarksAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<BookmarksAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<BookmarksAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<BookmarksAPI>*
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 efa0629297f..28e7612f554 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
@@ -51,11 +51,12 @@ BrailleDisplayPrivateAPI::~BrailleDisplayPrivateAPI() {
}
void BrailleDisplayPrivateAPI::Shutdown() {
+ event_delegate_.reset();
}
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<BrailleDisplayPrivateAPI> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<BrailleDisplayPrivateAPI>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<BrailleDisplayPrivateAPI>*
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 e8474db05fc..584ac30c335 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
@@ -15,6 +15,7 @@
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
#include "chrome/browser/browsing_data/browsing_data_remover_factory.h"
+#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/plugins/plugin_data_remover_helper.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
@@ -71,38 +72,38 @@ const char kDeleteProhibitedError[] = "Browsing history and downloads are not "
namespace {
int MaskForKey(const char* key) {
if (strcmp(key, extension_browsing_data_api_constants::kAppCacheKey) == 0)
- return BrowsingDataRemover::REMOVE_APPCACHE;
+ return BrowsingDataRemover::DATA_TYPE_APP_CACHE;
if (strcmp(key, extension_browsing_data_api_constants::kCacheKey) == 0)
- return BrowsingDataRemover::REMOVE_CACHE;
+ return BrowsingDataRemover::DATA_TYPE_CACHE;
if (strcmp(key, extension_browsing_data_api_constants::kCookiesKey) == 0) {
- return BrowsingDataRemover::REMOVE_COOKIES;
+ return BrowsingDataRemover::DATA_TYPE_COOKIES;
}
if (strcmp(key, extension_browsing_data_api_constants::kDownloadsKey) == 0)
- return BrowsingDataRemover::REMOVE_DOWNLOADS;
+ return BrowsingDataRemover::DATA_TYPE_DOWNLOADS;
if (strcmp(key, extension_browsing_data_api_constants::kFileSystemsKey) == 0)
- return BrowsingDataRemover::REMOVE_FILE_SYSTEMS;
+ return BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS;
if (strcmp(key, extension_browsing_data_api_constants::kFormDataKey) == 0)
- return BrowsingDataRemover::REMOVE_FORM_DATA;
+ return ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA;
if (strcmp(key, extension_browsing_data_api_constants::kHistoryKey) == 0)
- return BrowsingDataRemover::REMOVE_HISTORY;
+ return ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
if (strcmp(key, extension_browsing_data_api_constants::kIndexedDBKey) == 0)
- return BrowsingDataRemover::REMOVE_INDEXEDDB;
+ return BrowsingDataRemover::DATA_TYPE_INDEXED_DB;
if (strcmp(key, extension_browsing_data_api_constants::kLocalStorageKey) == 0)
- return BrowsingDataRemover::REMOVE_LOCAL_STORAGE;
+ return BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE;
if (strcmp(key,
extension_browsing_data_api_constants::kChannelIDsKey) == 0)
- return BrowsingDataRemover::REMOVE_CHANNEL_IDS;
+ return BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS;
if (strcmp(key, extension_browsing_data_api_constants::kPasswordsKey) == 0)
- return BrowsingDataRemover::REMOVE_PASSWORDS;
+ return ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS;
if (strcmp(key, extension_browsing_data_api_constants::kPluginDataKey) == 0)
- return BrowsingDataRemover::REMOVE_PLUGIN_DATA;
+ return ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;
if (strcmp(key, extension_browsing_data_api_constants::kServiceWorkersKey) ==
0)
- return BrowsingDataRemover::REMOVE_SERVICE_WORKERS;
+ return BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS;
if (strcmp(key, extension_browsing_data_api_constants::kCacheStorageKey) == 0)
- return BrowsingDataRemover::REMOVE_CACHE_STORAGE;
+ return BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE;
if (strcmp(key, extension_browsing_data_api_constants::kWebSQLKey) == 0)
- return BrowsingDataRemover::REMOVE_WEBSQL;
+ return BrowsingDataRemover::DATA_TYPE_WEB_SQL;
return 0;
}
@@ -112,8 +113,8 @@ int MaskForKey(const char* key) {
bool IsRemovalPermitted(int removal_mask, PrefService* prefs) {
// Enterprise policy or user preference might prohibit deleting browser or
// download history.
- if ((removal_mask & BrowsingDataRemover::REMOVE_HISTORY) ||
- (removal_mask & BrowsingDataRemover::REMOVE_DOWNLOADS)) {
+ if ((removal_mask & ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY) ||
+ (removal_mask & BrowsingDataRemover::DATA_TYPE_DOWNLOADS)) {
return prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory);
}
return true;
@@ -145,14 +146,14 @@ ExtensionFunction::ResponseAction BrowsingDataSettingsFunction::Run() {
browsing_data::TimePeriod period =
static_cast<browsing_data::TimePeriod>(period_pref);
double since = 0;
- if (period != browsing_data::ALL_TIME) {
+ if (period != browsing_data::TimePeriod::ALL_TIME) {
base::Time time = browsing_data::CalculateBeginDeleteTime(period);
since = time.ToJsTime();
}
std::unique_ptr<base::DictionaryValue> options(new base::DictionaryValue);
options->Set(extension_browsing_data_api_constants::kOriginTypesKey,
- origin_types.release());
+ std::move(origin_types));
options->SetDouble(extension_browsing_data_api_constants::kSinceKey, since);
// Fill dataToRemove and dataRemovalPermitted.
@@ -214,11 +215,11 @@ ExtensionFunction::ResponseAction BrowsingDataSettingsFunction::Run() {
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
result->Set(extension_browsing_data_api_constants::kOptionsKey,
- options.release());
+ std::move(options));
result->Set(extension_browsing_data_api_constants::kDataToRemoveKey,
- selected.release());
+ std::move(selected));
result->Set(extension_browsing_data_api_constants::kDataRemovalPermittedKey,
- permitted.release());
+ std::move(permitted));
return RespondNow(OneArgument(std::move(result)));
}
@@ -278,7 +279,8 @@ bool BrowsingDataRemoverFunction::RunAsync() {
return false;
}
- if (removal_mask_ & BrowsingDataRemover::REMOVE_PLUGIN_DATA) {
+ if (removal_mask_ &
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA) {
// If we're being asked to remove plugin data, check whether it's actually
// supported.
BrowserThread::PostTask(
@@ -301,7 +303,7 @@ BrowsingDataRemoverFunction::~BrowsingDataRemoverFunction() {}
void BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported(
scoped_refptr<PluginPrefs> plugin_prefs) {
if (!PluginDataRemoverHelper::IsSupported(plugin_prefs.get()))
- removal_mask_ &= ~BrowsingDataRemover::REMOVE_PLUGIN_DATA;
+ removal_mask_ &= ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -329,7 +331,7 @@ bool BrowsingDataRemoverFunction::ParseOriginTypeMask(
int* 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 = BrowsingDataHelper::UNPROTECTED_WEB;
+ *origin_type_mask = BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
const base::DictionaryValue* d = NULL;
if (options.HasKey(extension_browsing_data_api_constants::kOriginTypesKey)) {
@@ -349,7 +351,8 @@ bool BrowsingDataRemoverFunction::ParseOriginTypeMask(
&value)) {
return false;
}
- *origin_type_mask |= value ? BrowsingDataHelper::UNPROTECTED_WEB : 0;
+ *origin_type_mask |=
+ value ? BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB : 0;
}
// Protected web.
@@ -359,7 +362,8 @@ bool BrowsingDataRemoverFunction::ParseOriginTypeMask(
&value)) {
return false;
}
- *origin_type_mask |= value ? BrowsingDataHelper::PROTECTED_WEB : 0;
+ *origin_type_mask |=
+ value ? BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB : 0;
}
// Extensions.
@@ -368,7 +372,8 @@ bool BrowsingDataRemoverFunction::ParseOriginTypeMask(
&value)) {
return false;
}
- *origin_type_mask |= value ? BrowsingDataHelper::EXTENSION : 0;
+ *origin_type_mask |=
+ value ? ChromeBrowsingDataRemoverDelegate::ORIGIN_TYPE_EXTENSION : 0;
}
}
@@ -398,73 +403,73 @@ bool BrowsingDataRemoveFunction::GetRemovalMask(int* removal_mask) {
}
bool BrowsingDataRemoveAppcacheFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_APPCACHE;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_APP_CACHE;
return true;
}
bool BrowsingDataRemoveCacheFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_CACHE;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_CACHE;
return true;
}
bool BrowsingDataRemoveCookiesFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_COOKIES |
- BrowsingDataRemover::REMOVE_CHANNEL_IDS;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_COOKIES |
+ BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS;
return true;
}
bool BrowsingDataRemoveDownloadsFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_DOWNLOADS;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_DOWNLOADS;
return true;
}
bool BrowsingDataRemoveFileSystemsFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_FILE_SYSTEMS;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS;
return true;
}
bool BrowsingDataRemoveFormDataFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_FORM_DATA;
+ *removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA;
return true;
}
bool BrowsingDataRemoveHistoryFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_HISTORY;
+ *removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
return true;
}
bool BrowsingDataRemoveIndexedDBFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_INDEXEDDB;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_INDEXED_DB;
return true;
}
bool BrowsingDataRemoveLocalStorageFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_LOCAL_STORAGE;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE;
return true;
}
bool BrowsingDataRemovePluginDataFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_PLUGIN_DATA;
+ *removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;
return true;
}
bool BrowsingDataRemovePasswordsFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_PASSWORDS;
+ *removal_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS;
return true;
}
bool BrowsingDataRemoveServiceWorkersFunction::GetRemovalMask(
int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_SERVICE_WORKERS;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS;
return true;
}
bool BrowsingDataRemoveCacheStorageFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_CACHE_STORAGE;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE;
return true;
}
bool BrowsingDataRemoveWebSQLFunction::GetRemovalMask(int* removal_mask) {
- *removal_mask = BrowsingDataRemover::REMOVE_WEBSQL;
+ *removal_mask = BrowsingDataRemover::DATA_TYPE_WEB_SQL;
return true;
}
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 10efc181e6f..e48434737d1 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
@@ -13,6 +13,7 @@
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
#include "chrome/browser/browsing_data/browsing_data_remover_factory.h"
+#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/extensions/api/browsing_data/browsing_data_api.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/profiles/profile.h"
@@ -29,9 +30,9 @@ using extension_function_test_utils::RunFunctionAndReturnSingleResult;
namespace {
enum OriginTypeMask {
- UNPROTECTED_WEB = BrowsingDataHelper::UNPROTECTED_WEB,
- PROTECTED_WEB = BrowsingDataHelper::PROTECTED_WEB,
- EXTENSION = BrowsingDataHelper::EXTENSION
+ UNPROTECTED_WEB = BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
+ PROTECTED_WEB = BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
+ EXTENSION = ChromeBrowsingDataRemoverDelegate::ORIGIN_TYPE_EXTENSION
};
const char kRemoveEverythingArguments[] =
@@ -120,7 +121,8 @@ class ExtensionBrowsingDataTest : public InProcessBrowserTest {
void SetSinceAndVerify(browsing_data::TimePeriod since_pref) {
PrefService* prefs = browser()->profile()->GetPrefs();
- prefs->SetInteger(browsing_data::prefs::kDeleteTimePeriod, since_pref);
+ prefs->SetInteger(browsing_data::prefs::kDeleteTimePeriod,
+ static_cast<int>(since_pref));
scoped_refptr<BrowsingDataSettingsFunction> function =
new BrowsingDataSettingsFunction();
@@ -136,7 +138,7 @@ class ExtensionBrowsingDataTest : public InProcessBrowserTest {
EXPECT_TRUE(options->GetDouble("since", &since));
double expected_since = 0;
- if (since_pref != browsing_data::ALL_TIME) {
+ if (since_pref != browsing_data::TimePeriod::ALL_TIME) {
base::Time time = CalculateBeginDeleteTime(since_pref);
expected_since = time.ToJsTime();
}
@@ -152,23 +154,34 @@ class ExtensionBrowsingDataTest : public InProcessBrowserTest {
int expected_origin_type_mask,
int expected_removal_mask) {
PrefService* prefs = browser()->profile()->GetPrefs();
- prefs->SetBoolean(browsing_data::prefs::kDeleteCache,
- !!(data_type_flags & BrowsingDataRemover::REMOVE_CACHE));
- prefs->SetBoolean(browsing_data::prefs::kDeleteCookies,
- !!(data_type_flags & BrowsingDataRemover::REMOVE_COOKIES));
+ prefs->SetBoolean(
+ browsing_data::prefs::kDeleteCache,
+ !!(data_type_flags & BrowsingDataRemover::DATA_TYPE_CACHE));
+ prefs->SetBoolean(
+ browsing_data::prefs::kDeleteCookies,
+ !!(data_type_flags & BrowsingDataRemover::DATA_TYPE_COOKIES));
prefs->SetBoolean(browsing_data::prefs::kDeleteBrowsingHistory,
- !!(data_type_flags & BrowsingDataRemover::REMOVE_HISTORY));
- prefs->SetBoolean(browsing_data::prefs::kDeleteFormData,
- !!(data_type_flags & BrowsingDataRemover::REMOVE_FORM_DATA));
- prefs->SetBoolean(browsing_data::prefs::kDeleteDownloadHistory,
- !!(data_type_flags & BrowsingDataRemover::REMOVE_DOWNLOADS));
- prefs->SetBoolean(browsing_data::prefs::kDeleteHostedAppsData,
+ !!(data_type_flags &
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY));
+ prefs->SetBoolean(
+ browsing_data::prefs::kDeleteFormData,
!!(data_type_flags &
- BrowsingDataRemover::REMOVE_HOSTED_APP_DATA_TESTONLY));
- prefs->SetBoolean(browsing_data::prefs::kDeletePasswords,
- !!(data_type_flags & BrowsingDataRemover::REMOVE_PASSWORDS));
- prefs->SetBoolean(prefs::kClearPluginLSODataEnabled,
- !!(data_type_flags & BrowsingDataRemover::REMOVE_PLUGIN_DATA));
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA));
+ prefs->SetBoolean(
+ browsing_data::prefs::kDeleteDownloadHistory,
+ !!(data_type_flags & BrowsingDataRemover::DATA_TYPE_DOWNLOADS));
+ prefs->SetBoolean(
+ browsing_data::prefs::kDeleteHostedAppsData,
+ !!(data_type_flags & ChromeBrowsingDataRemoverDelegate::
+ DATA_TYPE_HOSTED_APP_DATA_TEST_ONLY));
+ prefs->SetBoolean(
+ browsing_data::prefs::kDeletePasswords,
+ !!(data_type_flags &
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS));
+ prefs->SetBoolean(
+ prefs::kClearPluginLSODataEnabled,
+ !!(data_type_flags &
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA));
scoped_refptr<BrowsingDataSettingsFunction> function =
new BrowsingDataSettingsFunction();
@@ -194,34 +207,35 @@ class ExtensionBrowsingDataTest : public InProcessBrowserTest {
EXPECT_TRUE(result->GetDictionary("dataToRemove", &data_to_remove));
int removal_mask =
GetAsMask(data_to_remove, "appcache",
- BrowsingDataRemover::REMOVE_APPCACHE) |
- GetAsMask(data_to_remove, "cache", BrowsingDataRemover::REMOVE_CACHE) |
+ BrowsingDataRemover::DATA_TYPE_APP_CACHE) |
+ GetAsMask(data_to_remove, "cache",
+ BrowsingDataRemover::DATA_TYPE_CACHE) |
GetAsMask(data_to_remove, "cookies",
- BrowsingDataRemover::REMOVE_COOKIES) |
+ BrowsingDataRemover::DATA_TYPE_COOKIES) |
GetAsMask(data_to_remove, "downloads",
- BrowsingDataRemover::REMOVE_DOWNLOADS) |
+ BrowsingDataRemover::DATA_TYPE_DOWNLOADS) |
GetAsMask(data_to_remove, "fileSystems",
- BrowsingDataRemover::REMOVE_FILE_SYSTEMS) |
+ BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS) |
GetAsMask(data_to_remove, "formData",
- BrowsingDataRemover::REMOVE_FORM_DATA) |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA) |
GetAsMask(data_to_remove, "history",
- BrowsingDataRemover::REMOVE_HISTORY) |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY) |
GetAsMask(data_to_remove, "indexedDB",
- BrowsingDataRemover::REMOVE_INDEXEDDB) |
+ BrowsingDataRemover::DATA_TYPE_INDEXED_DB) |
GetAsMask(data_to_remove, "localStorage",
- BrowsingDataRemover::REMOVE_LOCAL_STORAGE) |
+ BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE) |
GetAsMask(data_to_remove, "pluginData",
- BrowsingDataRemover::REMOVE_PLUGIN_DATA) |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA) |
GetAsMask(data_to_remove, "passwords",
- BrowsingDataRemover::REMOVE_PASSWORDS) |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS) |
GetAsMask(data_to_remove, "serviceWorkers",
- BrowsingDataRemover::REMOVE_SERVICE_WORKERS) |
+ BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS) |
GetAsMask(data_to_remove, "cacheStorage",
- BrowsingDataRemover::REMOVE_CACHE_STORAGE) |
+ BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE) |
GetAsMask(data_to_remove, "webSQL",
- BrowsingDataRemover::REMOVE_WEBSQL) |
+ BrowsingDataRemover::DATA_TYPE_WEB_SQL) |
GetAsMask(data_to_remove, "serverBoundCertificates",
- BrowsingDataRemover::REMOVE_CHANNEL_IDS);
+ BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS);
EXPECT_EQ(expected_removal_mask, removal_mask);
}
@@ -290,23 +304,23 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, RemoveBrowsingDataAll) {
EXPECT_EQ(base::Time::FromDoubleT(1.0), GetBeginTime());
EXPECT_EQ(
- (BrowsingDataRemover::REMOVE_SITE_DATA |
- BrowsingDataRemover::REMOVE_CACHE |
- BrowsingDataRemover::REMOVE_DOWNLOADS |
- BrowsingDataRemover::REMOVE_FORM_DATA |
- BrowsingDataRemover::REMOVE_HISTORY |
- BrowsingDataRemover::REMOVE_PASSWORDS) &
+ (ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_DATA |
+ BrowsingDataRemover::DATA_TYPE_CACHE |
+ BrowsingDataRemover::DATA_TYPE_DOWNLOADS |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS) &
// TODO(benwells): implement clearing of site usage data via the
// browsing data API. https://crbug.com/500801.
- ~BrowsingDataRemover::REMOVE_SITE_USAGE_DATA &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_USAGE_DATA &
// TODO(dmurph): implement clearing of durable storage permission
// via the browsing data API. https://crbug.com/500801.
- ~BrowsingDataRemover::REMOVE_DURABLE_PERMISSION &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_DURABLE_PERMISSION &
// We can't remove plugin data inside a test profile.
- ~BrowsingDataRemover::REMOVE_PLUGIN_DATA &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA &
// TODO(ramyasharma): implement clearing of external protocol data
// via the browsing data API. https://crbug.com/692850.
- ~BrowsingDataRemover::REMOVE_EXTERNAL_PROTOCOL_DATA,
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_EXTERNAL_PROTOCOL_DATA,
GetRemovalMask());
}
@@ -339,45 +353,44 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, BrowsingDataOriginTypeMask) {
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest,
BrowsingDataRemovalMask) {
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "appcache", BrowsingDataRemover::REMOVE_APPCACHE);
+ "appcache", BrowsingDataRemover::DATA_TYPE_APP_CACHE);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "cache", BrowsingDataRemover::REMOVE_CACHE);
+ "cache", BrowsingDataRemover::DATA_TYPE_CACHE);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "cookies", BrowsingDataRemover::REMOVE_COOKIES);
+ "cookies", BrowsingDataRemover::DATA_TYPE_COOKIES);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "downloads", BrowsingDataRemover::REMOVE_DOWNLOADS);
+ "downloads", BrowsingDataRemover::DATA_TYPE_DOWNLOADS);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "fileSystems", BrowsingDataRemover::REMOVE_FILE_SYSTEMS);
+ "fileSystems", BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "formData", BrowsingDataRemover::REMOVE_FORM_DATA);
+ "formData", ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "history", BrowsingDataRemover::REMOVE_HISTORY);
+ "history", ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "indexedDB", BrowsingDataRemover::REMOVE_INDEXEDDB);
+ "indexedDB", BrowsingDataRemover::DATA_TYPE_INDEXED_DB);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "localStorage", BrowsingDataRemover::REMOVE_LOCAL_STORAGE);
+ "localStorage", BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "serverBoundCertificates",
- BrowsingDataRemover::REMOVE_CHANNEL_IDS);
+ "serverBoundCertificates", BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "passwords", BrowsingDataRemover::REMOVE_PASSWORDS);
+ "passwords", ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS);
// We can't remove plugin data inside a test profile.
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "serviceWorkers", BrowsingDataRemover::REMOVE_SERVICE_WORKERS);
+ "serviceWorkers", BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "cacheStorage", BrowsingDataRemover::REMOVE_CACHE_STORAGE);
+ "cacheStorage", BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE);
RunBrowsingDataRemoveWithKeyAndCompareRemovalMask(
- "webSQL", BrowsingDataRemover::REMOVE_WEBSQL);
+ "webSQL", BrowsingDataRemover::DATA_TYPE_WEB_SQL);
}
// Test an arbitrary combination of data types.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest,
BrowsingDataRemovalMaskCombination) {
RunBrowsingDataRemoveFunctionAndCompareRemovalMask(
- "{\"appcache\": true, \"cookies\": true, \"history\": true}",
- BrowsingDataRemover::REMOVE_APPCACHE |
- BrowsingDataRemover::REMOVE_COOKIES |
- BrowsingDataRemover::REMOVE_HISTORY);
+ "{\"appcache\": true, \"cookies\": true, \"history\": true}",
+ BrowsingDataRemover::DATA_TYPE_APP_CACHE |
+ BrowsingDataRemover::DATA_TYPE_COOKIES |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY);
}
// Make sure the remove() function accepts the format produced by settings().
@@ -392,9 +405,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest,
prefs->SetBoolean(browsing_data::prefs::kDeleteHostedAppsData, false);
prefs->SetBoolean(browsing_data::prefs::kDeletePasswords, false);
prefs->SetBoolean(prefs::kClearPluginLSODataEnabled, false);
- int expected_mask = BrowsingDataRemover::REMOVE_CACHE |
- BrowsingDataRemover::REMOVE_DOWNLOADS |
- BrowsingDataRemover::REMOVE_HISTORY;
+ int expected_mask = BrowsingDataRemover::DATA_TYPE_CACHE |
+ BrowsingDataRemover::DATA_TYPE_DOWNLOADS |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
std::string json;
// Scoping for the traces.
{
@@ -427,40 +440,40 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest,
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, ShortcutFunctionRemovalMask) {
RunAndCompareRemovalMask<BrowsingDataRemoveAppcacheFunction>(
- BrowsingDataRemover::REMOVE_APPCACHE);
+ BrowsingDataRemover::DATA_TYPE_APP_CACHE);
RunAndCompareRemovalMask<BrowsingDataRemoveCacheFunction>(
- BrowsingDataRemover::REMOVE_CACHE);
+ BrowsingDataRemover::DATA_TYPE_CACHE);
RunAndCompareRemovalMask<BrowsingDataRemoveCookiesFunction>(
- BrowsingDataRemover::REMOVE_COOKIES |
- BrowsingDataRemover::REMOVE_CHANNEL_IDS);
+ BrowsingDataRemover::DATA_TYPE_COOKIES |
+ BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS);
RunAndCompareRemovalMask<BrowsingDataRemoveDownloadsFunction>(
- BrowsingDataRemover::REMOVE_DOWNLOADS);
+ BrowsingDataRemover::DATA_TYPE_DOWNLOADS);
RunAndCompareRemovalMask<BrowsingDataRemoveFileSystemsFunction>(
- BrowsingDataRemover::REMOVE_FILE_SYSTEMS);
+ BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS);
RunAndCompareRemovalMask<BrowsingDataRemoveFormDataFunction>(
- BrowsingDataRemover::REMOVE_FORM_DATA);
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA);
RunAndCompareRemovalMask<BrowsingDataRemoveHistoryFunction>(
- BrowsingDataRemover::REMOVE_HISTORY);
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY);
RunAndCompareRemovalMask<BrowsingDataRemoveIndexedDBFunction>(
- BrowsingDataRemover::REMOVE_INDEXEDDB);
+ BrowsingDataRemover::DATA_TYPE_INDEXED_DB);
RunAndCompareRemovalMask<BrowsingDataRemoveLocalStorageFunction>(
- BrowsingDataRemover::REMOVE_LOCAL_STORAGE);
+ BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE);
// We can't remove plugin data inside a test profile.
RunAndCompareRemovalMask<BrowsingDataRemovePasswordsFunction>(
- BrowsingDataRemover::REMOVE_PASSWORDS);
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS);
RunAndCompareRemovalMask<BrowsingDataRemoveServiceWorkersFunction>(
- BrowsingDataRemover::REMOVE_SERVICE_WORKERS);
+ BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS);
RunAndCompareRemovalMask<BrowsingDataRemoveWebSQLFunction>(
- BrowsingDataRemover::REMOVE_WEBSQL);
+ BrowsingDataRemover::DATA_TYPE_WEB_SQL);
}
// Test the processing of the 'delete since' preference.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionSince) {
- SetSinceAndVerify(browsing_data::ALL_TIME);
- SetSinceAndVerify(browsing_data::LAST_HOUR);
- SetSinceAndVerify(browsing_data::LAST_DAY);
- SetSinceAndVerify(browsing_data::LAST_WEEK);
- SetSinceAndVerify(browsing_data::FOUR_WEEKS);
+ SetSinceAndVerify(browsing_data::TimePeriod::ALL_TIME);
+ SetSinceAndVerify(browsing_data::TimePeriod::LAST_HOUR);
+ SetSinceAndVerify(browsing_data::TimePeriod::LAST_DAY);
+ SetSinceAndVerify(browsing_data::TimePeriod::LAST_WEEK);
+ SetSinceAndVerify(browsing_data::TimePeriod::FOUR_WEEKS);
}
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionEmpty) {
@@ -469,60 +482,64 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionEmpty) {
// Test straightforward settings, mapped 1:1 to data types.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionSimple) {
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_CACHE, 0,
- BrowsingDataRemover::REMOVE_CACHE);
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_HISTORY, 0,
- BrowsingDataRemover::REMOVE_HISTORY);
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_FORM_DATA, 0,
- BrowsingDataRemover::REMOVE_FORM_DATA);
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_DOWNLOADS, 0,
- BrowsingDataRemover::REMOVE_DOWNLOADS);
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_PASSWORDS, 0,
- BrowsingDataRemover::REMOVE_PASSWORDS);
+ SetPrefsAndVerifySettings(BrowsingDataRemover::DATA_TYPE_CACHE, 0,
+ BrowsingDataRemover::DATA_TYPE_CACHE);
+ SetPrefsAndVerifySettings(
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY, 0,
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY);
+ SetPrefsAndVerifySettings(
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA, 0,
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA);
+ SetPrefsAndVerifySettings(BrowsingDataRemover::DATA_TYPE_DOWNLOADS, 0,
+ BrowsingDataRemover::DATA_TYPE_DOWNLOADS);
+ SetPrefsAndVerifySettings(
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS, 0,
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS);
}
// Test cookie and app data settings.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionSiteData) {
int site_data_no_durable_or_usage_or_external =
- BrowsingDataRemover::REMOVE_SITE_DATA &
- ~BrowsingDataRemover::REMOVE_SITE_USAGE_DATA &
- ~BrowsingDataRemover::REMOVE_DURABLE_PERMISSION &
- ~BrowsingDataRemover::REMOVE_EXTERNAL_PROTOCOL_DATA;
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_DATA &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_USAGE_DATA &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_DURABLE_PERMISSION &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_EXTERNAL_PROTOCOL_DATA;
int site_data_no_plugins_durable_usage_external =
site_data_no_durable_or_usage_or_external &
- ~BrowsingDataRemover::REMOVE_PLUGIN_DATA;
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_COOKIES,
+ SetPrefsAndVerifySettings(BrowsingDataRemover::DATA_TYPE_COOKIES,
UNPROTECTED_WEB,
site_data_no_plugins_durable_usage_external);
SetPrefsAndVerifySettings(
- BrowsingDataRemover::REMOVE_HOSTED_APP_DATA_TESTONLY, PROTECTED_WEB,
- site_data_no_plugins_durable_usage_external);
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HOSTED_APP_DATA_TEST_ONLY,
+ PROTECTED_WEB, site_data_no_plugins_durable_usage_external);
+ SetPrefsAndVerifySettings(BrowsingDataRemover::DATA_TYPE_COOKIES |
+ ChromeBrowsingDataRemoverDelegate::
+ DATA_TYPE_HOSTED_APP_DATA_TEST_ONLY,
+ PROTECTED_WEB | UNPROTECTED_WEB,
+ site_data_no_plugins_durable_usage_external);
SetPrefsAndVerifySettings(
- BrowsingDataRemover::REMOVE_COOKIES |
- BrowsingDataRemover::REMOVE_HOSTED_APP_DATA_TESTONLY,
- PROTECTED_WEB | UNPROTECTED_WEB,
- site_data_no_plugins_durable_usage_external);
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_COOKIES |
- BrowsingDataRemover::REMOVE_PLUGIN_DATA,
- UNPROTECTED_WEB,
- site_data_no_durable_or_usage_or_external);
+ BrowsingDataRemover::DATA_TYPE_COOKIES |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA,
+ UNPROTECTED_WEB, site_data_no_durable_or_usage_or_external);
}
// Test an arbitrary assortment of settings.
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionAssorted) {
int site_data_no_plugins_durable_usage_external =
- BrowsingDataRemover::REMOVE_SITE_DATA &
- ~BrowsingDataRemover::REMOVE_DURABLE_PERMISSION &
- ~BrowsingDataRemover::REMOVE_SITE_USAGE_DATA &
- ~BrowsingDataRemover::REMOVE_PLUGIN_DATA &
- ~BrowsingDataRemover::REMOVE_EXTERNAL_PROTOCOL_DATA;
-
- SetPrefsAndVerifySettings(BrowsingDataRemover::REMOVE_COOKIES |
- BrowsingDataRemover::REMOVE_HISTORY |
- BrowsingDataRemover::REMOVE_DOWNLOADS,
- UNPROTECTED_WEB,
- site_data_no_plugins_durable_usage_external |
- BrowsingDataRemover::REMOVE_HISTORY |
- BrowsingDataRemover::REMOVE_DOWNLOADS);
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_DATA &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_DURABLE_PERMISSION &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_USAGE_DATA &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA &
+ ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_EXTERNAL_PROTOCOL_DATA;
+
+ SetPrefsAndVerifySettings(
+ BrowsingDataRemover::DATA_TYPE_COOKIES |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY |
+ BrowsingDataRemover::DATA_TYPE_DOWNLOADS,
+ UNPROTECTED_WEB,
+ site_data_no_plugins_durable_usage_external |
+ ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY |
+ BrowsingDataRemover::DATA_TYPE_DOWNLOADS);
}
diff --git a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
index bd24b95add7..866e14da134 100644
--- a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
@@ -72,7 +72,7 @@ void StoreString(std::string* result,
void StoreDigest(std::vector<uint8_t>* digest,
const base::Closure& callback,
const base::Value* value) {
- const base::BinaryValue* binary = nullptr;
+ const base::Value* binary = nullptr;
const bool is_binary = value->GetAsBinary(&binary);
EXPECT_TRUE(is_binary) << "Unexpected value in StoreDigest";
if (is_binary) {
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 9aa074a35ff..0ffe5d98ca0 100644
--- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/extensions/api/declarative_content/default_content_predicate_evaluators.h"
#include "chrome/browser/extensions/api/management/chrome_management_api_delegate.h"
#include "chrome/browser/extensions/api/metrics_private/chrome_metrics_private_delegate.h"
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
#include "chrome/browser/extensions/api/storage/managed_value_store_cache.h"
#include "chrome/browser/extensions/api/storage/sync_value_store_cache.h"
#include "chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.h"
@@ -168,6 +169,16 @@ MetricsPrivateDelegate* ChromeExtensionsAPIClient::GetMetricsPrivateDelegate() {
return metrics_private_delegate_.get();
}
+NetworkingCastPrivateDelegate*
+ChromeExtensionsAPIClient::GetNetworkingCastPrivateDelegate() {
+#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_MACOSX)
+ if (!networking_cast_private_delegate_)
+ networking_cast_private_delegate_ =
+ ChromeNetworkingCastPrivateDelegate::Create();
+#endif
+ return networking_cast_private_delegate_.get();
+}
+
#if defined(OS_CHROMEOS)
NonNativeFileSystemDelegate*
ChromeExtensionsAPIClient::GetNonNativeFileSystemDelegate() {
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 55611b757ca..bd5c11636fd 100644
--- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h
+++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h
@@ -54,6 +54,7 @@ class ChromeExtensionsAPIClient : public ExtensionsAPIClient {
const override;
ManagementAPIDelegate* CreateManagementAPIDelegate() const override;
MetricsPrivateDelegate* GetMetricsPrivateDelegate() override;
+ NetworkingCastPrivateDelegate* GetNetworkingCastPrivateDelegate() override;
#if defined(OS_CHROMEOS)
NonNativeFileSystemDelegate* GetNonNativeFileSystemDelegate() override;
@@ -67,6 +68,8 @@ class ChromeExtensionsAPIClient : public ExtensionsAPIClient {
private:
std::unique_ptr<ChromeMetricsPrivateDelegate> metrics_private_delegate_;
+ std::unique_ptr<NetworkingCastPrivateDelegate>
+ networking_cast_private_delegate_;
#if defined(OS_CHROMEOS)
std::unique_ptr<NonNativeFileSystemDelegate> non_native_file_system_delegate_;
diff --git a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
index a3b40642e23..71649982225 100644
--- a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
@@ -81,7 +81,7 @@ CloudPrintPrivateGetHostNameFunction::~CloudPrintPrivateGetHostNameFunction() {
}
bool CloudPrintPrivateGetHostNameFunction::RunAsync() {
- SetResult(base::MakeUnique<base::StringValue>(
+ SetResult(base::MakeUnique<base::Value>(
CloudPrintTestsDelegate::Get()
? CloudPrintTestsDelegate::Get()->GetHostName()
: net::GetHostName()));
@@ -129,7 +129,7 @@ CloudPrintPrivateGetClientIdFunction::~CloudPrintPrivateGetClientIdFunction() {
}
bool CloudPrintPrivateGetClientIdFunction::RunAsync() {
- SetResult(base::MakeUnique<base::StringValue>(
+ SetResult(base::MakeUnique<base::Value>(
CloudPrintTestsDelegate::Get()
? CloudPrintTestsDelegate::Get()->GetClientId()
: google_apis::GetOAuth2ClientID(google_apis::CLIENT_CLOUD_PRINT)));
diff --git a/chromium/chrome/browser/extensions/api/commands/OWNERS b/chromium/chrome/browser/extensions/api/commands/OWNERS
index 32f119ecf4c..5b3c2a89fc5 100644
--- a/chromium/chrome/browser/extensions/api/commands/OWNERS
+++ b/chromium/chrome/browser/extensions/api/commands/OWNERS
@@ -1,3 +1,6 @@
# Anyone in the parent directories can review changes to this directory,
# but the following people are the most knowledgeable:
finnur@chromium.org
+
+# TEAM: extensions-dev@chromium.org
+# COMPONENT: Platform>Extensions>API
diff --git a/chromium/chrome/browser/extensions/api/commands/command_service.cc b/chromium/chrome/browser/extensions/api/commands/command_service.cc
index dc0c704e72d..a5bc5e0b407 100644
--- a/chromium/chrome/browser/extensions/api/commands/command_service.cc
+++ b/chromium/chrome/browser/extensions/api/commands/command_service.cc
@@ -8,9 +8,11 @@
#include <vector>
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/extensions/api/commands/commands.h"
#include "chrome/browser/extensions/extension_commands_global_registry.h"
@@ -85,7 +87,7 @@ std::string StripCurrentPlatform(const std::string& key) {
void SetInitialBindingsHaveBeenAssigned(
ExtensionPrefs* prefs, const std::string& extension_id) {
prefs->UpdateExtensionPref(extension_id, kInitialBindingsHaveBeenAssigned,
- new base::Value(true));
+ base::MakeUnique<base::Value>(true));
}
bool InitialBindingsHaveBeenAssigned(
@@ -114,9 +116,8 @@ void MergeSuggestedKeyPrefs(
suggested_key_prefs = std::move(new_prefs);
}
- extension_prefs->UpdateExtensionPref(extension_id,
- kCommands,
- suggested_key_prefs.release());
+ extension_prefs->UpdateExtensionPref(extension_id, kCommands,
+ std::move(suggested_key_prefs));
}
} // namespace
@@ -141,8 +142,9 @@ CommandService::CommandService(content::BrowserContext* context)
CommandService::~CommandService() {
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<CommandService> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<CommandService>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<CommandService>*
@@ -276,12 +278,12 @@ bool CommandService::AddKeybindingPref(
RemoveKeybindingPrefs(extension_id, command_name);
// Set the keybinding pref.
- base::DictionaryValue* keybinding = new base::DictionaryValue();
+ auto keybinding = base::MakeUnique<base::DictionaryValue>();
keybinding->SetString(kExtension, extension_id);
keybinding->SetString(kCommandName, command_name);
keybinding->SetBoolean(kGlobal, global);
- bindings->Set(key, keybinding);
+ bindings->Set(key, std::move(keybinding));
// Set the was_assigned pref for the suggested key.
std::unique_ptr<base::DictionaryValue> command_keys(
@@ -289,7 +291,7 @@ bool CommandService::AddKeybindingPref(
command_keys->SetBoolean(kSuggestedKeyWasAssigned, true);
std::unique_ptr<base::DictionaryValue> suggested_key_prefs(
new base::DictionaryValue);
- suggested_key_prefs->Set(command_name, command_keys.release());
+ suggested_key_prefs->Set(command_name, std::move(command_keys));
MergeSuggestedKeyPrefs(extension_id, ExtensionPrefs::Get(profile_),
std::move(suggested_key_prefs));
@@ -645,7 +647,7 @@ void CommandService::UpdateExtensionSuggestedCommandPrefs(
command_keys->SetString(
kSuggestedKey,
Command::AcceleratorToString(command.accelerator()));
- suggested_key_prefs->Set(command.command_name(), command_keys.release());
+ suggested_key_prefs->Set(command.command_name(), std::move(command_keys));
}
}
@@ -662,7 +664,7 @@ void CommandService::UpdateExtensionSuggestedCommandPrefs(
kSuggestedKey,
Command::AcceleratorToString(browser_action_command->accelerator()));
suggested_key_prefs->Set(browser_action_command->command_name(),
- command_keys.release());
+ std::move(command_keys));
}
const Command* page_action_command =
@@ -674,7 +676,7 @@ void CommandService::UpdateExtensionSuggestedCommandPrefs(
kSuggestedKey,
Command::AcceleratorToString(page_action_command->accelerator()));
suggested_key_prefs->Set(page_action_command->command_name(),
- command_keys.release());
+ std::move(command_keys));
}
// Merge into current prefs, if present.
@@ -718,9 +720,8 @@ void CommandService::RemoveDefunctExtensionSuggestedCommandPrefs(
}
}
- extension_prefs->UpdateExtensionPref(extension->id(),
- kCommands,
- suggested_key_prefs.release());
+ extension_prefs->UpdateExtensionPref(extension->id(), kCommands,
+ std::move(suggested_key_prefs));
}
}
diff --git a/chromium/chrome/browser/extensions/api/commands/command_service_browsertest.cc b/chromium/chrome/browser/extensions/api/commands/command_service_browsertest.cc
index 0f69acbf453..636cffe6ef4 100644
--- a/chromium/chrome/browser/extensions/api/commands/command_service_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/commands/command_service_browsertest.cc
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/commands/command_service.h"
#include "chrome/browser/extensions/extension_apitest.h"
@@ -110,11 +114,11 @@ IN_PROC_BROWSER_TEST_F(CommandServiceTest,
// another platform.
std::string anotherPlatformKey = GetAnotherCommandPlatform() + ":Alt+G";
const char kNamedCommandName[] = "toggle-feature";
- base::DictionaryValue* keybinding = new base::DictionaryValue();
+ auto keybinding = base::MakeUnique<base::DictionaryValue>();
keybinding->SetString("extension", extension->id());
keybinding->SetString("command_name", kNamedCommandName);
keybinding->SetBoolean("global", false);
- bindings->Set(anotherPlatformKey, keybinding);
+ bindings->Set(anotherPlatformKey, std::move(keybinding));
CommandService* command_service = CommandService::Get(browser()->profile());
command_service->RemoveKeybindingPrefs(extension->id(), kNamedCommandName);
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc
index 4a7e4151999..83169fca6d7 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc
@@ -27,8 +27,8 @@ ContentSettingsService* ContentSettingsService::Get(
BrowserContextKeyedAPIFactory<ContentSettingsService>*
ContentSettingsService::GetFactoryInstance() {
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<ContentSettingsService> > factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<ContentSettingsService>>::DestructorAtExit
+ factory = LAZY_INSTANCE_INITIALIZER;
return factory.Pointer();
}
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 0b1c48ddc0e..6f2a5797051 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
@@ -245,7 +245,7 @@ void ContentSettingsStore::ClearContentSettingsForExtension(
}
}
-base::ListValue* ContentSettingsStore::GetSettingsForExtension(
+std::unique_ptr<base::ListValue> ContentSettingsStore::GetSettingsForExtension(
const std::string& extension_id,
ExtensionPrefsScope scope) const {
base::AutoLock lock(lock_);
@@ -253,7 +253,7 @@ base::ListValue* ContentSettingsStore::GetSettingsForExtension(
if (!map)
return nullptr;
- base::ListValue* settings = new base::ListValue();
+ auto settings = base::MakeUnique<base::ListValue>();
for (const auto& it : *map) {
const auto& key = it.first;
std::unique_ptr<RuleIterator> rule_iterator(
@@ -294,8 +294,8 @@ void ContentSettingsStore::SetExtensionContentSettingFromList(
const base::ListValue* list,
ExtensionPrefsScope scope) {
for (const auto& value : *list) {
- base::DictionaryValue* dict;
- if (!value->GetAsDictionary(&dict)) {
+ const base::DictionaryValue* dict = nullptr;
+ if (!value.GetAsDictionary(&dict)) {
NOTREACHED();
continue;
}
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 0567613a172..3a9033a4747 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
@@ -80,8 +80,9 @@ class ContentSettingsStore
// Serializes all content settings set by the extension with ID |extension_id|
// and returns them as a ListValue. The caller takes ownership of the returned
// value.
- base::ListValue* GetSettingsForExtension(const std::string& extension_id,
- ExtensionPrefsScope scope) const;
+ std::unique_ptr<base::ListValue> GetSettingsForExtension(
+ const std::string& extension_id,
+ ExtensionPrefsScope scope) const;
// Deserializes content settings rules from |list| and applies them as set by
// the extension with ID |extension_id|.
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
index 38e7d966545..850814c9026 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -258,7 +259,7 @@ void CookiesGetFunction::GetCookieCallback(const net::CookieList& cookie_list) {
// The cookie doesn't exist; return null.
if (!results_)
- SetResult(base::Value::CreateNullValue());
+ SetResult(base::MakeUnique<base::Value>());
bool rv = BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -555,12 +556,12 @@ ExtensionFunction::ResponseAction CookiesGetAllCookieStoresFunction::Run() {
std::vector<cookies::CookieStore> cookie_stores;
if (original_tab_ids->GetSize() > 0) {
cookie_stores.push_back(cookies_helpers::CreateCookieStore(
- original_profile, original_tab_ids.release()));
+ original_profile, std::move(original_tab_ids)));
}
if (incognito_tab_ids.get() && incognito_tab_ids->GetSize() > 0 &&
incognito_profile) {
cookie_stores.push_back(cookies_helpers::CreateCookieStore(
- incognito_profile, incognito_tab_ids.release()));
+ incognito_profile, std::move(incognito_tab_ids)));
}
return RespondNow(
ArgumentList(GetAllCookieStores::Results::Create(cookie_stores)));
@@ -579,8 +580,9 @@ void CookiesAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<CookiesAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<CookiesAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<CookiesAPI>* CookiesAPI::GetFactoryInstance() {
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc
index b5073942cf1..bcb3066e597 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -8,6 +8,7 @@
#include <stddef.h>
+#include <utility>
#include <vector>
#include "base/logging.h"
@@ -103,12 +104,13 @@ Cookie CreateCookie(const net::CanonicalCookie& canonical_cookie,
return cookie;
}
-CookieStore CreateCookieStore(Profile* profile, base::ListValue* tab_ids) {
+CookieStore CreateCookieStore(Profile* profile,
+ std::unique_ptr<base::ListValue> tab_ids) {
DCHECK(profile);
DCHECK(tab_ids);
base::DictionaryValue dict;
dict.SetString(keys::kIdKey, GetStoreIdFromProfile(profile));
- dict.Set(keys::kTabIdsKey, tab_ids);
+ dict.Set(keys::kTabIdsKey, std::move(tab_ids));
CookieStore cookie_store;
bool rv = CookieStore::Populate(dict, &cookie_store);
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h
index 8d3b2d516b6..28a19415b3a 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_helpers.h
@@ -10,6 +10,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_COOKIES_COOKIES_HELPERS_H_
#define CHROME_BROWSER_EXTENSIONS_API_COOKIES_COOKIES_HELPERS_H_
+#include <memory>
#include <string>
#include <vector>
@@ -50,8 +51,9 @@ api::cookies::Cookie CreateCookie(const net::CanonicalCookie& cookie,
const std::string& store_id);
// Constructs a new CookieStore object as defined by the cookies API.
-api::cookies::CookieStore CreateCookieStore(Profile* profile,
- base::ListValue* tab_ids);
+api::cookies::CookieStore CreateCookieStore(
+ Profile* profile,
+ std::unique_ptr<base::ListValue> tab_ids);
// Retrieves all cookies from the given cookie store corresponding to the given
// URL. If the URL is empty, all cookies in the cookie store are retrieved.
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_unittest.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_unittest.cc
index 8eab2626204..850dc97dd84 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_unittest.cc
@@ -5,11 +5,12 @@
// Tests common functionality used by the Chrome Extensions Cookies API
// implementation.
-#include "testing/gtest/include/gtest/gtest.h"
-
#include <stddef.h>
+#include <utility>
+
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/cookies/cookies_api_constants.h"
#include "chrome/browser/extensions/api/cookies/cookies_helpers.h"
@@ -18,6 +19,7 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using extensions::api::cookies::Cookie;
@@ -119,10 +121,10 @@ TEST_F(ExtensionCookiesTest, ExtensionTypeCreation) {
EXPECT_EQ(10000, *cookie2.expiration_date);
TestingProfile profile;
- base::ListValue* tab_ids_list = new base::ListValue();
+ auto tab_ids_list = base::MakeUnique<base::ListValue>();
std::vector<int> tab_ids;
CookieStore cookie_store =
- cookies_helpers::CreateCookieStore(&profile, tab_ids_list);
+ cookies_helpers::CreateCookieStore(&profile, std::move(tab_ids_list));
EXPECT_EQ("0", cookie_store.id);
EXPECT_EQ(tab_ids, cookie_store.tab_ids);
}
@@ -168,9 +170,9 @@ TEST_F(ExtensionCookiesTest, DomainMatching) {
for (size_t i = 0; i < arraysize(tests); ++i) {
// Build up the Params struct.
base::ListValue args;
- base::DictionaryValue* dict = new base::DictionaryValue();
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString(keys::kDomainKey, std::string(tests[i].filter));
- args.Set(0, dict);
+ args.Set(0, std::move(dict));
std::unique_ptr<GetAll::Params> params(GetAll::Params::Create(args));
cookies_helpers::MatchFilter filter(&params->details);
diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
index 88d7f073bde..2e48eb88dff 100644
--- a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -391,8 +391,8 @@ void ExtensionDevToolsClientHost::SendMessageToBackend(
protocol_request.SetInteger("id", request_id);
protocol_request.SetString("method", method);
if (command_params) {
- protocol_request.Set("params",
- command_params->additional_properties.DeepCopy());
+ protocol_request.Set(
+ "params", command_params->additional_properties.CreateDeepCopy());
}
std::string json_args;
diff --git a/chromium/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc b/chromium/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
index b990d137381..d87d88f900e 100644
--- a/chromium/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
@@ -9,6 +9,7 @@
// RulesRegistryWithCache.
#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_environment.h"
@@ -242,11 +243,11 @@ TEST_F(RulesRegistryWithCacheTest, DeclarativeRulesStored) {
EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
extension_prefs->UpdateExtensionPref(extension1_->id(), rules_stored_key,
- new base::Value(false));
+ base::MakeUnique<base::Value>(false));
EXPECT_FALSE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
extension_prefs->UpdateExtensionPref(extension1_->id(), rules_stored_key,
- new base::Value(true));
+ base::MakeUnique<base::Value>(true));
EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
// 2. Test writing behavior.
@@ -325,7 +326,7 @@ TEST_F(RulesRegistryWithCacheTest, RulesStoredFlagMultipleRegistries) {
// Update the flag for the first registry.
extension_prefs->UpdateExtensionPref(extension1_->id(), rules_stored_key1,
- new base::Value(false));
+ base::MakeUnique<base::Value>(false));
EXPECT_FALSE(cache_delegate1->GetDeclarativeRulesStored(extension1_->id()));
EXPECT_TRUE(cache_delegate2->GetDeclarativeRulesStored(extension1_->id()));
}
@@ -342,13 +343,9 @@ TEST_F(RulesRegistryWithCacheTest, RulesPreservedAcrossRestart) {
// 1. Add an extension, before rules registry gets created.
std::string error;
- scoped_refptr<Extension> extension(
- LoadManifestUnchecked("permissions",
- "web_request_all_host_permissions.json",
- Manifest::INVALID_LOCATION,
- Extension::NO_FLAGS,
- extension1_->id(),
- &error));
+ scoped_refptr<Extension> extension(LoadManifestUnchecked(
+ "permissions", "web_request_all_host_permissions.json",
+ Manifest::UNPACKED, Extension::NO_FLAGS, extension1_->id(), &error));
ASSERT_TRUE(error.empty());
extension_service->AddExtension(extension.get());
EXPECT_TRUE(extensions::ExtensionRegistry::Get(env_.profile())
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc b/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
index 45b6c3b4a43..9c5db12dfe2 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
@@ -20,6 +20,7 @@
#include "extensions/browser/api/declarative/rules_registry_service.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/browser/extension_util.h"
#include "extensions/common/extension_id.h"
namespace extensions {
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 6da57a16b91..5185a417e75 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc
@@ -170,7 +170,7 @@ static bool AppendJSStringsToCPPStrings(const base::ListValue& append_strings,
it != append_strings.end();
++it) {
std::string value;
- if ((*it)->GetAsString(&value)) {
+ if (it->GetAsString(&value)) {
append_to->push_back(value);
} else {
return false;
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
index 2f52275a2f0..d69a933eaf5 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
@@ -99,7 +99,7 @@ DeclarativeContentCssConditionTracker::PerWebContentsTracker::
void DeclarativeContentCssConditionTracker::PerWebContentsTracker::
OnWebContentsNavigation(content::NavigationHandle* navigation_handle) {
- if (navigation_handle->IsSamePage()) {
+ if (navigation_handle->IsSameDocument()) {
// Within-page navigations don't change the set of elements that
// exist, and we only support filtering on the top-level URL, so
// this can't change which rules match.
diff --git a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
index 348d2c8462d..e5ecb2cf045 100644
--- a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
@@ -28,6 +28,7 @@
#include "extensions/common/extension.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -54,7 +55,7 @@ std::unique_ptr<WebRequestActionSet> CreateSetOfActions(const char* json) {
it != parsed_list->end();
++it) {
const base::DictionaryValue* dict;
- CHECK((*it)->GetAsDictionary(&dict));
+ CHECK(it->GetAsDictionary(&dict));
actions.push_back(dict->CreateDeepCopy());
}
@@ -146,7 +147,8 @@ bool WebRequestActionWithThreadsTest::ActionWorksOnRequest(
const WebRequestActionSet* action_set,
RequestStage stage) {
std::unique_ptr<net::URLRequest> regular_request(
- context_.CreateRequest(GURL(url_string), net::DEFAULT_PRIORITY, NULL));
+ context_.CreateRequest(GURL(url_string), net::DEFAULT_PRIORITY, NULL,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
std::list<LinkedPtrEventResponseDelta> deltas;
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders(""));
diff --git a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
index 474367a592a..596bbf3c6ec 100644
--- a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -8,11 +8,13 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@@ -25,6 +27,7 @@
#include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
#include "extensions/browser/api/web_request/web_request_api_helpers.h"
#include "net/base/request_priority.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -100,24 +103,23 @@ class WebRequestRulesRegistryTest : public testing::Test {
// Returns a rule that roughly matches http://*.example.com and
// https://www.example.com and cancels it
linked_ptr<api::events::Rule> CreateRule1() {
- base::ListValue* scheme_http = new base::ListValue();
+ auto scheme_http = base::MakeUnique<base::ListValue>();
scheme_http->AppendString("http");
- base::DictionaryValue* http_condition_dict = new base::DictionaryValue();
- http_condition_dict->Set(keys2::kSchemesKey, scheme_http);
+ auto http_condition_dict = base::MakeUnique<base::DictionaryValue>();
http_condition_dict->SetString(keys2::kHostSuffixKey, "example.com");
base::DictionaryValue http_condition_url_filter;
- http_condition_url_filter.Set(keys::kUrlKey, http_condition_dict);
http_condition_url_filter.SetString(keys::kInstanceTypeKey,
keys::kRequestMatcherType);
- base::ListValue* scheme_https = new base::ListValue();
scheme_http->AppendString("https");
- base::DictionaryValue* https_condition_dict = new base::DictionaryValue();
- https_condition_dict->Set(keys2::kSchemesKey, scheme_https);
+ auto https_condition_dict = base::MakeUnique<base::DictionaryValue>();
+ https_condition_dict->Set(keys2::kSchemesKey,
+ base::MakeUnique<base::ListValue>());
https_condition_dict->SetString(keys2::kHostSuffixKey, "example.com");
https_condition_dict->SetString(keys2::kHostPrefixKey, "www");
base::DictionaryValue https_condition_url_filter;
- https_condition_url_filter.Set(keys::kUrlKey, https_condition_dict);
+ https_condition_url_filter.Set(keys::kUrlKey,
+ std::move(https_condition_dict));
https_condition_url_filter.SetString(keys::kInstanceTypeKey,
keys::kRequestMatcherType);
@@ -128,6 +130,9 @@ class WebRequestRulesRegistryTest : public testing::Test {
rule->id.reset(new std::string(kRuleId1));
rule->priority.reset(new int(100));
rule->actions.push_back(action_dict.CreateDeepCopy());
+ http_condition_dict->Set(keys2::kSchemesKey, std::move(scheme_http));
+ http_condition_url_filter.Set(keys::kUrlKey,
+ std::move(http_condition_dict));
rule->conditions.push_back(http_condition_url_filter.CreateDeepCopy());
rule->conditions.push_back(https_condition_url_filter.CreateDeepCopy());
return rule;
@@ -170,10 +175,10 @@ class WebRequestRulesRegistryTest : public testing::Test {
// contains index.html.
linked_ptr<api::events::Rule> CreateIgnoreRule() {
base::DictionaryValue condition_dict;
- base::DictionaryValue* http_condition_dict = new base::DictionaryValue();
+ auto http_condition_dict = base::MakeUnique<base::DictionaryValue>();
http_condition_dict->SetString(keys2::kPathContainsKey, "index.html");
condition_dict.SetString(keys::kInstanceTypeKey, keys::kRequestMatcherType);
- condition_dict.Set(keys::kUrlKey, http_condition_dict);
+ condition_dict.Set(keys::kUrlKey, std::move(http_condition_dict));
base::DictionaryValue action_dict;
action_dict.SetString(keys::kInstanceTypeKey, keys::kIgnoreRulesType);
@@ -279,8 +284,8 @@ TEST_F(WebRequestRulesRegistryTest, AddRulesImpl) {
GURL http_url("http://www.example.com");
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> http_request(
- context.CreateRequest(http_url, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> http_request(context.CreateRequest(
+ http_url, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data(http_request.get(), ON_BEFORE_REQUEST);
matches = registry->GetMatches(request_data);
EXPECT_EQ(2u, matches.size());
@@ -295,8 +300,8 @@ TEST_F(WebRequestRulesRegistryTest, AddRulesImpl) {
base::ContainsKey(matches_ids, std::make_pair(kExtensionId, kRuleId2)));
GURL foobar_url("http://www.foobar.com");
- std::unique_ptr<net::URLRequest> foobar_request(
- context.CreateRequest(foobar_url, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> foobar_request(context.CreateRequest(
+ foobar_url, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
request_data.request = foobar_request.get();
matches = registry->GetMatches(request_data);
EXPECT_EQ(1u, matches.size());
@@ -422,8 +427,8 @@ TEST_F(WebRequestRulesRegistryTest, Precedences) {
GURL url("http://www.google.com");
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> request(
- context.CreateRequest(url, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ url, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data(request.get(), ON_BEFORE_REQUEST);
std::list<LinkedPtrEventResponseDelta> deltas =
registry->CreateDeltas(NULL, request_data, false);
@@ -471,8 +476,8 @@ TEST_F(WebRequestRulesRegistryTest, Priorities) {
GURL url("http://www.google.com/index.html");
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> request(
- context.CreateRequest(url, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ url, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data(request.get(), ON_BEFORE_REQUEST);
std::list<LinkedPtrEventResponseDelta> deltas =
registry->CreateDeltas(NULL, request_data, false);
@@ -545,8 +550,8 @@ TEST_F(WebRequestRulesRegistryTest, IgnoreRulesByTag) {
GURL url("http://www.foo.com/test");
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> request(
- context.CreateRequest(url, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ url, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data(request.get(), ON_BEFORE_REQUEST);
std::list<LinkedPtrEventResponseDelta> deltas =
registry->CreateDeltas(NULL, request_data, false);
@@ -595,8 +600,8 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesCheckFulfilled) {
GURL http_url("http://www.example.com");
net::TestURLRequestContext context;
- std::unique_ptr<net::URLRequest> http_request(
- context.CreateRequest(http_url, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> http_request(context.CreateRequest(
+ http_url, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data(http_request.get(), ON_BEFORE_REQUEST);
matches = registry->GetMatches(request_data);
EXPECT_EQ(1u, matches.size());
@@ -654,8 +659,8 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesDifferentUrls) {
for (size_t i = 0; i < arraysize(matchingRuleIds); ++i) {
// Construct the inputs.
- std::unique_ptr<net::URLRequest> http_request(
- context.CreateRequest(urls[i], net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> http_request(context.CreateRequest(
+ urls[i], net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data(http_request.get(), ON_BEFORE_REQUEST);
http_request->set_first_party_for_cookies(firstPartyUrls[i]);
// Now run both rules on the input.
@@ -803,16 +808,16 @@ TEST_F(WebRequestRulesRegistryTest, CheckOriginAndPathRegEx) {
// No match because match is in the query parameter.
GURL url1("http://bar.com/index.html?foo.com");
- std::unique_ptr<net::URLRequest> request1(
- context.CreateRequest(url1, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> request1(context.CreateRequest(
+ url1, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data1(request1.get(), ON_BEFORE_REQUEST);
deltas = registry->CreateDeltas(NULL, request_data1, false);
EXPECT_EQ(0u, deltas.size());
// This is a correct match.
GURL url2("http://foo.com/index.html");
- std::unique_ptr<net::URLRequest> request2(
- context.CreateRequest(url2, net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> request2(context.CreateRequest(
+ url2, net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
WebRequestData request_data2(request2.get(), ON_BEFORE_REQUEST);
deltas = registry->CreateDeltas(NULL, request_data2, false);
EXPECT_EQ(1u, deltas.size());
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
index 3d120986991..cc6b793728e 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
@@ -206,23 +206,28 @@ IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, MAYBE_ChooseDesktopMedia) {
webrtc::kFullDesktopScreenId)},
// cancelDialog()
{true, true, false, false, content::DesktopMediaID(), true},
+
+ // Some test cases below are commented out because getUserMedia will fail
+ // due to the fake source id currently.
+ // TODO(braveyao): get these cases working again. http://crbug.com/699201
+
// tabShareWithAudioGetStream()
- {false, false, true, true,
- content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 0,
- true)},
+ //{false, false, true, true,
+ // content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 0,
+ // true)},
// windowShareWithAudioGetStream()
- {false, true, false, true,
- content::DesktopMediaID(content::DesktopMediaID::TYPE_WINDOW, 0, true)},
+ //{false, true, false, true,
+ //content::DesktopMediaID(content::DesktopMediaID::TYPE_WINDOW, 0, true)},
// screenShareWithAudioGetStream()
{true, false, false, true,
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
webrtc::kFullDesktopScreenId, true)},
// tabShareWithoutAudioGetStream()
- {false, false, true, true,
- content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 0)},
+ //{false, false, true, true,
+ //content::DesktopMediaID(content::DesktopMediaID::TYPE_WEB_CONTENTS, 0)},
// windowShareWithoutAudioGetStream()
- {false, true, false, true,
- content::DesktopMediaID(content::DesktopMediaID::TYPE_WINDOW, 0)},
+ //{false, true, false, true,
+ // content::DesktopMediaID(content::DesktopMediaID::TYPE_WINDOW, 0)},
// screenShareWithoutAudioGetStream()
{true, false, false, true,
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
index a92d060ea89..4b8736571aa 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -67,7 +67,7 @@ void DesktopCaptureChooseDesktopMediaFunctionBase::Cancel() {
scoped_refptr<DesktopCaptureChooseDesktopMediaFunctionBase> self(this);
if (picker_) {
picker_.reset();
- SetResult(base::MakeUnique<base::StringValue>(std::string()));
+ SetResult(base::MakeUnique<base::Value>(std::string()));
SendResponse(true);
}
}
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 ccd13f8af48..6f24801965e 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
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
+#include "base/guid.h"
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
@@ -29,6 +30,7 @@
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/install_verifier.h"
+#include "chrome/browser/extensions/path_util.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "chrome/browser/extensions/shared_module_service.h"
#include "chrome/browser/extensions/unpacked_installer.h"
@@ -42,6 +44,7 @@
#include "chrome/browser/ui/extensions/app_launch_params.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/extensions/extension_loader_handler.h"
#include "chrome/common/extensions/api/developer_private.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/pref_names.h"
@@ -57,6 +60,7 @@
#include "extensions/browser/api/file_handlers/app_file_handler_util.h"
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/app_window_registry.h"
+#include "extensions/browser/content_verifier.h"
#include "extensions/browser/error_map.h"
#include "extensions/browser/extension_error.h"
#include "extensions/browser/extension_prefs.h"
@@ -72,6 +76,7 @@
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_handlers/options_page_info.h"
+#include "extensions/common/manifest_url_handlers.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/grit/extensions_browser_resources.h"
#include "storage/browser/fileapi/external_mount_points.h"
@@ -106,6 +111,10 @@ const char kCannotUpdateSupervisedProfileSettingsError[] =
"Cannot change settings for a supervised profile.";
const char kNoOptionsPageForExtensionError[] =
"Extension does not have an options page.";
+const char kCannotRepairHealthyExtension[] =
+ "Cannot repair a healthy extension.";
+const char kCannotRepairPolicyExtension[] =
+ "Cannot repair a policy-installed extension.";
const char kUnpackedAppsFolder[] = "apps_target";
const char kManifestFile[] = "manifest.json";
@@ -148,8 +157,8 @@ void PerformVerificationCheck(content::BrowserContext* context) {
bool should_do_verification_check = false;
for (const scoped_refptr<const Extension>& extension : *extensions) {
if (ui_util::ShouldDisplayInExtensionSettings(extension.get(), context) &&
- ((prefs->GetDisableReasons(extension->id()) &
- Extension::DISABLE_NOT_VERIFIED) != 0)) {
+ prefs->HasDisableReason(extension->id(),
+ Extension::DISABLE_NOT_VERIFIED)) {
should_do_verification_check = true;
break;
}
@@ -188,8 +197,29 @@ namespace GetItemsInfo = api::developer_private::GetItemsInfo;
namespace PackDirectory = api::developer_private::PackDirectory;
namespace Reload = api::developer_private::Reload;
-static base::LazyInstance<BrowserContextKeyedAPIFactory<DeveloperPrivateAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<DeveloperPrivateAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
+
+class DeveloperPrivateAPI::WebContentsTracker
+ : public content::WebContentsObserver {
+ public:
+ WebContentsTracker(base::WeakPtr<DeveloperPrivateAPI> api,
+ content::WebContents* web_contents)
+ : content::WebContentsObserver(web_contents), api_(api) {}
+
+ private:
+ ~WebContentsTracker() override = default;
+
+ void WebContentsDestroyed() override {
+ if (api_)
+ api_->allowed_unpacked_paths_.erase(web_contents());
+ delete this;
+ }
+
+ base::WeakPtr<DeveloperPrivateAPI> api_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebContentsTracker);
+};
// static
BrowserContextKeyedAPIFactory<DeveloperPrivateAPI>*
@@ -204,7 +234,7 @@ DeveloperPrivateAPI* DeveloperPrivateAPI::Get(
}
DeveloperPrivateAPI::DeveloperPrivateAPI(content::BrowserContext* context)
- : profile_(Profile::FromBrowserContext(context)) {
+ : profile_(Profile::FromBrowserContext(context)), weak_factory_(this) {
RegisterNotifications();
}
@@ -412,8 +442,42 @@ void DeveloperPrivateEventRouter::BroadcastItemStateChangedHelper(
event_router_->BroadcastEvent(std::move(event));
}
-void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) {
+DeveloperPrivateAPI::UnpackedRetryId DeveloperPrivateAPI::AddUnpackedPath(
+ content::WebContents* web_contents,
+ const base::FilePath& path) {
+ DCHECK(web_contents);
last_unpacked_directory_ = path;
+ IdToPathMap& paths = allowed_unpacked_paths_[web_contents];
+ if (paths.empty()) {
+ // This is the first we've added this WebContents. Track its lifetime so we
+ // can clean up the paths when it is destroyed.
+ // WebContentsTracker manages its own lifetime.
+ new WebContentsTracker(weak_factory_.GetWeakPtr(), web_contents);
+ } else {
+ auto existing = std::find_if(
+ paths.begin(), paths.end(),
+ [path](const std::pair<std::string, base::FilePath>& entry) {
+ return entry.second == path;
+ });
+ if (existing != paths.end())
+ return existing->first;
+ }
+ UnpackedRetryId id = base::GenerateGUID();
+ paths[id] = path;
+ return id;
+}
+
+base::FilePath DeveloperPrivateAPI::GetUnpackedPath(
+ content::WebContents* web_contents,
+ const UnpackedRetryId& id) const {
+ auto iter = allowed_unpacked_paths_.find(web_contents);
+ if (iter == allowed_unpacked_paths_.end())
+ return base::FilePath();
+ const IdToPathMap& paths = iter->second;
+ auto path_iter = paths.find(id);
+ if (path_iter == paths.end())
+ return base::FilePath();
+ return path_iter->second;
}
void DeveloperPrivateAPI::RegisterNotifications() {
@@ -469,6 +533,7 @@ ExtensionFunction::ResponseAction DeveloperPrivateAutoUpdateFunction::Run() {
ExtensionSystem::Get(browser_context())->extension_service()->updater();
if (updater) {
ExtensionUpdater::CheckParams params;
+ params.fetch_priority = ManifestFetchData::FetchPriority::FOREGROUND;
params.install_immediately = true;
updater->CheckNow(params);
}
@@ -723,27 +788,42 @@ void DeveloperPrivateShowPermissionsDialogFunction::Finish() {
Respond(NoArguments());
}
-DeveloperPrivateLoadUnpackedFunction::DeveloperPrivateLoadUnpackedFunction()
- : fail_quietly_(false) {
-}
+DeveloperPrivateLoadUnpackedFunction::DeveloperPrivateLoadUnpackedFunction() {}
ExtensionFunction::ResponseAction DeveloperPrivateLoadUnpackedFunction::Run() {
std::unique_ptr<developer::LoadUnpacked::Params> params(
developer::LoadUnpacked::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- if (!ShowPicker(
- ui::SelectFileDialog::SELECT_FOLDER,
- l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY),
- ui::SelectFileDialog::FileTypeInfo(),
- 0 /* file_type_index */)) {
- return RespondNow(Error(kCouldNotShowSelectFileDialogError));
- }
+ content::WebContents* web_contents = GetSenderWebContents();
+ if (!web_contents)
+ return RespondNow(Error(kCouldNotFindWebContentsError));
fail_quietly_ = params->options &&
params->options->fail_quietly &&
*params->options->fail_quietly;
+ populate_error_ = params->options && params->options->populate_error &&
+ *params->options->populate_error;
+
+ if (params->options && params->options->retry_guid) {
+ DeveloperPrivateAPI* api = DeveloperPrivateAPI::Get(browser_context());
+ base::FilePath path =
+ api->GetUnpackedPath(web_contents, *params->options->retry_guid);
+ if (path.empty())
+ return RespondNow(Error("Invalid retry id"));
+ AddRef(); // Balanced in FileSelected.
+ FileSelected(path);
+ return RespondLater();
+ }
+
+ if (!ShowPicker(ui::SelectFileDialog::SELECT_FOLDER,
+ l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY),
+ ui::SelectFileDialog::FileTypeInfo(),
+ 0 /* file_type_index */)) {
+ return RespondNow(Error(kCouldNotShowSelectFileDialogError));
+ }
+
AddRef(); // Balanced in FileSelected / FileSelectionCanceled.
return RespondLater();
}
@@ -757,7 +837,8 @@ void DeveloperPrivateLoadUnpackedFunction::FileSelected(
base::Bind(&DeveloperPrivateLoadUnpackedFunction::OnLoadComplete, this));
installer->Load(path);
- DeveloperPrivateAPI::Get(browser_context())->SetLastUnpackedDirectory(path);
+ retry_guid_ = DeveloperPrivateAPI::Get(browser_context())
+ ->AddUnpackedPath(GetSenderWebContents(), path);
Release(); // Balanced in Run().
}
@@ -773,7 +854,37 @@ void DeveloperPrivateLoadUnpackedFunction::OnLoadComplete(
const Extension* extension,
const base::FilePath& file_path,
const std::string& error) {
- Respond(extension ? NoArguments() : Error(error));
+ if (extension || !populate_error_) {
+ Respond(extension ? NoArguments() : Error(error));
+ return;
+ }
+
+ ExtensionLoaderHandler::GetManifestError(
+ error, file_path,
+ base::Bind(&DeveloperPrivateLoadUnpackedFunction::OnGotManifestError,
+ this));
+}
+
+void DeveloperPrivateLoadUnpackedFunction::OnGotManifestError(
+ const base::FilePath& file_path,
+ const std::string& error,
+ size_t line_number,
+ const std::string& manifest) {
+ DCHECK(!retry_guid_.empty());
+ base::FilePath prettified_path = path_util::PrettifyPath(file_path);
+
+ SourceHighlighter highlighter(manifest, line_number);
+ developer::LoadError response;
+ response.error = error;
+ response.path = base::UTF16ToUTF8(prettified_path.LossyDisplayName());
+ response.retry_guid = retry_guid_;
+
+ response.source = base::MakeUnique<developer::ErrorFileSource>();
+ response.source->before_highlight = highlighter.GetBeforeFeature();
+ response.source->highlight = highlighter.GetFeature();
+ response.source->after_highlight = highlighter.GetAfterFeature();
+
+ Respond(OneArgument(response.ToValue()));
}
bool DeveloperPrivateChooseEntryFunction::ShowPicker(
@@ -789,14 +900,10 @@ bool DeveloperPrivateChooseEntryFunction::ShowPicker(
// and subsequent sending of the function response) until the user has
// selected a file or cancelled the picker. At that point, the picker will
// delete itself.
- new EntryPicker(this,
- web_contents,
- picker_type,
- DeveloperPrivateAPI::Get(browser_context())->
- GetLastUnpackedDirectory(),
- select_title,
- info,
- file_type_index);
+ new EntryPicker(
+ this, web_contents, picker_type,
+ DeveloperPrivateAPI::Get(browser_context())->last_unpacked_directory(),
+ select_title, info, file_type_index);
return true;
}
@@ -979,7 +1086,7 @@ void DeveloperPrivateLoadDirectoryFunction::Load() {
// TODO(grv) : The unpacked installer should fire an event when complete
// and return the extension_id.
- SetResult(base::MakeUnique<base::StringValue>("-1"));
+ SetResult(base::MakeUnique<base::Value>("-1"));
SendResponse(true);
}
@@ -1153,8 +1260,7 @@ ExtensionFunction::ResponseAction DeveloperPrivateChoosePathFunction::Run() {
void DeveloperPrivateChoosePathFunction::FileSelected(
const base::FilePath& path) {
- Respond(OneArgument(
- base::MakeUnique<base::StringValue>(path.LossyDisplayName())));
+ Respond(OneArgument(base::MakeUnique<base::Value>(path.LossyDisplayName())));
Release();
}
@@ -1361,6 +1467,21 @@ DeveloperPrivateRepairExtensionFunction::Run() {
if (!extension)
return RespondNow(Error(kNoSuchExtensionError));
+ if (!ExtensionPrefs::Get(browser_context())
+ ->HasDisableReason(extension->id(), Extension::DISABLE_CORRUPTED)) {
+ return RespondNow(Error(kCannotRepairHealthyExtension));
+ }
+
+ ManagementPolicy* management_policy =
+ ExtensionSystem::Get(browser_context())->management_policy();
+ // If content verifier would repair this extension independently, then don't
+ // allow repair from here. This applies to policy extensions.
+ // Also note that if we let |reinstaller| continue with the repair, this would
+ // have uninstalled the extension but then we would have failed to reinstall
+ // it for policy check (see PolicyCheck::Start()).
+ if (ContentVerifier::ShouldRepairIfCorrupted(management_policy, extension))
+ return RespondNow(Error(kCannotRepairPolicyExtension));
+
content::WebContents* web_contents = GetSenderWebContents();
if (!web_contents)
return RespondNow(Error(kCouldNotFindWebContentsError));
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 607e3029d07..c284ad5d1b4 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -171,6 +171,8 @@ class DeveloperPrivateEventRouter : public ExtensionRegistryObserver,
class DeveloperPrivateAPI : public BrowserContextKeyedAPI,
public EventRouter::Observer {
public:
+ using UnpackedRetryId = std::string;
+
static BrowserContextKeyedAPIFactory<DeveloperPrivateAPI>*
GetFactoryInstance();
@@ -180,11 +182,17 @@ class DeveloperPrivateAPI : public BrowserContextKeyedAPI,
explicit DeveloperPrivateAPI(content::BrowserContext* context);
~DeveloperPrivateAPI() override;
- void SetLastUnpackedDirectory(const base::FilePath& path);
+ // Adds a path to the list of allowed unpacked paths for the given
+ // |web_contents|. Returns a unique identifier to retry that path. Safe to
+ // call multiple times for the same <web_contents, path> pair; each call will
+ // return the same identifier.
+ UnpackedRetryId AddUnpackedPath(content::WebContents* web_contents,
+ const base::FilePath& path);
- base::FilePath& GetLastUnpackedDirectory() {
- return last_unpacked_directory_;
- }
+ // Returns the FilePath associated with the given |id| and |web_contents|, if
+ // one exists.
+ base::FilePath GetUnpackedPath(content::WebContents* web_contents,
+ const UnpackedRetryId& id) const;
// KeyedService implementation
void Shutdown() override;
@@ -196,8 +204,13 @@ class DeveloperPrivateAPI : public BrowserContextKeyedAPI,
DeveloperPrivateEventRouter* developer_private_event_router() {
return developer_private_event_router_.get();
}
+ const base::FilePath& last_unpacked_directory() const {
+ return last_unpacked_directory_;
+ }
private:
+ class WebContentsTracker;
+
friend class BrowserContextKeyedAPIFactory<DeveloperPrivateAPI>;
// BrowserContextKeyedAPI implementation.
@@ -213,9 +226,23 @@ class DeveloperPrivateAPI : public BrowserContextKeyedAPI,
// was loaded.
base::FilePath last_unpacked_directory_;
+ // A set of unpacked paths that we are allowed to load for different
+ // WebContents. For security reasons, we don't let JavaScript arbitrarily
+ // pass us a path and load the extension at that location; instead, the user
+ // has to explicitly select the path through a native dialog first, and then
+ // we will allow JavaScript to request we reload that same selected path.
+ // Additionally, these are segmented by WebContents; this is primarily to
+ // allow collection (removing old paths when the WebContents closes) but has
+ // the effect that WebContents A cannot retry a path selected in
+ // WebContents B.
+ using IdToPathMap = std::map<UnpackedRetryId, base::FilePath>;
+ std::map<content::WebContents*, IdToPathMap> allowed_unpacked_paths_;
+
// Created lazily upon OnListenerAdded.
std::unique_ptr<DeveloperPrivateEventRouter> developer_private_event_router_;
+ base::WeakPtrFactory<DeveloperPrivateAPI> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateAPI);
};
@@ -395,8 +422,20 @@ class DeveloperPrivateLoadUnpackedFunction
const std::string& error);
private:
+ void OnGotManifestError(const base::FilePath& file_path,
+ const std::string& error,
+ size_t line_number,
+ const std::string& manifest);
+
// Whether or not we should fail quietly in the event of a load error.
- bool fail_quietly_;
+ bool fail_quietly_ = false;
+
+ // Whether we populate a developer_private::LoadError on load failure, as
+ // opposed to simply passing the message in lastError.
+ bool populate_error_ = false;
+
+ // The identifier for the selected path when retrying an unpacked load.
+ DeveloperPrivateAPI::UnpackedRetryId retry_guid_;
};
class DeveloperPrivateChoosePathFunction
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 580034ae9a1..416355aa9c9 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
@@ -11,10 +11,11 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/error_console/error_console.h"
#include "chrome/browser/extensions/extension_function_test_utils.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/scripting_permissions_modifier.h"
#include "chrome/browser/extensions/test_extension_dir.h"
@@ -32,12 +33,16 @@
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/browser/notification_service.h"
#include "content/public/test/web_contents_tester.h"
+#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/event_router_factory.h"
#include "extensions/browser/extension_error_test_util.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/browser/extension_util.h"
+#include "extensions/browser/mock_external_provider.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
@@ -54,6 +59,8 @@ namespace extensions {
namespace {
+const char kGoodCrx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
+
std::unique_ptr<KeyedService> BuildAPI(content::BrowserContext* context) {
return base::MakeUnique<DeveloperPrivateAPI>(context);
}
@@ -77,11 +84,16 @@ bool HasPrefsPermission(bool (*has_pref)(const std::string&,
} // namespace
-class DeveloperPrivateApiUnitTest : public ExtensionServiceTestBase {
+class DeveloperPrivateApiUnitTest : public ExtensionServiceTestWithInstall {
protected:
DeveloperPrivateApiUnitTest() {}
~DeveloperPrivateApiUnitTest() override {}
+ void AddMockExternalProvider(
+ std::unique_ptr<ExternalProviderInterface> provider) {
+ service()->AddProviderForTesting(std::move(provider));
+ }
+
// A wrapper around extension_function_test_utils::RunFunction that runs with
// the associated browser, no flags, and can take stack-allocated arguments.
bool RunFunction(const scoped_refptr<UIThreadExtensionFunction>& function,
@@ -501,6 +513,225 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateLoadUnpacked) {
current_ids).size());
}
+TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateLoadUnpackedLoadError) {
+ std::unique_ptr<content::WebContents> web_contents(
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
+
+ {
+ // Load an extension with a clear manifest error ('version' is invalid).
+ TestExtensionDir dir;
+ dir.WriteManifest(
+ R"({
+ "name": "foo",
+ "description": "bar",
+ "version": 1,
+ "manifest_version": 2
+ })");
+ base::FilePath path = dir.UnpackedPath();
+ api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path);
+
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ std::unique_ptr<base::Value> result =
+ api_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(),
+ "[{\"failQuietly\": true, \"populateError\": true}]", profile());
+ // The loadError result should be populated.
+ ASSERT_TRUE(result);
+ std::unique_ptr<api::developer_private::LoadError> error =
+ api::developer_private::LoadError::FromValue(*result);
+ ASSERT_TRUE(error);
+ ASSERT_TRUE(error->source);
+ // The source should have *something* (rely on file highlighter tests for
+ // the correct population).
+ EXPECT_FALSE(error->source->before_highlight.empty());
+ // The error should be appropriate (mentioning that version was invalid).
+ EXPECT_TRUE(error->error.find("version") != std::string::npos)
+ << error->error;
+ }
+
+ {
+ // Load an extension with no manifest.
+ TestExtensionDir dir;
+ base::FilePath path = dir.UnpackedPath();
+ api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path);
+
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ std::unique_ptr<base::Value> result =
+ api_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(),
+ "[{\"failQuietly\": true, \"populateError\": true}]", profile());
+ // The load error should be populated.
+ ASSERT_TRUE(result);
+ std::unique_ptr<api::developer_private::LoadError> error =
+ api::developer_private::LoadError::FromValue(*result);
+ ASSERT_TRUE(error);
+ // The file source should be empty.
+ ASSERT_TRUE(error->source);
+ EXPECT_TRUE(error->source->before_highlight.empty());
+ EXPECT_TRUE(error->source->highlight.empty());
+ EXPECT_TRUE(error->source->after_highlight.empty());
+ }
+
+ {
+ // Load a valid extension.
+ TestExtensionDir dir;
+ dir.WriteManifest(
+ R"({
+ "name": "foo",
+ "description": "bar",
+ "version": "1.0",
+ "manifest_version": 2
+ })");
+ base::FilePath path = dir.UnpackedPath();
+ api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path);
+
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ std::unique_ptr<base::Value> result =
+ api_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(),
+ "[{\"failQuietly\": true, \"populateError\": true}]", profile());
+ // There should be no load error.
+ ASSERT_FALSE(result);
+ }
+}
+
+// Test that the retryGuid supplied by loadUnpacked works correctly.
+TEST_F(DeveloperPrivateApiUnitTest, LoadUnpackedRetryId) {
+ std::unique_ptr<content::WebContents> web_contents(
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
+
+ // Load an extension with a clear manifest error ('version' is invalid).
+ TestExtensionDir dir;
+ dir.WriteManifest(
+ R"({
+ "name": "foo",
+ "description": "bar",
+ "version": 1,
+ "manifest_version": 2
+ })");
+ base::FilePath path = dir.UnpackedPath();
+ api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path);
+
+ DeveloperPrivateAPI::UnpackedRetryId retry_guid;
+ {
+ // Trying to load the extension should result in a load error with the
+ // retry id populated.
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ std::unique_ptr<base::Value> result =
+ api_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(),
+ "[{\"failQuietly\": true, \"populateError\": true}]", profile());
+ ASSERT_TRUE(result);
+ std::unique_ptr<api::developer_private::LoadError> error =
+ api::developer_private::LoadError::FromValue(*result);
+ ASSERT_TRUE(error);
+ EXPECT_FALSE(error->retry_guid.empty());
+ retry_guid = error->retry_guid;
+ }
+
+ {
+ // Trying to reload the same extension, again to fail, should result in the
+ // same retry id. This is somewhat an implementation detail, but is
+ // important to ensure we don't allocate crazy numbers of ids if the user
+ // just retries continously.
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ std::unique_ptr<base::Value> result =
+ api_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(),
+ "[{\"failQuietly\": true, \"populateError\": true}]", profile());
+ ASSERT_TRUE(result);
+ std::unique_ptr<api::developer_private::LoadError> error =
+ api::developer_private::LoadError::FromValue(*result);
+ ASSERT_TRUE(error);
+ EXPECT_EQ(retry_guid, error->retry_guid);
+ }
+
+ {
+ // Try loading a different directory. The retry id should be different; this
+ // also tests loading a second extension with one retry currently
+ // "in-flight" (i.e., unresolved).
+ TestExtensionDir second_dir;
+ second_dir.WriteManifest(
+ R"({
+ "name": "foo",
+ "description": "bar",
+ "version": 1,
+ "manifest_version": 2
+ })");
+ base::FilePath second_path = second_dir.UnpackedPath();
+ api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&second_path);
+
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ std::unique_ptr<base::Value> result =
+ api_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(),
+ "[{\"failQuietly\": true, \"populateError\": true}]", profile());
+ // The loadError result should be populated.
+ ASSERT_TRUE(result);
+ std::unique_ptr<api::developer_private::LoadError> error =
+ api::developer_private::LoadError::FromValue(*result);
+ ASSERT_TRUE(error);
+ EXPECT_NE(retry_guid, error->retry_guid);
+ }
+
+ // Correct the manifest to make the extension valid.
+ dir.WriteManifest(
+ R"({
+ "name": "foo",
+ "description": "bar",
+ "version": "1.0",
+ "manifest_version": 2
+ })");
+
+ // Set the picker to choose an invalid path (the picker should be skipped if
+ // we supply a retry id).
+ base::FilePath empty_path;
+ api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&empty_path);
+
+ {
+ // Try reloading the extension by supplying the retry id. It should succeed.
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ TestExtensionRegistryObserver observer(registry());
+ api_test_utils::RunFunction(function.get(),
+ base::StringPrintf("[{\"failQuietly\": true,"
+ "\"populateError\": true,"
+ "\"retryGuid\": \"%s\"}]",
+ retry_guid.c_str()),
+ profile());
+ const Extension* extension = observer.WaitForExtensionLoaded();
+ ASSERT_TRUE(extension);
+ EXPECT_EQ(extension->path(), path);
+ }
+
+ {
+ // Try supplying an invalid retry id. It should fail with an error.
+ scoped_refptr<UIThreadExtensionFunction> function(
+ new api::DeveloperPrivateLoadUnpackedFunction());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ std::string error = api_test_utils::RunFunctionAndReturnError(
+ function.get(),
+ "[{\"failQuietly\": true,"
+ "\"populateError\": true,"
+ "\"retryGuid\": \"invalid id\"}]",
+ profile());
+ EXPECT_EQ("Invalid retry id", error);
+ }
+}
+
// Test developerPrivate.requestFileSource.
TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateRequestFileSource) {
// Testing of this function seems light, but that's because it basically just
@@ -633,11 +864,66 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDeleteExtensionErrors) {
EXPECT_TRUE(error_console->GetErrorsForExtension(extension->id()).empty());
}
+// Tests that developerPrivate.repair does not succeed for a non-corrupted
+// extension.
+TEST_F(DeveloperPrivateApiUnitTest, RepairNotBrokenExtension) {
+ base::FilePath extension_path = data_dir().AppendASCII("good.crx");
+ const Extension* extension = InstallCRX(extension_path, INSTALL_NEW);
+
+ // Attempt to repair the good extension, expect failure.
+ std::unique_ptr<base::ListValue> args =
+ ListBuilder().Append(extension->id()).Build();
+ scoped_refptr<UIThreadExtensionFunction> function =
+ new api::DeveloperPrivateRepairExtensionFunction();
+ EXPECT_FALSE(RunFunction(function, *args));
+ EXPECT_EQ("Cannot repair a healthy extension.", function->GetError());
+}
+
+// Tests that developerPrivate.private cannot repair a policy-installed
+// extension.
+// Regression test for https://crbug.com/577959.
+TEST_F(DeveloperPrivateApiUnitTest, RepairPolicyExtension) {
+ std::string extension_id(kGoodCrx);
+
+ // Set up a mock provider with a policy extension.
+ std::unique_ptr<MockExternalProvider> mock_provider =
+ base::MakeUnique<MockExternalProvider>(
+ service(), Manifest::EXTERNAL_POLICY_DOWNLOAD);
+ MockExternalProvider* mock_provider_ptr = mock_provider.get();
+ AddMockExternalProvider(std::move(mock_provider));
+ mock_provider_ptr->UpdateOrAddExtension(extension_id, "1.0.0.0",
+ data_dir().AppendASCII("good.crx"));
+ // Reloading extensions should find our externally registered extension
+ // and install it.
+ content::WindowedNotificationObserver observer(
+ extensions::NOTIFICATION_CRX_INSTALLER_DONE,
+ content::NotificationService::AllSources());
+ service()->CheckForExternalUpdates();
+ observer.Wait();
+
+ // Attempt to repair the good extension, expect failure.
+ std::unique_ptr<base::ListValue> args =
+ ListBuilder().Append(extension_id).Build();
+ scoped_refptr<UIThreadExtensionFunction> function =
+ new api::DeveloperPrivateRepairExtensionFunction();
+ EXPECT_FALSE(RunFunction(function, *args));
+ EXPECT_EQ("Cannot repair a healthy extension.", function->GetError());
+
+ // Corrupt the extension , still expect repair failure because this is a
+ // policy extension.
+ service()->DisableExtension(extension_id, Extension::DISABLE_CORRUPTED);
+ args = ListBuilder().Append(extension_id).Build();
+ function = new api::DeveloperPrivateRepairExtensionFunction();
+ EXPECT_FALSE(RunFunction(function, *args));
+ EXPECT_EQ("Cannot repair a policy-installed extension.",
+ function->GetError());
+}
+
// Test developerPrivate.updateProfileConfiguration: Try to turn on devMode
// when DeveloperToolsDisabled policy is active.
TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDevModeDisabledPolicy) {
testing_pref_service()->SetManagedPref(prefs::kExtensionsUIDeveloperMode,
- new base::Value(false));
+ base::MakeUnique<base::Value>(false));
UpdateProfileConfigurationDevMode(true);
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 30d379c8708..d1d54f7dad3 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
@@ -172,7 +172,7 @@ class ExtensionInfoGeneratorUnitTest : public ExtensionServiceTestBase {
// Produce test output.
std::unique_ptr<developer::ExtensionInfo> info =
- CreateExtensionInfoFromPath(extension_path, Manifest::INVALID_LOCATION);
+ CreateExtensionInfoFromPath(extension_path, Manifest::UNPACKED);
info->views = std::move(views);
std::unique_ptr<base::DictionaryValue> actual_output_data = info->ToValue();
ASSERT_TRUE(actual_output_data);
diff --git a/chromium/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc b/chromium/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
index e5051949ed1..d0b197c6bcc 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/extensions/api/developer_private/inspectable_views_finder.h"
-#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/developer_private.h"
#include "content/public/browser/render_frame_host.h"
@@ -13,6 +12,7 @@
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_util.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/constants.h"
diff --git a/chromium/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc b/chromium/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc
index fe8425b2681..620e32c45d5 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/show_permissions_dialog_helper.cc
@@ -6,9 +6,9 @@
#include <utility>
-#include "apps/app_load_service.h"
#include "apps/saved_files_service.h"
#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/apps/app_load_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/apps/app_info_dialog.h"
#include "content/public/browser/web_contents.h"
diff --git a/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc b/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
index 6ff4e53cc25..4ee780d7326 100644
--- a/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
@@ -301,7 +301,7 @@ TEST_F(DevicePermissionsManagerTest, LoadPrefs) {
" }"
"]");
env_->GetExtensionPrefs()->UpdateExtensionPref(extension_->id(), "devices",
- prefs_value.release());
+ std::move(prefs_value));
DevicePermissionsManager* manager =
DevicePermissionsManager::Get(env_->profile());
diff --git a/chromium/chrome/browser/extensions/api/dial/device_description_fetcher.cc b/chromium/chrome/browser/extensions/api/dial/device_description_fetcher.cc
deleted file mode 100644
index 654fc3355c7..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/device_description_fetcher.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "chrome/browser/extensions/api/dial/device_description_fetcher.h"
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "chrome/browser/profiles/profile.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_status_code.h"
-#include "net/http/http_util.h"
-#include "net/url_request/url_fetcher.h"
-
-using content::BrowserThread;
-
-constexpr char kApplicationUrlHeaderName[] = "Application-URL";
-constexpr int kMaxRetries = 3;
-// DIAL devices are unlikely to expose uPnP functions other than DIAL, so 256kb
-// should be more than sufficient.
-constexpr int kMaxDescriptionSizeBytes = 262144;
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-DeviceDescriptionFetcher::DeviceDescriptionFetcher(
- const GURL& device_description_url,
- Profile* profile,
- base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb,
- base::OnceCallback<void(const std::string&)> error_cb)
- : device_description_url_(device_description_url),
- profile_(profile),
- success_cb_(std::move(success_cb)),
- error_cb_(std::move(error_cb)) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(profile_);
- DCHECK(device_description_url_.is_valid());
-}
-
-DeviceDescriptionFetcher::~DeviceDescriptionFetcher() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-void DeviceDescriptionFetcher::Start() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!fetcher_);
-
- // DIAL returns device descriptions via GET request.
- fetcher_ =
- net::URLFetcher::Create(kURLFetcherIDForTest, device_description_url_,
- net::URLFetcher::GET, this);
-
- // net::LOAD_BYPASS_PROXY: Proxies almost certainly hurt more cases than they
- // help.
- // net::LOAD_DISABLE_CACHE: The request should not touch the cache.
- // net::LOAD_DO_NOT_{SAVE,SEND}_COOKIES: The request should not touch cookies.
- // net::LOAD_DO_NOT_SEND_AUTH_DATA: The request should not send auth data.
- fetcher_->SetLoadFlags(net::LOAD_BYPASS_PROXY | net::LOAD_DISABLE_CACHE |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SEND_AUTH_DATA);
-
- // Section 5.4 of the DIAL spec prohibits redirects.
- fetcher_->SetStopOnRedirect(true);
-
- // Allow the fetcher to retry on 5XX responses and ERR_NETWORK_CHANGED.
- fetcher_->SetMaxRetriesOn5xx(kMaxRetries);
- fetcher_->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
-
- fetcher_->SetRequestContext(profile_->GetRequestContext());
- fetcher_->Start();
-}
-
-void DeviceDescriptionFetcher::OnURLFetchComplete(
- const net::URLFetcher* source) {
- DCHECK_EQ(fetcher_.get(), source);
-
- if (source->GetResponseCode() != net::HTTP_OK) {
- ReportError(
- base::StringPrintf("HTTP %d: Unable to fetch device description",
- source->GetResponseCode()));
- return;
- }
-
- const net::HttpResponseHeaders* headers = source->GetResponseHeaders();
-
- // NOTE: The uPnP spec requires devices to set a Content-Type: header of
- // text/xml; charset="utf-8" (sec 2.11). However Chromecast (and possibly
- // other devices) do not comply, so specifically not checking this header.
- std::string app_url_header;
- if (!headers->GetNormalizedHeader(kApplicationUrlHeaderName,
- &app_url_header) ||
- app_url_header.empty()) {
- ReportError("Missing or empty Application-URL:");
- return;
- }
-
- // Section 5.4 of the DIAL spec implies that the Application URL should not
- // have path, query or fragment...unsure if that can be enforced.
- GURL app_url(app_url_header);
- if (!app_url.is_valid() || !app_url.SchemeIs("http") ||
- !app_url.HostIsIPAddress() ||
- app_url.host() != device_description_url_.host()) {
- ReportError(base::StringPrintf("Invalid Application-URL: %s",
- app_url_header.c_str()));
- return;
- }
-
- if (source->GetReceivedResponseContentLength() > kMaxDescriptionSizeBytes) {
- ReportError("Response too large");
- return;
- }
-
- std::string device_description;
- if (!source->GetResponseAsString(&device_description) ||
- device_description.empty()) {
- ReportError("Missing or empty response");
- return;
- }
-
- if (!base::IsStringUTF8(device_description)) {
- ReportError("Invalid response encoding");
- return;
- }
-
- std::move(success_cb_)
- .Run(DialDeviceDescriptionData(std::move(device_description), app_url));
-}
-
-void DeviceDescriptionFetcher::OnURLFetchDownloadProgress(
- const net::URLFetcher* source,
- int64_t current,
- int64_t total,
- int64_t current_network_bytes) {}
-
-void DeviceDescriptionFetcher::OnURLFetchUploadProgress(
- const net::URLFetcher* source,
- int64_t current,
- int64_t total) {}
-
-void DeviceDescriptionFetcher::ReportError(const std::string& message) {
- std::move(error_cb_).Run(message);
-}
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/dial/device_description_fetcher.h b/chromium/chrome/browser/extensions/api/dial/device_description_fetcher.h
deleted file mode 100644
index 309dc88a600..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/device_description_fetcher.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_DIAL_DEVICE_DESCRIPTION_FETCHER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_DIAL_DEVICE_DESCRIPTION_FETCHER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "url/gurl.h"
-
-class Profile;
-
-namespace net {
-class URLFetcher;
-}
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-struct DialDeviceDescriptionData;
-
-// Used to make a single HTTP GET request with |device_description_url| to fetch
-// a uPnP device description from a DIAL device. If successful, |success_cb| is
-// invoked with the result; otherwise, |error_cb| is invoked with an error
-// reason. This class is not thread safe and must be used on the UI thread.
-class DeviceDescriptionFetcher : public net::URLFetcherDelegate {
- public:
- // Used to identify the net::URLFetcher instance for tests.
- static constexpr int kURLFetcherIDForTest = 1;
-
- // |profile| is unowned; the caller must ensure that this object does not
- // outlive it.
- DeviceDescriptionFetcher(
- const GURL& device_description_url,
- Profile* profile,
- base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb,
- base::OnceCallback<void(const std::string&)> error_cb);
-
- ~DeviceDescriptionFetcher() override;
-
- void Start();
-
- private:
- // net::URLFetcherDelegate implementation.
- void OnURLFetchComplete(const net::URLFetcher* source) override;
- void OnURLFetchDownloadProgress(const net::URLFetcher* source,
- int64_t current,
- int64_t total,
- int64_t current_network_bytes) override;
- void OnURLFetchUploadProgress(const net::URLFetcher* source,
- int64_t current,
- int64_t total) override;
-
- // Runs |error_cb_| with |message| and clears it.
- void ReportError(const std::string& message);
-
- const GURL device_description_url_;
- Profile* const profile_;
- base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb_;
- base::OnceCallback<void(const std::string&)> error_cb_;
- std::unique_ptr<net::URLFetcher> fetcher_;
-};
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_DIAL_DEVICE_DESCRIPTION_FETCHER_H_
diff --git a/chromium/chrome/browser/extensions/api/dial/device_description_fetcher_unittest.cc b/chromium/chrome/browser/extensions/api/dial/device_description_fetcher_unittest.cc
deleted file mode 100644
index 92b72c73a51..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/device_description_fetcher_unittest.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "chrome/browser/extensions/api/dial/device_description_fetcher.h"
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_fetcher.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-class DeviceDescriptionFetcherTest : public testing::Test {
- public:
- DeviceDescriptionFetcherTest() : url_("http://127.0.0.1/description.xml") {}
-
- void TearDown() override {
- EXPECT_FALSE(error_cb_);
- EXPECT_FALSE(success_cb_);
- }
-
- void ExpectSuccess(const GURL& expected_app_url,
- const std::string& expected_description) {
- success_cb_ = base::BindOnce(&DeviceDescriptionFetcherTest::OnSuccess,
- base::Unretained(this), expected_app_url,
- expected_description);
- }
-
- void ExpectError(const std::string& expected_message) {
- error_cb_ = base::BindOnce(&DeviceDescriptionFetcherTest::OnError,
- base::Unretained(this), expected_message);
- }
-
- net::TestURLFetcher* StartRequest() {
- fetcher_ = base::MakeUnique<DeviceDescriptionFetcher>(
- url_, &profile_, std::move(success_cb_), std::move(error_cb_));
- fetcher_->Start();
- return factory_.GetFetcherByID(
- DeviceDescriptionFetcher::kURLFetcherIDForTest);
- }
-
- protected:
- const content::TestBrowserThreadBundle thread_bundle_;
- TestingProfile profile_;
- const net::TestURLFetcherFactory factory_;
- const GURL url_;
- base::OnceCallback<void(const DialDeviceDescriptionData&)> success_cb_;
- base::OnceCallback<void(const std::string&)> error_cb_;
- std::unique_ptr<DeviceDescriptionFetcher> fetcher_;
-
- private:
- void OnSuccess(const GURL& expected_app_url,
- const std::string& expected_description,
- const DialDeviceDescriptionData& description) {
- EXPECT_EQ(expected_app_url, description.app_url);
- EXPECT_EQ(expected_description, description.device_description);
- }
-
- void OnError(const std::string& expected_message,
- const std::string& message) {
- EXPECT_TRUE(message.find(expected_message) == 0);
- }
-
- DISALLOW_COPY_AND_ASSIGN(DeviceDescriptionFetcherTest);
-};
-
-TEST_F(DeviceDescriptionFetcherTest, FetchSuccessful) {
- ExpectSuccess(GURL("http://127.0.0.1/apps"), "<xml>description</xml>");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_OK);
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders("");
- headers->AddHeader("Application-URL: http://127.0.0.1/apps");
- test_fetcher->set_response_headers(headers);
- test_fetcher->SetResponseString("<xml>description</xml>");
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-TEST_F(DeviceDescriptionFetcherTest, FetchFailsOnMissingDescription) {
- ExpectError("HTTP 404:");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_NOT_FOUND);
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-TEST_F(DeviceDescriptionFetcherTest, FetchFailsOnMissingAppUrl) {
- ExpectError("Missing or empty Application-URL:");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_OK);
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders("");
- test_fetcher->set_response_headers(headers);
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-TEST_F(DeviceDescriptionFetcherTest, FetchFailsOnEmptyAppUrl) {
- ExpectError("Missing or empty Application-URL:");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_OK);
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders("");
- headers->AddHeader("Application-URL:");
- test_fetcher->set_response_headers(headers);
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-TEST_F(DeviceDescriptionFetcherTest, FetchFailsOnInvalidAppUrl) {
- ExpectError("Invalid Application-URL:");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_OK);
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders("");
- headers->AddHeader("Application-URL: http://www.example.com");
- test_fetcher->set_response_headers(headers);
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-TEST_F(DeviceDescriptionFetcherTest, FetchFailsOnEmptyDescription) {
- ExpectError("Missing or empty response");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_OK);
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders("");
- headers->AddHeader("Application-URL: http://127.0.0.1/apps");
- test_fetcher->set_response_headers(headers);
- test_fetcher->SetResponseString("");
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-TEST_F(DeviceDescriptionFetcherTest, FetchFailsOnBadDescription) {
- ExpectError("Invalid response encoding");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_OK);
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders("");
- headers->AddHeader("Application-URL: http://127.0.0.1/apps");
- test_fetcher->set_response_headers(headers);
- test_fetcher->SetResponseString("\xfc\x9c\xbf\x80\xbf\x80");
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-TEST_F(DeviceDescriptionFetcherTest, FetchFailsOnResponseTooLarge) {
- ExpectError("Response too large");
- net::TestURLFetcher* test_fetcher = StartRequest();
-
- test_fetcher->set_response_code(net::HTTP_OK);
- scoped_refptr<net::HttpResponseHeaders> headers =
- new net::HttpResponseHeaders("");
- headers->AddHeader("Application-URL: http://127.0.0.1/apps");
- test_fetcher->set_response_headers(headers);
- test_fetcher->SetResponseString(std::string(262145, 'd'));
- test_fetcher->delegate()->OnURLFetchComplete(test_fetcher);
-}
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_api.cc b/chromium/chrome/browser/extensions/api/dial/dial_api.cc
index 0fd0b9c5400..dd07c40724f 100644
--- a/chromium/chrome/browser/extensions/api/dial/dial_api.cc
+++ b/chromium/chrome/browser/extensions/api/dial/dial_api.cc
@@ -11,8 +11,9 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
-#include "chrome/browser/extensions/api/dial/device_description_fetcher.h"
#include "chrome/browser/extensions/api/dial/dial_api_factory.h"
+#include "chrome/browser/media/router/discovery/dial/device_description_fetcher.h"
+#include "chrome/browser/media/router/discovery/dial/dial_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/dial.h"
#include "content/public/browser/browser_thread.h"
@@ -22,47 +23,41 @@
using base::TimeDelta;
using content::BrowserThread;
-using extensions::api::dial::DeviceDescriptionFetcher;
-using extensions::api::dial::DialDeviceData;
-using extensions::api::dial::DialDeviceDescriptionData;
-using extensions::api::dial::DialRegistry;
+using media_router::DeviceDescriptionFetcher;
+using media_router::DialDeviceData;
+using media_router::DialDeviceDescriptionData;
+using media_router::DialRegistry;
namespace extensions {
-namespace {
-
-// How often to poll for devices.
-const int kDialRefreshIntervalSecs = 120;
-
-// We prune a device if it does not respond after this time.
-const int kDialExpirationSecs = 240;
-
-// The maximum number of devices retained at once in the registry.
-const size_t kDialMaxDevices = 256;
-
-} // namespace
-
DialAPI::DialAPI(Profile* profile)
: RefcountedKeyedService(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
- profile_(profile) {
+ profile_(profile),
+ dial_registry_(nullptr) {
EventRouter::Get(profile)->RegisterObserver(
this, api::dial::OnDeviceList::kEventName);
}
-DialAPI::~DialAPI() {}
+DialAPI::~DialAPI() {
+ // TODO(zhaobin): Call dial_registry_->UnregisterObserver() instead. In
+ // current implementation, UnregistryObserver() does not StopDiscovery() and
+ // causes crash in ~DialRegistry(). May keep a listener count and
+ // Register/UnregisterObserver as needed.
+ if (dial_registry_)
+ dial_registry_->StopPeriodicDiscovery();
+}
DialRegistry* DialAPI::dial_registry() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!dial_registry_.get()) {
- dial_registry_.reset(new DialRegistry(
- this, TimeDelta::FromSeconds(kDialRefreshIntervalSecs),
- TimeDelta::FromSeconds(kDialExpirationSecs), kDialMaxDevices));
+ if (!dial_registry_) {
+ dial_registry_ = media_router::DialRegistry::GetInstance();
+ dial_registry_->RegisterObserver(this);
if (test_device_data_) {
dial_registry_->AddDeviceForTest(*test_device_data_);
}
}
- return dial_registry_.get();
+ return dial_registry_;
}
void DialAPI::OnListenerAdded(const EventListenerInfo& details) {
@@ -91,6 +86,17 @@ void DialAPI::NotifyListenerRemovedOnIOThread() {
dial_registry()->OnListenerRemoved();
}
+void DialAPI::FillDialDevice(const media_router::DialDeviceData& device_data,
+ api::dial::DialDevice* device) const {
+ DCHECK(!device_data.device_id().empty());
+ DCHECK(media_router::DialDeviceData::IsDeviceDescriptionUrl(
+ device_data.device_description_url()));
+ device->device_label = device_data.label();
+ device->device_description_url = device_data.device_description_url().spec();
+ if (device_data.has_config_id())
+ device->config_id.reset(new int(device_data.config_id()));
+}
+
void DialAPI::OnDialDeviceEvent(const DialRegistry::DeviceList& devices) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
@@ -109,7 +115,7 @@ void DialAPI::SendEventOnUIThread(const DialRegistry::DeviceList& devices) {
std::vector<api::dial::DialDevice> args;
for (const DialDeviceData& device : devices) {
api::dial::DialDevice api_device;
- device.FillDialDevice(&api_device);
+ FillDialDevice(device, &api_device);
args.push_back(std::move(api_device));
}
std::unique_ptr<base::ListValue> results =
@@ -156,8 +162,8 @@ void DialAPI::SendErrorOnUIThread(const DialRegistry::DialErrorCode code) {
void DialAPI::ShutdownOnUIThread() {}
void DialAPI::SetDeviceForTest(
- const api::dial::DialDeviceData& device_data,
- const api::dial::DialDeviceDescriptionData& device_description) {
+ const media_router::DialDeviceData& device_data,
+ const media_router::DialDeviceDescriptionData& device_description) {
test_device_data_ = base::MakeUnique<DialDeviceData>(device_data);
test_device_description_ =
base::MakeUnique<DialDeviceDescriptionData>(device_description);
@@ -230,7 +236,7 @@ void DialFetchDeviceDescriptionFunction::MaybeStartFetch(const GURL& url) {
}
device_description_fetcher_ = base::MakeUnique<DeviceDescriptionFetcher>(
- url, Profile::FromBrowserContext(browser_context()),
+ url, Profile::FromBrowserContext(browser_context())->GetRequestContext(),
base::BindOnce(&DialFetchDeviceDescriptionFunction::OnFetchComplete,
this),
base::BindOnce(&DialFetchDeviceDescriptionFunction::OnFetchError, this));
@@ -239,7 +245,7 @@ void DialFetchDeviceDescriptionFunction::MaybeStartFetch(const GURL& url) {
}
void DialFetchDeviceDescriptionFunction::OnFetchComplete(
- const api::dial::DialDeviceDescriptionData& result) {
+ const media_router::DialDeviceDescriptionData& result) {
// Destroy the DeviceDescriptionFetcher since it still contains a reference
// to |this| in its un-invoked callback.
device_description_fetcher_.reset();
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_api.h b/chromium/chrome/browser/extensions/api/dial/dial_api.h
index 1aba1c75a70..e9fb6ccd1a0 100644
--- a/chromium/chrome/browser/extensions/api/dial/dial_api.h
+++ b/chromium/chrome/browser/extensions/api/dial/dial_api.h
@@ -8,20 +8,18 @@
#include <memory>
#include "base/macros.h"
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "chrome/browser/extensions/api/dial/dial_registry.h"
+#include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
+#include "chrome/browser/media/router/discovery/dial/dial_registry.h"
#include "chrome/common/extensions/api/dial.h"
#include "components/keyed_service/core/refcounted_keyed_service.h"
#include "extensions/browser/api/async_api_function.h"
#include "extensions/browser/event_router.h"
-namespace extensions {
-
-namespace api {
-namespace dial {
+namespace media_router {
class DeviceDescriptionFetcher;
-} // namespace dial
-} // namespace api
+} // namespace media_router
+
+namespace extensions {
class DialFetchDeviceDescriptionFunction;
@@ -46,23 +44,25 @@ class DialFetchDeviceDescriptionFunction;
// real DialRegsitry.
class DialAPI : public RefcountedKeyedService,
public EventRouter::Observer,
- public api::dial::DialRegistry::Observer {
+ public media_router::DialRegistry::Observer {
public:
explicit DialAPI(Profile* profile);
// The DialRegistry for the API. This must always be used only from the IO
// thread.
- api::dial::DialRegistry* dial_registry();
+ media_router::DialRegistry* dial_registry();
// Called by the DialRegistry on the IO thread so that the DialAPI dispatches
// the event to listeners on the UI thread.
- void SendEventOnUIThread(const api::dial::DialRegistry::DeviceList& devices);
- void SendErrorOnUIThread(const api::dial::DialRegistry::DialErrorCode type);
+ void SendEventOnUIThread(
+ const media_router::DialRegistry::DeviceList& devices);
+ void SendErrorOnUIThread(
+ const media_router::DialRegistry::DialErrorCode type);
// Sets test device data.
void SetDeviceForTest(
- const api::dial::DialDeviceData& device_data,
- const api::dial::DialDeviceDescriptionData& device_description);
+ const media_router::DialDeviceData& device_data,
+ const media_router::DialDeviceDescriptionData& device_description);
private:
~DialAPI() override;
@@ -78,22 +78,27 @@ class DialAPI : public RefcountedKeyedService,
// DialRegistry::Observer:
void OnDialDeviceEvent(
- const api::dial::DialRegistry::DeviceList& devices) override;
- void OnDialError(api::dial::DialRegistry::DialErrorCode type) override;
+ const media_router::DialRegistry::DeviceList& devices) override;
+ void OnDialError(media_router::DialRegistry::DialErrorCode type) override;
// Methods to notify the DialRegistry on the correct thread of new/removed
// listeners.
void NotifyListenerAddedOnIOThread();
void NotifyListenerRemovedOnIOThread();
+ // Fills the |device| API struct from |device_data|.
+ void FillDialDevice(const media_router::DialDeviceData& device_data,
+ api::dial::DialDevice* device) const;
+
Profile* profile_;
- // Created lazily on first access on the IO thread.
- std::unique_ptr<api::dial::DialRegistry> dial_registry_;
+ // Created lazily on first access on the IO thread. Does not take ownership of
+ // |dial_registry_|.
+ media_router::DialRegistry* dial_registry_;
// Device data for testing.
- std::unique_ptr<api::dial::DialDeviceData> test_device_data_;
- std::unique_ptr<api::dial::DialDeviceDescriptionData>
+ std::unique_ptr<media_router::DialDeviceData> test_device_data_;
+ std::unique_ptr<media_router::DialDeviceDescriptionData>
test_device_description_;
DISALLOW_COPY_AND_ASSIGN(DialAPI);
@@ -145,11 +150,11 @@ class DialFetchDeviceDescriptionFunction : public AsyncExtensionFunction {
void GetDeviceDescriptionUrlOnIOThread(const std::string& label);
void MaybeStartFetch(const GURL& url);
- void OnFetchComplete(const api::dial::DialDeviceDescriptionData& result);
+ void OnFetchComplete(const media_router::DialDeviceDescriptionData& result);
void OnFetchError(const std::string& result);
std::unique_ptr<api::dial::FetchDeviceDescription::Params> params_;
- std::unique_ptr<api::dial::DeviceDescriptionFetcher>
+ std::unique_ptr<media_router::DeviceDescriptionFetcher>
device_description_fetcher_;
DialAPI* dial_;
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_apitest.cc b/chromium/chrome/browser/extensions/api/dial/dial_apitest.cc
index c3698c52b5a..67049da9bf4 100644
--- a/chromium/chrome/browser/extensions/api/dial/dial_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/dial/dial_apitest.cc
@@ -6,9 +6,9 @@
#include "build/build_config.h"
#include "chrome/browser/extensions/api/dial/dial_api.h"
#include "chrome/browser/extensions/api/dial/dial_api_factory.h"
-#include "chrome/browser/extensions/api/dial/dial_registry.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/media/router/discovery/dial/dial_registry.h"
#include "extensions/common/switches.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
@@ -17,9 +17,9 @@
using extensions::Extension;
using extensions::ResultCatcher;
-using extensions::api::dial::DialDeviceData;
-using extensions::api::dial::DialDeviceDescriptionData;
-using extensions::api::dial::DialRegistry;
+using media_router::DialDeviceData;
+using media_router::DialDeviceDescriptionData;
+using media_router::DialRegistry;
namespace {
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_device_data.cc b/chromium/chrome/browser/extensions/api/dial/dial_device_data.cc
deleted file mode 100644
index 1db2e5c38b5..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_device_data.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-
-#include "chrome/common/extensions/api/dial.h"
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-DialDeviceData::DialDeviceData() : max_age_(-1), config_id_(-1) { }
-
-DialDeviceData::DialDeviceData(const std::string& device_id,
- const GURL& device_description_url,
- const base::Time& response_time)
- : device_id_(device_id), device_description_url_(device_description_url),
- response_time_(response_time), max_age_(-1), config_id_(-1) {
-}
-
-DialDeviceData::DialDeviceData(const DialDeviceData& other) = default;
-
-DialDeviceData::~DialDeviceData() { }
-
-const GURL& DialDeviceData::device_description_url() const {
- return device_description_url_;
-}
-
-void DialDeviceData::set_device_description_url(const GURL& url) {
- device_description_url_ = url;
-}
-
-// static
-bool DialDeviceData::IsDeviceDescriptionUrl(const GURL& url) {
- return url.is_valid() && !url.is_empty() && url.SchemeIsHTTPOrHTTPS();
-}
-
-bool DialDeviceData::UpdateFrom(const DialDeviceData& new_data) {
- DCHECK(new_data.device_id() == device_id_);
- DCHECK(new_data.label().empty());
- std::string label_tmp(label_);
- bool updated_api_visible_field =
- (new_data.device_description_url() != device_description_url_) ||
- (new_data.config_id() != config_id_);
- *this = new_data;
- label_ = label_tmp;
- return updated_api_visible_field;
-}
-
-void DialDeviceData::FillDialDevice(api::dial::DialDevice* device) const {
- DCHECK(!device_id_.empty());
- DCHECK(IsDeviceDescriptionUrl(device_description_url_));
- device->device_label = label_;
- device->device_description_url = device_description_url_.spec();
- if (has_config_id())
- device->config_id.reset(new int(config_id_));
-}
-
-DialDeviceDescriptionData::DialDeviceDescriptionData(
- const std::string& device_description,
- const GURL& app_url)
- : device_description(device_description), app_url(app_url) {}
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_device_data.h b/chromium/chrome/browser/extensions/api/dial/dial_device_data.h
deleted file mode 100644
index 4706885a465..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_device_data.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_DEVICE_DATA_H_
-#define CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_DEVICE_DATA_H_
-
-#include <string>
-#include <vector>
-
-#include "base/time/time.h"
-#include "base/values.h"
-#include "url/gurl.h"
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-struct DialDevice;
-
-// Dial device information that is used within the DialService and Registry on
-// the IO thread. It is updated as new information arrives and a list of
-// DialDeviceData is copied and sent to event listeners on the UI thread.
-class DialDeviceData {
- public:
- DialDeviceData();
- DialDeviceData(const std::string& device_id,
- const GURL& device_description_url,
- const base::Time& response_time);
- DialDeviceData(const DialDeviceData& other);
- ~DialDeviceData();
-
- bool operator==(const DialDeviceData& other_data) const {
- return device_id_ == other_data.device_id_;
- }
-
- const std::string& device_id() const { return device_id_; }
- void set_device_id(const std::string& id) {
- device_id_ = id;
- }
-
- const std::string& label() const { return label_; }
- void set_label(const std::string& label) {
- label_ = label;
- }
-
- const GURL& device_description_url() const;
- void set_device_description_url(const GURL& url);
-
- const base::Time& response_time() const { return response_time_; }
- void set_response_time(const base::Time& response_time) {
- response_time_ = response_time;
- }
-
- int max_age() const { return max_age_; }
- void set_max_age(int max_age) { max_age_ = max_age; }
- bool has_max_age() const { return max_age_ >= 0; }
-
- int config_id() const { return config_id_; }
- void set_config_id(int config_id) { config_id_ = config_id; }
- bool has_config_id() const { return config_id_ >= 0; }
-
- // Fills the |device| API struct from this instance.
- void FillDialDevice(api::dial::DialDevice* device) const;
-
- // Updates this DeviceData based on information from a new response in
- // |new_data|. Returns |true| if a field was updated that is visible through
- // the DIAL API.
- bool UpdateFrom(const DialDeviceData& new_data);
-
- // Validates that the URL is valid for the device description.
- static bool IsDeviceDescriptionUrl(const GURL& url);
-
- private:
- // Hardware identifier from the DIAL response. Not exposed to API clients.
- std::string device_id_;
-
- // Identifies this device to clients of the API as a proxy for the hardware
- // identifier. Automatically generated by the DIAL registry.
- std::string label_;
-
- // The device description URL.
- GURL device_description_url_;
-
- // The time that the most recent response was received.
- base::Time response_time_;
-
- // Optional (-1 means unset).
- int max_age_;
-
- // Optional (-1 means unset).
- int config_id_;
-};
-
-struct DialDeviceDescriptionData {
- public:
- DialDeviceDescriptionData() = default;
- DialDeviceDescriptionData(const std::string& device_description,
- const GURL& app_url);
-
- std::string device_description;
- GURL app_url;
-};
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_DEVICE_DATA_H_
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_device_data_unittest.cc b/chromium/chrome/browser/extensions/api/dial/dial_device_data_unittest.cc
deleted file mode 100644
index fc079a37cd0..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_device_data_unittest.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "chrome/common/extensions/api/dial.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-namespace {
-
-// Asserts equality between the two objects.
-void ExpectEqual(const DialDeviceData& first, const DialDeviceData& second) {
- EXPECT_EQ(first.device_id(), second.device_id());
- EXPECT_EQ(first.label(), second.label());
- EXPECT_EQ(first.device_description_url(), second.device_description_url());
- EXPECT_EQ(first.response_time(), second.response_time());
- EXPECT_EQ(first.max_age(), second.max_age());
- EXPECT_EQ(first.config_id(), second.config_id());
-}
-
-} // namespace
-
-TEST(DialDeviceDataTest, TestFillDialDevice) {
- api::dial::DialDevice api_device;
-
- DialDeviceData device;
- device.set_device_id("device");
- device.set_label("label");
- device.set_device_description_url(GURL("http://127.0.0.1/dd.xml"));
- device.set_config_id(1);
-
- device.FillDialDevice(&api_device);
- EXPECT_EQ(api_device.device_label, device.label());
- EXPECT_EQ(api_device.device_description_url,
- device.device_description_url().spec());
- EXPECT_EQ(*(api_device.config_id), device.config_id());
-}
-
-TEST(DialDeviceDataTest, TestUpdateFrom) {
- DialDeviceData original;
- original.set_device_id("device_a");
- original.set_label("label_a");
- original.set_device_description_url(GURL("http://127.0.0.1/dd-a.xml"));
- original.set_response_time(base::Time::FromInternalValue(1000));
- original.set_max_age(100);
- original.set_config_id(1);
-
- DialDeviceData new_data;
- new_data.set_device_id("device_a");
- new_data.set_device_description_url(GURL("http://127.0.0.1/dd-a.xml"));
- new_data.set_response_time(base::Time::FromInternalValue(1000));
- new_data.set_max_age(100);
- new_data.set_config_id(1);
-
- DialDeviceData original_1(original);
- EXPECT_FALSE(original_1.UpdateFrom(new_data));
- ExpectEqual(original_1, original);
-
- DialDeviceData original_2(original);
- new_data.set_max_age(200);
- new_data.set_response_time(base::Time::FromInternalValue(2000));
- EXPECT_FALSE(original_2.UpdateFrom(new_data));
-
- EXPECT_EQ("device_a", original_2.device_id());
- EXPECT_EQ(GURL("http://127.0.0.1/dd-a.xml"),
- original_2.device_description_url());
- EXPECT_EQ("label_a", original_2.label());
- EXPECT_EQ(200, original_2.max_age());
- EXPECT_EQ(base::Time::FromInternalValue(2000), original_2.response_time());
- EXPECT_EQ(1, original_2.config_id());
-
- DialDeviceData original_3(original);
- new_data.set_device_description_url(GURL("http://127.0.0.2/dd-b.xml"));
- new_data.set_config_id(2);
- EXPECT_TRUE(original_3.UpdateFrom(new_data));
-
- EXPECT_EQ("device_a", original_3.device_id());
- EXPECT_EQ(GURL("http://127.0.0.2/dd-b.xml"),
- original_3.device_description_url());
- EXPECT_EQ("label_a", original_3.label());
- EXPECT_EQ(200, original_3.max_age());
- EXPECT_EQ(base::Time::FromInternalValue(2000), original_3.response_time());
- EXPECT_EQ(2, original_3.config_id());
-}
-
-TEST(DialDeviceDataTest, TestIsDeviceDescriptionUrl) {
- EXPECT_TRUE(DialDeviceData::IsDeviceDescriptionUrl(
- GURL("http://some.device.com/dd.xml")));
- EXPECT_TRUE(DialDeviceData::IsDeviceDescriptionUrl(
- GURL("https://some.device.com/dd.xml")));
- EXPECT_TRUE(DialDeviceData::IsDeviceDescriptionUrl(
- GURL("http://192.168.1.1:1234/dd.xml")));
- EXPECT_TRUE(DialDeviceData::IsDeviceDescriptionUrl(
- GURL("https://192.168.1.1:1234/dd.xml")));
-
- EXPECT_FALSE(DialDeviceData::IsDeviceDescriptionUrl(GURL()));
- EXPECT_FALSE(DialDeviceData::IsDeviceDescriptionUrl(GURL(std::string())));
- EXPECT_FALSE(
- DialDeviceData::IsDeviceDescriptionUrl(GURL("file://path/to/file")));
-}
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_registry.cc b/chromium/chrome/browser/extensions/api/dial/dial_registry.cc
deleted file mode 100644
index 752dbd69f9f..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_registry.cc
+++ /dev/null
@@ -1,359 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/dial/dial_registry.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/api/dial/dial_api.h"
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "chrome/browser/extensions/api/dial/dial_service.h"
-#include "chrome/common/extensions/api/dial.h"
-#include "components/net_log/chrome_net_log.h"
-#include "content/public/browser/browser_thread.h"
-
-using base::Time;
-using base::TimeDelta;
-using content::BrowserThread;
-using net::NetworkChangeNotifier;
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-DialRegistry::DialRegistry(Observer* dial_api,
- const base::TimeDelta& refresh_interval,
- const base::TimeDelta& expiration,
- const size_t max_devices)
- : num_listeners_(0),
- registry_generation_(0),
- last_event_registry_generation_(0),
- label_count_(0),
- refresh_interval_delta_(refresh_interval),
- expiration_delta_(expiration),
- max_devices_(max_devices),
- dial_api_(dial_api) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK_GT(max_devices_, 0U);
- NetworkChangeNotifier::AddNetworkChangeObserver(this);
-}
-
-DialRegistry::~DialRegistry() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-}
-
-std::unique_ptr<DialService> DialRegistry::CreateDialService() {
- DCHECK(g_browser_process->net_log());
- return base::MakeUnique<DialServiceImpl>(g_browser_process->net_log());
-}
-
-void DialRegistry::ClearDialService() {
- dial_.reset();
-}
-
-base::Time DialRegistry::Now() const {
- return Time::Now();
-}
-
-void DialRegistry::OnListenerAdded() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (++num_listeners_ == 1) {
- VLOG(2) << "Listener added; starting periodic discovery.";
- StartPeriodicDiscovery();
- }
- // Event listeners with the current device list.
- // TODO(crbug.com/576817): Rework the DIAL API so we don't need to have extra
- // behaviors when adding listeners.
- SendEvent();
-}
-
-void DialRegistry::OnListenerRemoved() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK_GT(num_listeners_, 0);
- if (--num_listeners_ == 0) {
- VLOG(2) << "Listeners removed; stopping periodic discovery.";
- StopPeriodicDiscovery();
- }
-}
-
-GURL DialRegistry::GetDeviceDescriptionURL(const std::string& label) const {
- const auto device_it = device_by_label_map_.find(label);
- if (device_it != device_by_label_map_.end())
- return device_it->second->device_description_url();
-
- return GURL();
-}
-
-void DialRegistry::AddDeviceForTest(const DialDeviceData& device_data) {
- std::unique_ptr<DialDeviceData> test_data =
- base::MakeUnique<DialDeviceData>(device_data);
- device_by_label_map_.insert(
- std::make_pair(device_data.label(), test_data.get()));
- device_by_id_map_.insert(
- std::make_pair(device_data.device_id(), std::move(test_data)));
-}
-
-bool DialRegistry::ReadyToDiscover() {
- if (num_listeners_ == 0) {
- dial_api_->OnDialError(DIAL_NO_LISTENERS);
- return false;
- }
- if (NetworkChangeNotifier::IsOffline()) {
- dial_api_->OnDialError(DIAL_NETWORK_DISCONNECTED);
- return false;
- }
- if (NetworkChangeNotifier::IsConnectionCellular(
- NetworkChangeNotifier::GetConnectionType())) {
- dial_api_->OnDialError(DIAL_CELLULAR_NETWORK);
- return false;
- }
- return true;
-}
-
-bool DialRegistry::DiscoverNow() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ReadyToDiscover()) {
- return false;
- }
- if (!dial_) {
- dial_api_->OnDialError(DIAL_UNKNOWN);
- return false;
- }
-
- if (!dial_->HasObserver(this))
- NOTREACHED() << "DiscoverNow() called without observing dial_";
-
- // Force increment |registry_generation_| to ensure an event is sent even if
- // the device list did not change.
- bool started = dial_->Discover();
- if (started)
- ++registry_generation_;
-
- return started;
-}
-
-void DialRegistry::StartPeriodicDiscovery() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!ReadyToDiscover() || dial_)
- return;
-
- dial_ = CreateDialService();
- dial_->AddObserver(this);
- DoDiscovery();
- repeating_timer_.Start(FROM_HERE,
- refresh_interval_delta_,
- this,
- &DialRegistry::DoDiscovery);
-}
-
-void DialRegistry::DoDiscovery() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(dial_);
- VLOG(2) << "About to discover!";
- dial_->Discover();
-}
-
-void DialRegistry::StopPeriodicDiscovery() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!dial_)
- return;
-
- repeating_timer_.Stop();
- dial_->RemoveObserver(this);
- ClearDialService();
-}
-
-bool DialRegistry::PruneExpiredDevices() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- bool pruned_device = false;
- DeviceByLabelMap::iterator it = device_by_label_map_.begin();
- while (it != device_by_label_map_.end()) {
- auto* device = it->second;
- if (IsDeviceExpired(*device)) {
- VLOG(2) << "Device " << device->label() << " expired, removing";
-
- // Make a copy of the device ID here since |device| will be destroyed
- // during erase().
- std::string device_id = device->device_id();
- const size_t num_erased_by_id = device_by_id_map_.erase(device_id);
- DCHECK_EQ(1U, num_erased_by_id);
- device_by_label_map_.erase(it++);
- pruned_device = true;
- } else {
- ++it;
- }
- }
- return pruned_device;
-}
-
-bool DialRegistry::IsDeviceExpired(const DialDeviceData& device) const {
- Time now = Now();
-
- // Check against our default expiration timeout.
- Time default_expiration_time = device.response_time() + expiration_delta_;
- if (now > default_expiration_time)
- return true;
-
- // Check against the device's cache-control header, if set.
- if (device.has_max_age()) {
- Time max_age_expiration_time =
- device.response_time() + TimeDelta::FromSeconds(device.max_age());
- if (now > max_age_expiration_time)
- return true;
- }
- return false;
-}
-
-void DialRegistry::Clear() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- device_by_id_map_.clear();
- device_by_label_map_.clear();
- registry_generation_++;
-}
-
-void DialRegistry::MaybeSendEvent() {
- // Send an event if the device list has changed since the last event.
- bool needs_event = last_event_registry_generation_ < registry_generation_;
- VLOG(2) << "lerg = " << last_event_registry_generation_ << ", rg = "
- << registry_generation_ << ", needs_event = " << needs_event;
- if (needs_event)
- SendEvent();
-}
-
-void DialRegistry::SendEvent() {
- DeviceList device_list;
- for (DeviceByLabelMap::const_iterator it = device_by_label_map_.begin();
- it != device_by_label_map_.end(); ++it) {
- device_list.push_back(*(it->second));
- }
- dial_api_->OnDialDeviceEvent(device_list);
-
- // Reset watermark.
- last_event_registry_generation_ = registry_generation_;
-}
-
-std::string DialRegistry::NextLabel() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return base::IntToString(++label_count_);
-}
-
-void DialRegistry::OnDiscoveryRequest(DialService* service) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- MaybeSendEvent();
-}
-
-void DialRegistry::OnDeviceDiscovered(DialService* service,
- const DialDeviceData& device) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Adds |device| to our list of devices or updates an existing device, unless
- // |device| is a duplicate. Returns true if the list was modified and
- // increments the list generation.
- auto device_data = base::MakeUnique<DialDeviceData>(device);
- DCHECK(!device_data->device_id().empty());
- DCHECK(device_data->label().empty());
-
- bool did_modify_list = false;
- DeviceByIdMap::iterator lookup_result =
- device_by_id_map_.find(device_data->device_id());
-
- if (lookup_result != device_by_id_map_.end()) {
- VLOG(2) << "Found device " << device_data->device_id() << ", merging";
-
- // Already have previous response. Merge in data from this response and
- // track if there were any API visible changes.
- did_modify_list = lookup_result->second->UpdateFrom(*device_data);
- } else {
- did_modify_list = MaybeAddDevice(std::move(device_data));
- }
-
- if (did_modify_list)
- registry_generation_++;
-
- VLOG(2) << "did_modify_list = " << did_modify_list
- << ", generation = " << registry_generation_;
-}
-
-bool DialRegistry::MaybeAddDevice(std::unique_ptr<DialDeviceData> device_data) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (device_by_id_map_.size() == max_devices_) {
- VLOG(1) << "Maximum registry size reached. Cannot add device.";
- return false;
- }
- device_data->set_label(NextLabel());
- DialDeviceData* device_data_ptr = device_data.get();
- device_by_id_map_[device_data_ptr->device_id()] = std::move(device_data);
- device_by_label_map_[device_data_ptr->label()] = device_data_ptr;
- VLOG(2) << "Added device, id = " << device_data_ptr->device_id()
- << ", label = " << device_data_ptr->label();
- return true;
-}
-
-void DialRegistry::OnDiscoveryFinished(DialService* service) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (PruneExpiredDevices())
- registry_generation_++;
- MaybeSendEvent();
-}
-
-void DialRegistry::OnError(DialService* service,
- const DialService::DialServiceErrorCode& code) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- switch (code) {
- case DialService::DIAL_SERVICE_SOCKET_ERROR:
- dial_api_->OnDialError(DIAL_SOCKET_ERROR);
- break;
- case DialService::DIAL_SERVICE_NO_INTERFACES:
- dial_api_->OnDialError(DIAL_NO_INTERFACES);
- break;
- default:
- NOTREACHED();
- dial_api_->OnDialError(DIAL_UNKNOWN);
- break;
- }
-}
-
-void DialRegistry::OnNetworkChanged(
- NetworkChangeNotifier::ConnectionType type) {
- switch (type) {
- case NetworkChangeNotifier::CONNECTION_NONE:
- if (dial_) {
- VLOG(2) << "Lost connection, shutting down discovery and clearing"
- << " list.";
- dial_api_->OnDialError(DIAL_NETWORK_DISCONNECTED);
-
- StopPeriodicDiscovery();
- // TODO(justinlin): As an optimization, we can probably keep our device
- // list around and restore it if we reconnected to the exact same
- // network.
- Clear();
- MaybeSendEvent();
- }
- break;
- case NetworkChangeNotifier::CONNECTION_2G:
- case NetworkChangeNotifier::CONNECTION_3G:
- case NetworkChangeNotifier::CONNECTION_4G:
- case NetworkChangeNotifier::CONNECTION_ETHERNET:
- case NetworkChangeNotifier::CONNECTION_WIFI:
- case NetworkChangeNotifier::CONNECTION_UNKNOWN:
- case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
- if (!dial_) {
- VLOG(2) << "Connection detected, restarting discovery.";
- StartPeriodicDiscovery();
- }
- break;
- }
-}
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_registry.h b/chromium/chrome/browser/extensions/api/dial/dial_registry.h
deleted file mode 100644
index e43d207bff8..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_registry.h
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_
-#define CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "chrome/browser/extensions/api/dial/dial_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "net/base/network_change_notifier.h"
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-// Keeps track of devices that have responded to discovery requests and notifies
-// the observer with an updated, complete set of active devices. The registry's
-// observer (i.e., the Dial API) owns the registry instance.
-// DialRegistry lives on the IO thread.
-class DialRegistry : public DialService::Observer,
- public net::NetworkChangeNotifier::NetworkChangeObserver {
- public:
- using DeviceList = std::vector<DialDeviceData>;
-
- enum DialErrorCode {
- DIAL_NO_LISTENERS = 0,
- DIAL_NO_INTERFACES,
- DIAL_NETWORK_DISCONNECTED,
- DIAL_CELLULAR_NETWORK,
- DIAL_SOCKET_ERROR,
- DIAL_UNKNOWN
- };
-
- class Observer {
- public:
- // Methods invoked on the IO thread when a new device is discovered, an
- // update is triggered by dial.discoverNow or an error occured.
- virtual void OnDialDeviceEvent(const DeviceList& devices) = 0;
- virtual void OnDialError(DialErrorCode type) = 0;
-
- protected:
- virtual ~Observer() {}
- };
-
- // Create the DIAL registry and pass a reference to allow it to notify on
- // DIAL device events.
- DialRegistry(Observer* dial_api,
- const base::TimeDelta& refresh_interval,
- const base::TimeDelta& expiration,
- const size_t max_devices);
-
- ~DialRegistry() override;
-
- // Called by the DIAL API when event listeners are added or removed. The dial
- // service is started after the first listener is added and stopped after the
- // last listener is removed.
- void OnListenerAdded();
- void OnListenerRemoved();
-
- // Called by the DIAL API to try to kickoff a discovery if there is not one
- // already active.
- bool DiscoverNow();
-
- // Returns the URL of the device description for the device identified by
- // |label|, or an empty GURL if no such device exists.
- GURL GetDeviceDescriptionURL(const std::string& label) const;
-
- // Adds a device directly to the registry as if it was discovered. For tests
- // only. Note that if discovery is actually started, this device will be
- // removed by PruneExpiredDevices().
- void AddDeviceForTest(const DialDeviceData& device_data);
-
- protected:
- // Returns a new instance of the DIAL service. Overridden by tests.
- virtual std::unique_ptr<DialService> CreateDialService();
- virtual void ClearDialService();
-
- // Returns the current time. Overridden by tests.
- virtual base::Time Now() const;
-
- // The DIAL service. Periodic discovery is active when this is not NULL.
- std::unique_ptr<DialService> dial_;
-
- private:
- using DeviceByIdMap =
- base::hash_map<std::string, std::unique_ptr<DialDeviceData>>;
- using DeviceByLabelMap = std::map<std::string, DialDeviceData*>;
-
- // DialService::Observer:
- void OnDiscoveryRequest(DialService* service) override;
- void OnDeviceDiscovered(DialService* service,
- const DialDeviceData& device) override;
- void OnDiscoveryFinished(DialService* service) override;
- void OnError(DialService* service,
- const DialService::DialServiceErrorCode& code) override;
-
- // net::NetworkChangeObserver:
- void OnNetworkChanged(
- net::NetworkChangeNotifier::ConnectionType type) override;
-
- // Starts and stops periodic discovery. Periodic discovery is done when there
- // are registered event listeners.
- void StartPeriodicDiscovery();
- void StopPeriodicDiscovery();
-
- // Check whether we are in a state ready to discover and dispatch error
- // notifications if not.
- bool ReadyToDiscover();
-
- // Purge our whole registry. We may need to do this occasionally, e.g. when
- // the network status changes. Increments the registry generation.
- void Clear();
-
- // The repeating timer schedules discoveries with this method.
- void DoDiscovery();
-
- // Attempts to add a newly discovered device to the registry. Returns true if
- // successful.
- bool MaybeAddDevice(std::unique_ptr<DialDeviceData> device_data);
-
- // Remove devices from the registry that have expired, i.e. not responded
- // after some time. Returns true if the registry was modified.
- bool PruneExpiredDevices();
-
- // Returns true if the device has expired and should be removed from the
- // active set.
- bool IsDeviceExpired(const DialDeviceData& device) const;
-
- // Notify listeners with the current device list if the list has changed.
- void MaybeSendEvent();
-
- // Notify listeners with the current device list.
- void SendEvent();
-
- // Returns the next label to use for a newly-seen device.
- std::string NextLabel();
-
- // The current number of event listeners attached to this registry.
- int num_listeners_;
-
- // Incremented each time we modify the registry of active devices.
- int registry_generation_;
-
- // The registry generation associated with the last time we sent an event.
- // Used to suppress events with duplicate device lists.
- int last_event_registry_generation_;
-
- // Counter to generate device labels.
- int label_count_;
-
- // Registry parameters
- const base::TimeDelta refresh_interval_delta_;
- const base::TimeDelta expiration_delta_;
- const size_t max_devices_;
-
- // A map used to track known devices by their device_id.
- DeviceByIdMap device_by_id_map_;
-
- // A map used to track known devices sorted by label. We iterate over this to
- // construct the device list sent to API clients.
- DeviceByLabelMap device_by_label_map_;
-
- // Timer used to manage periodic discovery requests.
- base::RepeatingTimer repeating_timer_;
-
- // Interface from which the DIAL API is notified of DIAL device events. the
- // DIAL API owns this DIAL registry.
- Observer* const dial_api_;
-
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestAddRemoveListeners);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestNoDevicesDiscovered);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestDevicesDiscovered);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest,
- TestDevicesDiscoveredWithTwoListeners);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestDeviceExpires);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestExpiredDeviceIsRediscovered);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest,
- TestRemovingListenerDoesNotClearList);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestNetworkEventConnectionLost);
- FRIEND_TEST_ALL_PREFIXES(DialRegistryTest,
- TestNetworkEventConnectionRestored);
- DISALLOW_COPY_AND_ASSIGN(DialRegistry);
-};
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_REGISTRY_H_
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_registry_unittest.cc b/chromium/chrome/browser/extensions/api/dial/dial_registry_unittest.cc
deleted file mode 100644
index 5c98b0ee5e0..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_registry_unittest.cc
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/memory/ptr_util.h"
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "chrome/browser/extensions/api/dial/dial_registry.h"
-#include "chrome/browser/extensions/api/dial/dial_service.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using base::Time;
-using base::TimeDelta;
-using ::testing::A;
-using ::testing::AtLeast;
-using ::testing::Return;
-using ::testing::InSequence;
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-class MockDialObserver : public DialRegistry::Observer {
- public:
- ~MockDialObserver() override {}
-
- MOCK_METHOD1(OnDialDeviceEvent,
- void(const DialRegistry::DeviceList& devices));
- MOCK_METHOD1(OnDialError, void(DialRegistry::DialErrorCode type));
-};
-
-class MockDialService : public DialService {
- public:
- ~MockDialService() override {}
-
- MOCK_METHOD0(Discover, bool());
- MOCK_METHOD1(AddObserver, void(DialService::Observer*));
- MOCK_METHOD1(RemoveObserver, void(DialService::Observer*));
- MOCK_CONST_METHOD1(HasObserver, bool(const DialService::Observer*));
-};
-
-class MockDialRegistry : public DialRegistry {
- public:
- MockDialRegistry(Observer* dial_api,
- const base::TimeDelta& refresh_interval,
- const base::TimeDelta& expiration,
- const size_t max_devices)
- : DialRegistry(dial_api, refresh_interval, expiration, max_devices),
- time_(Time::Now()) {}
-
- ~MockDialRegistry() override {
- // Don't let the DialRegistry delete this.
- DialService* tmp = dial_.release();
- if (tmp)
- CHECK_EQ(&mock_service_, tmp);
- }
-
- // Returns the mock Dial service.
- MockDialService& mock_service() {
- return mock_service_;
- }
-
- void set_time(Time time) { time_ = time; }
-
- protected:
- base::Time Now() const override { return time_; }
-
- std::unique_ptr<DialService> CreateDialService() override {
- return base::WrapUnique(&mock_service_);
- }
-
- void ClearDialService() override {
- // Release the pointer but don't delete the object because the test owns it.
- CHECK_EQ(&mock_service_, dial_.release());
- }
-
- private:
- MockDialService mock_service_;
-
- // Set to mock out the current time.
- Time time_;
-};
-
-class DialRegistryTest : public testing::Test {
- public:
- DialRegistryTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- first_device_("first", GURL("http://127.0.0.1/dd.xml"), Time::Now()),
- second_device_("second", GURL("http://127.0.0.2/dd.xml"), Time::Now()),
- third_device_("third", GURL("http://127.0.0.3/dd.xml"), Time::Now()) {
- registry_ = base::MakeUnique<MockDialRegistry>(
- &mock_observer_, TimeDelta::FromSeconds(1000),
- TimeDelta::FromSeconds(10), 10);
- list_with_first_device_.push_back(first_device_);
- list_with_second_device_.push_back(second_device_);
- }
-
- protected:
- void SetListenerExpectations() {
- EXPECT_CALL(registry_->mock_service(),
- AddObserver(A<DialService::Observer*>()));
- EXPECT_CALL(registry_->mock_service(),
- RemoveObserver(A<DialService::Observer*>()));
- }
-
- content::TestBrowserThreadBundle thread_bundle_;
- std::unique_ptr<MockDialRegistry> registry_;
- MockDialObserver mock_observer_;
- const DialDeviceData first_device_;
- const DialDeviceData second_device_;
- const DialDeviceData third_device_;
-
- const DialRegistry::DeviceList empty_list_;
- DialRegistry::DeviceList list_with_first_device_;
- DialRegistry::DeviceList list_with_second_device_;
-};
-
-TEST_F(DialRegistryTest, TestAddRemoveListeners) {
- SetListenerExpectations();
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_)).Times(2);
-
- EXPECT_FALSE(registry_->repeating_timer_.IsRunning());
- registry_->OnListenerAdded();
- EXPECT_TRUE(registry_->repeating_timer_.IsRunning());
- registry_->OnListenerAdded();
- EXPECT_TRUE(registry_->repeating_timer_.IsRunning());
- registry_->OnListenerRemoved();
- EXPECT_TRUE(registry_->repeating_timer_.IsRunning());
- registry_->OnListenerRemoved();
- EXPECT_FALSE(registry_->repeating_timer_.IsRunning());
-}
-
-TEST_F(DialRegistryTest, TestNoDevicesDiscovered) {
- SetListenerExpectations();
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(registry_->mock_service(), Discover());
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDiscoveryFinished(nullptr);
- registry_->OnListenerRemoved();
-}
-
-TEST_F(DialRegistryTest, TestDevicesDiscovered) {
- DialRegistry::DeviceList expected_list2;
- expected_list2.push_back(first_device_);
- expected_list2.push_back(second_device_);
-
- SetListenerExpectations();
- InSequence s;
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_));
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(expected_list2));
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, first_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->DoDiscovery();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, second_device_);
- registry_->OnDiscoveryFinished(nullptr);
- registry_->OnListenerRemoved();
-}
-
-TEST_F(DialRegistryTest, TestDevicesDiscoveredWithTwoListeners) {
- DialRegistry::DeviceList expected_list2;
- expected_list2.push_back(first_device_);
- expected_list2.push_back(second_device_);
-
- SetListenerExpectations();
- InSequence s;
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_))
- .Times(2);
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(expected_list2));
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, first_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->OnListenerAdded();
-
- registry_->DoDiscovery();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, second_device_);
- registry_->OnDiscoveryFinished(nullptr);
- registry_->OnListenerRemoved();
- registry_->OnListenerRemoved();
-}
-
-TEST_F(DialRegistryTest, TestDeviceExpires) {
- SetListenerExpectations();
- InSequence s;
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_));
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, first_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->set_time(Time::Now() + TimeDelta::FromSeconds(30));
-
- registry_->DoDiscovery();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDiscoveryFinished(nullptr);
- registry_->OnListenerRemoved();
-}
-
-TEST_F(DialRegistryTest, TestExpiredDeviceIsRediscovered) {
- std::vector<Time> discovery_times;
- discovery_times.push_back(Time::Now());
- discovery_times.push_back(discovery_times[0] + TimeDelta::FromSeconds(30));
- discovery_times.push_back(discovery_times[1] + TimeDelta::FromSeconds(30));
-
- DialDeviceData rediscovered_device("first",
- GURL("http://127.0.0.1/dd.xml"),
- discovery_times[2]);
-
- SetListenerExpectations();
-
- InSequence s;
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_));
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_));
-
- registry_->set_time(discovery_times[0]);
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, first_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- // Will expire "first" device as it is not discovered this time.
- registry_->set_time(discovery_times[1]);
- registry_->DoDiscovery();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDiscoveryFinished(nullptr);
-
- // "first" device is rediscovered 30 seconds later. We pass a device object
- // with a newer discovery time so it is not pruned immediately.
- registry_->set_time(discovery_times[2]);
- registry_->DoDiscovery();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, rediscovered_device);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->OnListenerRemoved();
-}
-
-TEST_F(DialRegistryTest, TestRemovingListenerDoesNotClearList) {
- DialRegistry::DeviceList expected_list2;
- expected_list2.push_back(first_device_);
- expected_list2.push_back(second_device_);
-
- InSequence s;
- EXPECT_CALL(registry_->mock_service(),
- AddObserver(A<DialService::Observer*>()));
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(expected_list2));
- EXPECT_CALL(registry_->mock_service(),
- RemoveObserver(A<DialService::Observer*>()));
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, first_device_);
- registry_->OnDeviceDiscovered(nullptr, second_device_);
- registry_->OnDiscoveryFinished(nullptr);
- registry_->OnListenerRemoved();
-
- // Removing and adding a listener again fires an event with the current device
- // list (even though no new devices were discovered).
- EXPECT_CALL(registry_->mock_service(),
- AddObserver(A<DialService::Observer*>()));
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(expected_list2));
- EXPECT_CALL(registry_->mock_service(),
- RemoveObserver(A<DialService::Observer*>()));
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDiscoveryFinished(nullptr);
- registry_->OnListenerRemoved();
-}
-
-TEST_F(DialRegistryTest, TestNetworkEventConnectionLost) {
- SetListenerExpectations();
-
- InSequence s;
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_));
- EXPECT_CALL(mock_observer_,
- OnDialError(DialRegistry::DIAL_NETWORK_DISCONNECTED));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, first_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
-
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDiscoveryFinished(nullptr);
- registry_->OnListenerRemoved();
-}
-
-TEST_F(DialRegistryTest, TestNetworkEventConnectionRestored) {
- DialRegistry::DeviceList expected_list3;
- expected_list3.push_back(second_device_);
- expected_list3.push_back(third_device_);
-
- // A disconnection should shutdown the DialService, so we expect the observer
- // to be added twice.
- EXPECT_CALL(registry_->mock_service(),
- AddObserver(A<DialService::Observer*>()))
- .Times(2);
- EXPECT_CALL(registry_->mock_service(),
- RemoveObserver(A<DialService::Observer*>()))
- .Times(2);
-
- InSequence s;
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_first_device_));
-
- EXPECT_CALL(mock_observer_,
- OnDialError(DialRegistry::DIAL_NETWORK_DISCONNECTED));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(empty_list_));
-
- EXPECT_CALL(registry_->mock_service(), Discover());
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(list_with_second_device_));
- EXPECT_CALL(mock_observer_, OnDialDeviceEvent(expected_list3));
-
- registry_->OnListenerAdded();
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, first_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
-
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_WIFI);
-
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, second_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-
- registry_->OnDiscoveryRequest(nullptr);
- registry_->OnDeviceDiscovered(nullptr, third_device_);
- registry_->OnDiscoveryFinished(nullptr);
-
- registry_->OnListenerRemoved();
-}
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_service.cc b/chromium/chrome/browser/extensions/api/dial/dial_service.cc
deleted file mode 100644
index 679b6b0d6cc..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_service.cc
+++ /dev/null
@@ -1,626 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/dial/dial_service.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <set>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/rand_util.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "components/version_info/version_info.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/address_family.h"
-#include "net/base/completion_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_errors.h"
-#include "net/base/network_interfaces.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "net/log/net_log.h"
-#include "net/log/net_log_source_type.h"
-#include "url/gurl.h"
-
-#if defined(OS_CHROMEOS)
-#include "chromeos/network/network_state.h"
-#include "chromeos/network/network_state_handler.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
-#endif
-
-using base::Time;
-using base::TimeDelta;
-using content::BrowserThread;
-using net::HttpResponseHeaders;
-using net::HttpUtil;
-using net::IOBufferWithSize;
-using net::IPAddress;
-using net::NetworkInterface;
-using net::NetworkInterfaceList;
-using net::StringIOBuffer;
-using net::UDPSocket;
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-namespace {
-
-// The total number of requests to make per discovery cycle.
-const int kDialMaxRequests = 4;
-
-// The interval to wait between successive requests.
-const int kDialRequestIntervalMillis = 1000;
-
-// The maximum delay a device may wait before responding (MX).
-const int kDialMaxResponseDelaySecs = 1;
-
-// The maximum time a response is expected after a M-SEARCH request.
-const int kDialResponseTimeoutSecs = 2;
-
-// The multicast IP address for discovery.
-const char kDialRequestAddress[] = "239.255.255.250";
-
-// The UDP port number for discovery.
-const uint16_t kDialRequestPort = 1900;
-
-// The DIAL service type as part of the search request.
-const char kDialSearchType[] = "urn:dial-multiscreen-org:service:dial:1";
-
-// SSDP headers parsed from the response.
-const char kSsdpLocationHeader[] = "LOCATION";
-const char kSsdpCacheControlHeader[] = "CACHE-CONTROL";
-const char kSsdpConfigIdHeader[] = "CONFIGID.UPNP.ORG";
-const char kSsdpUsnHeader[] = "USN";
-
-// The receive buffer size, in bytes.
-const int kDialRecvBufferSize = 1500;
-
-// Gets a specific header from |headers| and puts it in |value|.
-bool GetHeader(HttpResponseHeaders* headers, const char* name,
- std::string* value) {
- return headers->EnumerateHeader(nullptr, std::string(name), value);
-}
-
-// Returns the request string.
-std::string BuildRequest() {
- // Extra line at the end to make UPnP lib happy.
- std::string request(base::StringPrintf(
- "M-SEARCH * HTTP/1.1\r\n"
- "HOST: %s:%u\r\n"
- "MAN: \"ssdp:discover\"\r\n"
- "MX: %d\r\n"
- "ST: %s\r\n"
- "USER-AGENT: %s/%s %s\r\n"
- "\r\n",
- kDialRequestAddress,
- kDialRequestPort,
- kDialMaxResponseDelaySecs,
- kDialSearchType,
- version_info::GetProductName().c_str(),
- version_info::GetVersionNumber().c_str(),
- version_info::GetOSType().c_str()));
- // 1500 is a good MTU value for most Ethernet LANs.
- DCHECK_LE(request.size(), 1500U);
- return request;
-}
-
-#if defined(OS_CHROMEOS)
-// Finds the IP address of the preferred interface of network type |type|
-// to bind the socket and inserts the address into |bind_address_list|. This
-// ChromeOS version can prioritize wifi and ethernet interfaces.
-void InsertBestBindAddressChromeOS(const chromeos::NetworkTypePattern& type,
- net::IPAddressList* bind_address_list) {
- const chromeos::NetworkState* state = chromeos::NetworkHandler::Get()
- ->network_state_handler()->ConnectedNetworkByType(type);
- IPAddress bind_ip_address;
- if (state && bind_ip_address.AssignFromIPLiteral(state->ip_address()) &&
- bind_ip_address.IsIPv4()) {
- VLOG(2) << "Found " << state->type() << ", " << state->name() << ": "
- << state->ip_address();
- bind_address_list->push_back(bind_ip_address);
- }
-}
-#else
-NetworkInterfaceList GetNetworkListOnFileThread() {
- NetworkInterfaceList list;
- bool success =
- net::GetNetworkList(&list, net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
- if (!success)
- VLOG(1) << "Could not retrieve network list!";
- return list;
-}
-#endif // defined(OS_CHROMEOS)
-
-} // namespace
-
-DialServiceImpl::DialSocket::DialSocket(
- const base::Closure& discovery_request_cb,
- const base::Callback<void(const DialDeviceData&)>& device_discovered_cb,
- const base::Closure& on_error_cb)
- : discovery_request_cb_(discovery_request_cb),
- device_discovered_cb_(device_discovered_cb),
- on_error_cb_(on_error_cb),
- is_writing_(false),
- is_reading_(false) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-DialServiceImpl::DialSocket::~DialSocket() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-bool DialServiceImpl::DialSocket::CreateAndBindSocket(
- const IPAddress& bind_ip_address,
- net::NetLog* net_log,
- net::NetLogSource net_log_source) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!socket_);
- DCHECK(bind_ip_address.IsIPv4());
-
- net::RandIntCallback rand_cb = base::Bind(&base::RandInt);
- socket_ = base::MakeUnique<UDPSocket>(net::DatagramSocket::RANDOM_BIND,
- rand_cb, net_log, net_log_source);
-
- // 0 means bind a random port
- net::IPEndPoint address(bind_ip_address, 0);
-
- if (socket_->Open(address.GetFamily()) != net::OK ||
- socket_->SetBroadcast(true) != net::OK ||
- !CheckResult("Bind", socket_->Bind(address))) {
- socket_.reset();
- return false;
- }
-
- recv_buffer_ = new IOBufferWithSize(kDialRecvBufferSize);
- return ReadSocket();
-}
-
-void DialServiceImpl::DialSocket::SendOneRequest(
- const net::IPEndPoint& send_address,
- const scoped_refptr<net::StringIOBuffer>& send_buffer) {
- if (!socket_) {
- VLOG(1) << "Socket not connected.";
- return;
- }
-
- if (is_writing_) {
- VLOG(1) << "Already writing.";
- return;
- }
-
- is_writing_ = true;
- int result = socket_->SendTo(
- send_buffer.get(), send_buffer->size(), send_address,
- base::Bind(&DialServiceImpl::DialSocket::OnSocketWrite,
- base::Unretained(this),
- send_buffer->size()));
- bool result_ok = CheckResult("SendTo", result);
- if (result_ok && result > 0) {
- // Synchronous write.
- OnSocketWrite(send_buffer->size(), result);
- }
-}
-
-bool DialServiceImpl::DialSocket::IsClosed() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return !socket_;
-}
-
-bool DialServiceImpl::DialSocket::CheckResult(const char* operation,
- int result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- VLOG(2) << "Operation " << operation << " result " << result;
- if (result < net::OK && result != net::ERR_IO_PENDING) {
- Close();
- std::string error_str(net::ErrorToString(result));
- VLOG(1) << "dial socket error: " << error_str;
- on_error_cb_.Run();
- return false;
- }
- return true;
-}
-
-void DialServiceImpl::DialSocket::Close() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- is_reading_ = false;
- is_writing_ = false;
- socket_.reset();
-}
-
-void DialServiceImpl::DialSocket::OnSocketWrite(int send_buffer_size,
- int result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- is_writing_ = false;
- if (!CheckResult("OnSocketWrite", result))
- return;
- if (result != send_buffer_size) {
- VLOG(1) << "Sent " << result << " chars, expected "
- << send_buffer_size << " chars";
- }
- discovery_request_cb_.Run();
-}
-
-bool DialServiceImpl::DialSocket::ReadSocket() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!socket_) {
- VLOG(1) << "Socket not connected.";
- return false;
- }
-
- if (is_reading_) {
- VLOG(1) << "Already reading.";
- return false;
- }
-
- int result = net::OK;
- bool result_ok = true;
- do {
- is_reading_ = true;
- result = socket_->RecvFrom(
- recv_buffer_.get(),
- kDialRecvBufferSize, &recv_address_,
- base::Bind(&DialServiceImpl::DialSocket::OnSocketRead,
- base::Unretained(this)));
- result_ok = CheckResult("RecvFrom", result);
- if (result != net::ERR_IO_PENDING)
- is_reading_ = false;
- if (result_ok && result > 0) {
- // Synchronous read.
- HandleResponse(result);
- }
- } while (result_ok && result != net::OK && result != net::ERR_IO_PENDING);
- return result_ok;
-}
-
-void DialServiceImpl::DialSocket::OnSocketRead(int result) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- is_reading_ = false;
- if (!CheckResult("OnSocketRead", result))
- return;
- if (result > 0)
- HandleResponse(result);
-
- // Await next response.
- ReadSocket();
-}
-
-void DialServiceImpl::DialSocket::HandleResponse(int bytes_read) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK_GT(bytes_read, 0);
- if (bytes_read > kDialRecvBufferSize) {
- VLOG(1) << bytes_read << " > " << kDialRecvBufferSize << "!?";
- return;
- }
- VLOG(2) << "Read " << bytes_read << " bytes from "
- << recv_address_.ToString();
-
- std::string response(recv_buffer_->data(), bytes_read);
- Time response_time = Time::Now();
-
- // Attempt to parse response, notify observers if successful.
- DialDeviceData parsed_device;
- if (ParseResponse(response, response_time, &parsed_device))
- device_discovered_cb_.Run(parsed_device);
-}
-
-// static
-bool DialServiceImpl::DialSocket::ParseResponse(
- const std::string& response,
- const base::Time& response_time,
- DialDeviceData* device) {
- int headers_end = HttpUtil::LocateEndOfHeaders(response.c_str(),
- response.size());
- if (headers_end < 1) {
- VLOG(1) << "Headers invalid or empty, ignoring: " << response;
- return false;
- }
- std::string raw_headers =
- HttpUtil::AssembleRawHeaders(response.c_str(), headers_end);
- VLOG(3) << "raw_headers: " << raw_headers << "\n";
- scoped_refptr<HttpResponseHeaders> headers =
- new HttpResponseHeaders(raw_headers);
-
- std::string device_url_str;
- if (!GetHeader(headers.get(), kSsdpLocationHeader, &device_url_str) ||
- device_url_str.empty()) {
- VLOG(1) << "No LOCATION header found.";
- return false;
- }
-
- GURL device_url(device_url_str);
- if (!DialDeviceData::IsDeviceDescriptionUrl(device_url)) {
- VLOG(1) << "URL " << device_url_str << " not valid.";
- return false;
- }
-
- std::string device_id;
- if (!GetHeader(headers.get(), kSsdpUsnHeader, &device_id) ||
- device_id.empty()) {
- VLOG(1) << "No USN header found.";
- return false;
- }
-
- device->set_device_id(device_id);
- device->set_device_description_url(device_url);
- device->set_response_time(response_time);
-
- // TODO(mfoltz): Parse the max-age value from the cache control header.
- // http://crbug.com/165289
- std::string cache_control;
- GetHeader(headers.get(), kSsdpCacheControlHeader, &cache_control);
-
- std::string config_id;
- int config_id_int;
- if (GetHeader(headers.get(), kSsdpConfigIdHeader, &config_id) &&
- base::StringToInt(config_id, &config_id_int)) {
- device->set_config_id(config_id_int);
- } else {
- VLOG(1) << "Malformed or missing " << kSsdpConfigIdHeader << ": "
- << config_id;
- }
-
- return true;
-}
-
-DialServiceImpl::DialServiceImpl(net::NetLog* net_log)
- : net_log_(net_log),
- discovery_active_(false),
- num_requests_sent_(0),
- max_requests_(kDialMaxRequests),
- finish_delay_(TimeDelta::FromMilliseconds((kDialMaxRequests - 1) *
- kDialRequestIntervalMillis) +
- TimeDelta::FromSeconds(kDialResponseTimeoutSecs)),
- request_interval_(
- TimeDelta::FromMilliseconds(kDialRequestIntervalMillis)),
- weak_factory_(this) {
- IPAddress address;
- bool success = address.AssignFromIPLiteral(kDialRequestAddress);
- DCHECK(success);
- send_address_ = net::IPEndPoint(address, kDialRequestPort);
- send_buffer_ = new StringIOBuffer(BuildRequest());
- net_log_source_.type = net::NetLogSourceType::UDP_SOCKET;
- net_log_source_.id = net_log_->NextID();
-}
-
-DialServiceImpl::~DialServiceImpl() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-void DialServiceImpl::AddObserver(Observer* observer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- observer_list_.AddObserver(observer);
-}
-
-void DialServiceImpl::RemoveObserver(Observer* observer) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- observer_list_.RemoveObserver(observer);
-}
-
-bool DialServiceImpl::HasObserver(const Observer* observer) const {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return observer_list_.HasObserver(observer);
-}
-
-bool DialServiceImpl::Discover() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (discovery_active_) {
- VLOG(2) << "Discovery is already active - returning.";
- return false;
- }
- discovery_active_ = true;
-
- VLOG(2) << "Discovery started.";
-
- StartDiscovery();
- return true;
-}
-
-void DialServiceImpl::StartDiscovery() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(discovery_active_);
- if (HasOpenSockets()) {
- VLOG(2) << "Calling StartDiscovery() with open sockets. Returning.";
- return;
- }
-
-#if defined(OS_CHROMEOS)
- // The ChromeOS specific version of getting network interfaces does not
- // require trampolining to another thread, and contains additional interface
- // information such as interface types (i.e. wifi vs cellular).
- net::IPAddressList chrome_os_address_list;
- InsertBestBindAddressChromeOS(chromeos::NetworkTypePattern::Ethernet(),
- &chrome_os_address_list);
- InsertBestBindAddressChromeOS(chromeos::NetworkTypePattern::WiFi(),
- &chrome_os_address_list);
- DiscoverOnAddresses(chrome_os_address_list);
-
-#else
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE, FROM_HERE, base::Bind(&GetNetworkListOnFileThread),
- base::Bind(&DialServiceImpl::SendNetworkList,
- weak_factory_.GetWeakPtr()));
-#endif
-}
-
-void DialServiceImpl::SendNetworkList(const NetworkInterfaceList& networks) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- using InterfaceIndexAddressFamily = std::pair<uint32_t, net::AddressFamily>;
- std::set<InterfaceIndexAddressFamily> interface_index_addr_family_seen;
- net::IPAddressList ip_addresses;
-
- // Binds a socket to each IPv4 network interface found. Note that
- // there may be duplicates in |networks|, so address family + interface index
- // is used to identify unique interfaces.
- // TODO(mfoltz): Support IPV6 multicast. http://crbug.com/165286
- for (NetworkInterfaceList::const_iterator iter = networks.begin();
- iter != networks.end(); ++iter) {
- net::AddressFamily addr_family = net::GetAddressFamily(iter->address);
- VLOG(2) << "Found " << iter->name << ", " << iter->address.ToString()
- << ", address family: " << addr_family;
- if (addr_family == net::ADDRESS_FAMILY_IPV4) {
- InterfaceIndexAddressFamily interface_index_addr_family =
- std::make_pair(iter->interface_index, addr_family);
- bool inserted = interface_index_addr_family_seen
- .insert(interface_index_addr_family)
- .second;
- // We have not seen this interface before, so add its IP address to the
- // discovery list.
- if (inserted) {
- VLOG(2) << "Encountered "
- << "interface index: " << iter->interface_index << ", "
- << "address family: " << addr_family << " for the first time, "
- << "adding IP address " << iter->address.ToString()
- << " to list.";
- ip_addresses.push_back(iter->address);
- } else {
- VLOG(2) << "Already encountered "
- << "interface index: " << iter->interface_index << ", "
- << "address family: " << addr_family << " before, not adding.";
- }
- }
- }
-
- DiscoverOnAddresses(ip_addresses);
-}
-
-void DialServiceImpl::DiscoverOnAddresses(
- const net::IPAddressList& ip_addresses) {
- if (ip_addresses.empty()) {
- VLOG(1) << "Could not find a valid interface to bind. Finishing discovery";
- FinishDiscovery();
- return;
- }
-
- // Schedule a timer to finish the discovery process (and close the sockets).
- if (finish_delay_ > TimeDelta::FromSeconds(0)) {
- VLOG(2) << "Starting timer to finish discovery.";
- finish_timer_.Start(FROM_HERE,
- finish_delay_,
- this,
- &DialServiceImpl::FinishDiscovery);
- }
-
- for (const auto& address : ip_addresses) {
- BindAndAddSocket(address);
- }
-
- SendOneRequest();
-}
-
-void DialServiceImpl::BindAndAddSocket(const IPAddress& bind_ip_address) {
- std::unique_ptr<DialServiceImpl::DialSocket> dial_socket(CreateDialSocket());
- if (dial_socket->CreateAndBindSocket(bind_ip_address, net_log_,
- net_log_source_))
- dial_sockets_.push_back(std::move(dial_socket));
-}
-
-std::unique_ptr<DialServiceImpl::DialSocket>
-DialServiceImpl::CreateDialSocket() {
- return base::MakeUnique<DialServiceImpl::DialSocket>(
- base::Bind(&DialServiceImpl::NotifyOnDiscoveryRequest,
- weak_factory_.GetWeakPtr()),
- base::Bind(&DialServiceImpl::NotifyOnDeviceDiscovered,
- weak_factory_.GetWeakPtr()),
- base::Bind(&DialServiceImpl::NotifyOnError, weak_factory_.GetWeakPtr()));
-}
-
-void DialServiceImpl::SendOneRequest() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (num_requests_sent_ == max_requests_) {
- VLOG(2) << "Reached max requests; stopping request timer.";
- request_timer_.Stop();
- return;
- }
- num_requests_sent_++;
- VLOG(2) << "Sending request " << num_requests_sent_ << "/"
- << max_requests_;
- for (const auto& socket : dial_sockets_) {
- if (!socket->IsClosed())
- socket->SendOneRequest(send_address_, send_buffer_);
- }
-}
-
-void DialServiceImpl::NotifyOnDiscoveryRequest() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // If discovery is inactive, no reason to notify observers.
- if (!discovery_active_) {
- VLOG(2) << "Request sent after discovery finished. Ignoring.";
- return;
- }
-
- VLOG(2) << "Notifying observers of discovery request";
- for (auto& observer : observer_list_)
- observer.OnDiscoveryRequest(this);
- // If we need to send additional requests, schedule a timer to do so.
- if (num_requests_sent_ < max_requests_ && num_requests_sent_ == 1) {
- VLOG(2) << "Scheduling timer to send additional requests";
- // TODO(imcheng): Move this to SendOneRequest() once the implications are
- // understood.
- request_timer_.Start(FROM_HERE,
- request_interval_,
- this,
- &DialServiceImpl::SendOneRequest);
- }
-}
-
-void DialServiceImpl::NotifyOnDeviceDiscovered(
- const DialDeviceData& device_data) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!discovery_active_) {
- VLOG(2) << "Got response after discovery finished. Ignoring.";
- return;
- }
- for (auto& observer : observer_list_)
- observer.OnDeviceDiscovered(this, device_data);
-}
-
-void DialServiceImpl::NotifyOnError() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(imcheng): Modify upstream so that the device list is not cleared
- // when it could still potentially discover devices on other sockets.
- for (auto& observer : observer_list_) {
- observer.OnError(this, HasOpenSockets() ? DIAL_SERVICE_SOCKET_ERROR
- : DIAL_SERVICE_NO_INTERFACES);
- }
-}
-
-void DialServiceImpl::FinishDiscovery() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(discovery_active_);
- VLOG(2) << "Discovery finished.";
- // Close all open sockets.
- dial_sockets_.clear();
- finish_timer_.Stop();
- request_timer_.Stop();
- discovery_active_ = false;
- num_requests_sent_ = 0;
- for (auto& observer : observer_list_)
- observer.OnDiscoveryFinished(this);
-}
-
-bool DialServiceImpl::HasOpenSockets() {
- for (const auto& socket : dial_sockets_) {
- if (!socket->IsClosed())
- return true;
- }
- return false;
-}
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_service.h b/chromium/chrome/browser/extensions/api/dial/dial_service.h
deleted file mode 100644
index dfe56c1986d..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_service.h
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_SERVICE_H_
-#define CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_SERVICE_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/timer/timer.h"
-#include "net/base/ip_address.h"
-#include "net/log/net_log_source.h"
-#include "net/socket/udp_socket.h"
-
-namespace net {
-class IPEndPoint;
-class StringIOBuffer;
-class NetLog;
-}
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-class DialDeviceData;
-
-// DialService accepts requests to discover devices, sends multiple M-SEARCH
-// requests via UDP multicast, and notifies observers when a DIAL-compliant
-// device responds.
-//
-// Each time Discover() is called, kDialNumRequests M-SEARCH requests are sent
-// (with a delay of kDialRequestIntervalMillis in between):
-//
-// Time Action
-// ---- ------
-// T1 Request 1 sent, OnDiscoveryReqest() called
-// ...
-// Tk Request kDialNumRequests sent, OnDiscoveryReqest() called
-// Tf OnDiscoveryFinished() called
-//
-// Any time a valid response is received between T1 and Tf, it is parsed and
-// OnDeviceDiscovered() is called with the result. Tf is set to Tk +
-// kDialResponseTimeoutSecs (the response timeout passed in each request).
-//
-// Calling Discover() again between T1 and Tf has no effect.
-//
-// All relevant constants are defined in dial_service.cc.
-class DialService {
- public:
- enum DialServiceErrorCode {
- DIAL_SERVICE_NO_INTERFACES = 0,
- DIAL_SERVICE_SOCKET_ERROR
- };
-
- class Observer {
- public:
- // Called when a single discovery request was sent.
- virtual void OnDiscoveryRequest(DialService* service) = 0;
-
- // Called when a device responds to a request.
- virtual void OnDeviceDiscovered(DialService* service,
- const DialDeviceData& device) = 0;
-
- // Called when we have all responses from the last discovery request.
- virtual void OnDiscoveryFinished(DialService* service) = 0;
-
- // Called when an error occurs.
- virtual void OnError(DialService* service,
- const DialServiceErrorCode& code) = 0;
-
- protected:
- virtual ~Observer() {}
- };
-
- virtual ~DialService() {}
-
- // Starts a new round of discovery. Returns |true| if discovery was started
- // successfully or there is already one active. Returns |false| on error.
- virtual bool Discover() = 0;
-
- // Called by listeners to this service to add/remove themselves as observers.
- virtual void AddObserver(Observer* observer) = 0;
- virtual void RemoveObserver(Observer* observer) = 0;
- virtual bool HasObserver(const Observer* observer) const = 0;
-};
-
-// Implements DialService.
-//
-// NOTE(mfoltz): It would make this class cleaner to refactor most of the state
-// associated with a single discovery cycle into its own |DiscoveryOperation|
-// object. This would also simplify lifetime of the object w.r.t. DialRegistry;
-// the Registry would not need to create/destroy the Service on demand.
-// DialServiceImpl lives on the IO thread.
-class DialServiceImpl : public DialService {
- public:
- explicit DialServiceImpl(net::NetLog* net_log);
- ~DialServiceImpl() override;
-
- // DialService implementation
- bool Discover() override;
- void AddObserver(Observer* observer) override;
- void RemoveObserver(Observer* observer) override;
- bool HasObserver(const Observer* observer) const override;
-
- private:
- // Represents a socket binding to a single network interface.
- // DialSocket lives on the IO thread.
- class DialSocket {
- public:
- // TODO(imcheng): Consider writing a DialSocket::Delegate interface that
- // declares methods for these callbacks, and taking a ptr to the delegate
- // here.
- DialSocket(
- const base::Closure& discovery_request_cb,
- const base::Callback<void(const DialDeviceData&)>& device_discovered_cb,
- const base::Closure& on_error_cb);
- ~DialSocket();
-
- // Creates a socket using |net_log| and |net_log_source| and binds it to
- // |bind_ip_address|.
- bool CreateAndBindSocket(const net::IPAddress& bind_ip_address,
- net::NetLog* net_log,
- net::NetLogSource net_log_source);
-
- // Sends a single discovery request |send_buffer| to |send_address|
- // over the socket.
- void SendOneRequest(const net::IPEndPoint& send_address,
- const scoped_refptr<net::StringIOBuffer>& send_buffer);
-
- // Returns true if the socket is closed.
- bool IsClosed();
-
- private:
- // Checks the result of a socket operation. The name of the socket
- // operation is given by |operation| and the result of the operation is
- // given by |result|. If the result is an error, closes the socket,
- // calls |on_error_cb_|, and returns |false|. Returns
- // |true| otherwise. |operation| and |result| are logged.
- bool CheckResult(const char* operation, int result);
-
- // Closes the socket.
- void Close();
-
- // Callback invoked for socket writes.
- void OnSocketWrite(int buffer_size, int result);
-
- // Establishes the callback to read from the socket. Returns true if
- // successful.
- bool ReadSocket();
-
- // Callback invoked for socket reads.
- void OnSocketRead(int result);
-
- // Callback invoked for socket reads.
- void HandleResponse(int bytes_read);
-
- // Parses a response into a DialDeviceData object. If the DIAL response is
- // invalid or does not contain enough information, then the return
- // value will be false and |device| is not changed.
- static bool ParseResponse(const std::string& response,
- const base::Time& response_time,
- DialDeviceData* device);
-
- // The UDP socket.
- std::unique_ptr<net::UDPSocket> socket_;
-
- // Buffer for socket reads.
- scoped_refptr<net::IOBufferWithSize> recv_buffer_;
-
- // The source of of the last socket read.
- net::IPEndPoint recv_address_;
-
- // The callback to be invoked when a discovery request was made.
- base::Closure discovery_request_cb_;
-
- // The callback to be invoked when a device has been discovered.
- base::Callback<void(const DialDeviceData&)> device_discovered_cb_;
-
- // The callback to be invoked when there is an error with socket operations.
- base::Closure on_error_cb_;
-
- // Marks whether there is an active write callback.
- bool is_writing_;
-
- // Marks whether there is an active read callback.
- bool is_reading_;
-
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestNotifyOnError);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestOnDeviceDiscovered);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestOnDiscoveryRequest);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestResponseParsing);
- DISALLOW_COPY_AND_ASSIGN(DialSocket);
- };
-
- // Starts the control flow for one discovery cycle.
- void StartDiscovery();
-
- // For each network interface in |list|, finds all unqiue IPv4 network
- // interfaces and call |DiscoverOnAddresses()| with their IP addresses.
- void SendNetworkList(const net::NetworkInterfaceList& list);
-
- // Calls |BindAndAddSocket()| for each address in |ip_addresses|, calls
- // |SendOneRequest()|, and start the timer to finish discovery if needed.
- // The (Address family, interface index) of each address in |ip_addresses|
- // must be unique. If |ip_address| is empty, calls |FinishDiscovery()|.
- void DiscoverOnAddresses(const net::IPAddressList& ip_addresses);
-
- // Creates a DialSocket, binds it to |bind_ip_address| and if
- // successful, add the DialSocket to |dial_sockets_|.
- void BindAndAddSocket(const net::IPAddress& bind_ip_address);
-
- // Creates a DialSocket with callbacks to this object.
- std::unique_ptr<DialSocket> CreateDialSocket();
-
- // Sends a single discovery request to every socket that are currently open.
- void SendOneRequest();
-
- // Notify observers that a discovery request was made.
- void NotifyOnDiscoveryRequest();
-
- // Notify observers a device has been discovered.
- void NotifyOnDeviceDiscovered(const DialDeviceData& device_data);
-
- // Notify observers that there has been an error with one of the DialSockets.
- void NotifyOnError();
-
- // Called from finish_timer_ when we are done with the current round of
- // discovery.
- void FinishDiscovery();
-
- // Returns |true| if there are open sockets.
- bool HasOpenSockets();
-
- // DialSockets for each network interface whose ip address was
- // successfully bound.
- std::vector<std::unique_ptr<DialSocket>> dial_sockets_;
-
- // The NetLog for this service.
- net::NetLog* const net_log_;
-
- // The NetLog source for this service.
- net::NetLogSource net_log_source_;
-
- // The multicast address:port for search requests.
- net::IPEndPoint send_address_;
-
- // Buffer for socket writes.
- scoped_refptr<net::StringIOBuffer> send_buffer_;
-
- // True when we are currently doing discovery.
- bool discovery_active_;
-
- // The number of requests that have been sent in the current discovery.
- int num_requests_sent_;
-
- // The maximum number of requests to send per discovery cycle.
- int max_requests_;
-
- // Timer for finishing discovery.
- base::OneShotTimer finish_timer_;
-
- // The delay for |finish_timer_|; how long to wait for discovery to finish.
- // Setting this to zero disables the timer.
- base::TimeDelta finish_delay_;
-
- // Timer for sending multiple requests at fixed intervals.
- base::RepeatingTimer request_timer_;
-
- // The delay for |request_timer_|; how long to wait between successive
- // requests.
- base::TimeDelta request_interval_;
-
- // List of observers.
- base::ObserverList<Observer> observer_list_;
-
- base::WeakPtrFactory<DialServiceImpl> weak_factory_;
-
- friend class DialServiceTest;
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestSendMultipleRequests);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestMultipleNetworkInterfaces);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestNotifyOnError);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestOnDeviceDiscovered);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestOnDiscoveryFinished);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestOnDiscoveryRequest);
- FRIEND_TEST_ALL_PREFIXES(DialServiceTest, TestResponseParsing);
- DISALLOW_COPY_AND_ASSIGN(DialServiceImpl);
-};
-
-} // namespace dial
-} // namespace api
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_DIAL_DIAL_SERVICE_H_
diff --git a/chromium/chrome/browser/extensions/api/dial/dial_service_unittest.cc b/chromium/chrome/browser/extensions/api/dial/dial_service_unittest.cc
deleted file mode 100644
index 9c46751de36..00000000000
--- a/chromium/chrome/browser/extensions/api/dial/dial_service_unittest.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/dial/dial_service.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "chrome/browser/extensions/api/dial/dial_device_data.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/network_interfaces.h"
-#include "net/log/test_net_log.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::Time;
-using base::TimeDelta;
-using ::testing::A;
-using ::testing::AtLeast;
-using ::testing::Return;
-
-namespace {
-
-const char kValidResponse[] =
- "HTTP/1.1 OK\r\n"
- "LOCATION: http://127.0.0.1/dd.xml\r\n"
- "USN: some_id\r\n"
- "CACHE-CONTROL: max-age=1800\r\n"
- "CONFIGID.UPNP.ORG: 1\r\n\r\n";
-
-} // namespace
-
-namespace extensions {
-namespace api {
-namespace dial {
-
-class MockObserver : public DialService::Observer {
- public:
- ~MockObserver() override {}
-
- MOCK_METHOD1(OnDiscoveryRequest, void(DialService*));
- MOCK_METHOD2(OnDeviceDiscovered, void(DialService*, const DialDeviceData&));
- MOCK_METHOD1(OnDiscoveryFinished, void(DialService*));
- MOCK_METHOD2(OnError, void(DialService*,
- const DialService::DialServiceErrorCode&));
-};
-
-class DialServiceTest : public testing::Test {
- public:
- DialServiceTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- mock_ip_(net::IPAddress::IPv4AllZeros()),
- dial_service_(&test_net_log_) {
- dial_service_.AddObserver(&mock_observer_);
- dial_socket_ = dial_service_.CreateDialSocket();
- }
- protected:
- content::TestBrowserThreadBundle thread_bundle_;
- net::TestNetLog test_net_log_;
- net::IPAddress mock_ip_;
- DialServiceImpl dial_service_;
- std::unique_ptr<DialServiceImpl::DialSocket> dial_socket_;
- MockObserver mock_observer_;
-};
-
-TEST_F(DialServiceTest, TestSendMultipleRequests) {
- // Setting the finish delay to zero disables the timer that invokes
- // FinishDiscovery().
- dial_service_.finish_delay_ = TimeDelta::FromSeconds(0);
- dial_service_.request_interval_ = TimeDelta::FromSeconds(0);
- dial_service_.max_requests_ = 4;
- dial_service_.discovery_active_ = true;
- EXPECT_CALL(mock_observer_, OnDiscoveryRequest(A<DialService*>())).Times(4);
- EXPECT_CALL(mock_observer_, OnDiscoveryFinished(A<DialService*>())).Times(1);
- dial_service_.BindAndAddSocket(mock_ip_);
- EXPECT_EQ(1u, dial_service_.dial_sockets_.size());
- dial_service_.SendOneRequest();
- base::RunLoop().RunUntilIdle();
- dial_service_.FinishDiscovery();
-}
-
-TEST_F(DialServiceTest, TestMultipleNetworkInterfaces) {
- // Setting the finish delay to zero disables the timer that invokes
- // FinishDiscovery().
- dial_service_.finish_delay_ = TimeDelta::FromSeconds(0);
- dial_service_.request_interval_ = TimeDelta::FromSeconds(0);
- dial_service_.max_requests_ = 4;
- dial_service_.discovery_active_ = true;
- net::NetworkInterfaceList interface_list;
- interface_list.push_back(
- net::NetworkInterface("network1",
- "network1",
- 0,
- net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
- mock_ip_,
- 0,
- net::IP_ADDRESS_ATTRIBUTE_NONE));
- interface_list.push_back(
- net::NetworkInterface("network2",
- "network2",
- 1,
- net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
- mock_ip_,
- 0,
- net::IP_ADDRESS_ATTRIBUTE_NONE));
- interface_list.push_back(
- net::NetworkInterface("network3",
- "network3",
- 2,
- net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
- mock_ip_,
- 0,
- net::IP_ADDRESS_ATTRIBUTE_NONE));
-
- // "network4" is equivalent to "network2" because both the address family
- // and interface index are the same.
- interface_list.push_back(
- net::NetworkInterface("network4",
- "network4",
- 1,
- net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
- mock_ip_,
- 0,
- net::IP_ADDRESS_ATTRIBUTE_NONE));
-
- // 3 sockets * 4 requests per socket = 12 requests
- EXPECT_CALL(mock_observer_, OnDiscoveryRequest(A<DialService*>())).Times(12);
- EXPECT_CALL(mock_observer_, OnDiscoveryFinished(A<DialService*>())).Times(1);
-
- dial_service_.SendNetworkList(interface_list);
- EXPECT_EQ(3u, dial_service_.dial_sockets_.size());
-
- base::RunLoop().RunUntilIdle();
- dial_service_.FinishDiscovery();
-}
-
-TEST_F(DialServiceTest, TestOnDiscoveryRequest) {
- dial_service_.discovery_active_ = true;
- dial_service_.num_requests_sent_ = 1;
- dial_service_.max_requests_ = 1;
- size_t num_bytes = dial_service_.send_buffer_->size();
- EXPECT_CALL(mock_observer_, OnDiscoveryRequest(A<DialService*>())).Times(1);
- dial_socket_->OnSocketWrite(num_bytes, num_bytes);
-}
-
-TEST_F(DialServiceTest, TestOnDeviceDiscovered) {
- dial_service_.discovery_active_ = true;
- int response_size = arraysize(kValidResponse) - 1;
- dial_socket_->recv_buffer_ =
- new net::IOBufferWithSize(response_size);
- strncpy(dial_socket_->recv_buffer_->data(),
- kValidResponse,
- response_size);
- dial_socket_->recv_address_ = net::IPEndPoint(mock_ip_, 12345);
-
- DialDeviceData expected_device;
- expected_device.set_device_id("some_id");
-
- EXPECT_CALL(mock_observer_,
- OnDeviceDiscovered(A<DialService*>(), expected_device))
- .Times(1);
- dial_socket_->OnSocketRead(response_size);
-}
-
-TEST_F(DialServiceTest, TestOnDiscoveryFinished) {
- dial_service_.discovery_active_ = true;
-
- EXPECT_CALL(mock_observer_, OnDiscoveryFinished(A<DialService*>())).Times(1);
- dial_service_.FinishDiscovery();
- EXPECT_FALSE(dial_service_.discovery_active_);
-}
-
-TEST_F(DialServiceTest, TestResponseParsing) {
- Time now = Time::Now();
-
- // Successful case
- DialDeviceData parsed;
- EXPECT_TRUE(DialServiceImpl::DialSocket::ParseResponse(
- kValidResponse, now, &parsed));
- EXPECT_EQ("some_id", parsed.device_id());
- EXPECT_EQ("http://127.0.0.1/dd.xml", parsed.device_description_url().spec());
- EXPECT_EQ(1, parsed.config_id());
- EXPECT_EQ(now, parsed.response_time());
-
- // Failure cases
- DialDeviceData not_parsed;
-
- // Empty, garbage
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- std::string(), now, &not_parsed));
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- "\r\n\r\n",
- now, &not_parsed));
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- "xyzzy",
- now, &not_parsed));
-
- // No headers
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- "HTTP/1.1 OK\r\n\r\n",
- now, &not_parsed));
-
- // Missing LOCATION
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- "HTTP/1.1 OK\r\n"
- "USN: some_id\r\n\r\n",
- now, &not_parsed));
-
- // Empty LOCATION
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- "HTTP/1.1 OK\r\n"
- "LOCATION:\r\n"
- "USN: some_id\r\n\r\n",
- now, &not_parsed));
-
- // Missing USN
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- "HTTP/1.1 OK\r\n"
- "LOCATION: http://127.0.0.1/dd.xml\r\n\r\n",
- now, &not_parsed));
-
- // Empty USN
- EXPECT_FALSE(DialServiceImpl::DialSocket::ParseResponse(
- "HTTP/1.1 OK\r\n"
- "LOCATION: http://127.0.0.1/dd.xml\r\n"
- "USN:\r\n\r\n",
- now, &not_parsed));
-}
-
-} // namespace dial
-} // namespace api
-} // 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 c50afbbc1b8..0c9d52254e5 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -476,8 +476,8 @@ void CompileDownloadQueryOrderBy(
DownloadQuery* query) {
// TODO(benjhayden): Consider switching from LazyInstance to explicit string
// comparisons.
- static base::LazyInstance<SortTypeMap> sorter_types =
- LAZY_INSTANCE_INITIALIZER;
+ static base::LazyInstance<SortTypeMap>::DestructorAtExit sorter_types =
+ LAZY_INSTANCE_INITIALIZER;
if (sorter_types.Get().empty())
InitSortTypeMap(sorter_types.Pointer());
@@ -509,8 +509,8 @@ void RunDownloadQuery(
DownloadQuery::DownloadVector* results) {
// TODO(benjhayden): Consider switching from LazyInstance to explicit string
// comparisons.
- static base::LazyInstance<FilterTypeMap> filter_types =
- LAZY_INSTANCE_INITIALIZER;
+ static base::LazyInstance<FilterTypeMap>::DestructorAtExit filter_types =
+ LAZY_INSTANCE_INITIALIZER;
if (filter_types.Get().empty())
InitFilterTypeMap(filter_types.Pointer());
@@ -1524,7 +1524,7 @@ void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) {
return;
}
RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON);
- SetResult(base::MakeUnique<base::StringValue>(url));
+ SetResult(base::MakeUnique<base::Value>(url));
SendResponse(true);
}
@@ -1824,9 +1824,9 @@ void ExtensionDownloadsEventRouter::OnDownloadUpdated(
if (!data->json().HasKey(iter.key()) ||
(data->json().Get(iter.key(), &old_value) &&
!iter.value().Equals(old_value))) {
- delta->Set(iter.key() + ".current", iter.value().DeepCopy());
+ delta->Set(iter.key() + ".current", iter.value().CreateDeepCopy());
if (old_value)
- delta->Set(iter.key() + ".previous", old_value->DeepCopy());
+ delta->Set(iter.key() + ".previous", old_value->CreateDeepCopy());
changed = true;
}
}
@@ -1839,7 +1839,7 @@ void ExtensionDownloadsEventRouter::OnDownloadUpdated(
if ((new_fields.find(iter.key()) == new_fields.end()) &&
IsDownloadDeltaField(iter.key())) {
// estimatedEndTime disappears after completion, but bytesReceived stays.
- delta->Set(iter.key() + ".previous", iter.value().DeepCopy());
+ delta->Set(iter.key() + ".previous", iter.value().CreateDeepCopy());
changed = true;
}
}
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 ec5b4b1bb99..fe5a9677051 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -432,8 +432,9 @@ class DownloadExtensionTest : public ExtensionApiTest {
(history_info[i].state != content::DownloadItem::CANCELLED
? content::DOWNLOAD_INTERRUPT_REASON_NONE
: content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED),
- false, // opened
- std::vector<DownloadItem::ReceivedSlice>());
+ false, // opened
+ current, // last_access_time
+ false, std::vector<DownloadItem::ReceivedSlice>());
items->push_back(item);
}
@@ -3998,20 +3999,14 @@ IN_PROC_BROWSER_TEST_F(
result_id)));
}
-#if defined(OS_WIN)
// This test is very flaky on Win XP and Aura. http://crbug.com/248438
-#define MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume \
- DISABLED_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume
-#else
-#define MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume \
- DownloadExtensionTest_OnDeterminingFilename_InterruptedResume
-#endif
-
+// Also flaky on Linux. http://crbug.com/700382
+// Also flaky on Mac ASAN with PlzNavigate.
// Test download interruption while extensions determining filename. Should not
// re-dispatch onDeterminingFilename.
IN_PROC_BROWSER_TEST_F(
DownloadExtensionTest,
- MAYBE_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume) {
+ DISABLED_DownloadExtensionTest_OnDeterminingFilename_InterruptedResume) {
LoadExtension("downloads_split");
ASSERT_TRUE(StartEmbeddedTestServer());
GoOnTheRecord();
diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
index 1dfdc65b71a..9082bdb3e06 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api_unittest.cc
@@ -29,6 +29,12 @@ class TestDownloadService : public DownloadServiceImpl {
: DownloadServiceImpl(profile), profile_(profile) {}
~TestDownloadService() override {}
+ void Shutdown() override {
+ DownloadServiceImpl::Shutdown();
+ download_history_.reset();
+ router_.reset();
+ }
+
void set_download_history(std::unique_ptr<DownloadHistory> download_history) {
download_history_.swap(download_history);
}
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/OWNERS b/chromium/chrome/browser/extensions/api/easy_unlock_private/OWNERS
index ce1e7d752b2..60607062dc5 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/OWNERS
@@ -1,2 +1,4 @@
tbarzic@chromium.org
tengs@chromium.org
+
+# COMPONENT: UI>ProximityAuth
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
index 840f60d3f20..2f423b5c986 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
@@ -53,7 +53,7 @@
#include "ui/gfx/range/range.h"
#if defined(OS_CHROMEOS)
-#include "ash/common/system/chromeos/devicetype_utils.h"
+#include "ash/system/devicetype_utils.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
#include "components/user_manager/user.h"
@@ -68,8 +68,8 @@ namespace easy_unlock_private = api::easy_unlock_private;
namespace {
-static base::LazyInstance<BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// Utility method for getting the API's crypto delegate.
EasyUnlockPrivateCryptoDelegate* GetCryptoDelegate(
@@ -1049,16 +1049,11 @@ EasyUnlockPrivateSetAutoPairingResultFunction::Run() {
}
EasyUnlockPrivateFindSetupConnectionFunction::
- EasyUnlockPrivateFindSetupConnectionFunction()
- : bluetooth_throttler_(new cryptauth::BluetoothThrottlerImpl(
- base::MakeUnique<base::DefaultTickClock>())) {}
+ EasyUnlockPrivateFindSetupConnectionFunction() {}
EasyUnlockPrivateFindSetupConnectionFunction::
~EasyUnlockPrivateFindSetupConnectionFunction() {
- // |connection_finder_| has a raw pointer to |bluetooth_throttler_|, so it
- // should be destroyed first.
connection_finder_.reset();
- bluetooth_throttler_.reset();
}
void EasyUnlockPrivateFindSetupConnectionFunction::
@@ -1092,7 +1087,7 @@ bool EasyUnlockPrivateFindSetupConnectionFunction::RunAsync() {
new proximity_auth::BluetoothLowEnergyConnectionFinder(
cryptauth::RemoteDevice(), params->setup_service_uuid,
proximity_auth::BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE,
- nullptr, bluetooth_throttler_.get(), 3));
+ nullptr, cryptauth::BluetoothThrottlerImpl::GetInstance(), 3));
connection_finder_->Find(base::Bind(
&EasyUnlockPrivateFindSetupConnectionFunction::OnConnectionFound, this));
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
index 91416507356..c81dd4bc470 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
@@ -28,7 +28,6 @@ class BrowserContext;
}
namespace cryptauth {
-class BluetoothThrottler;
class Connection;
class ExternalDeviceInfo;
class SecureMessageDelegate;
@@ -486,9 +485,6 @@ class EasyUnlockPrivateFindSetupConnectionFunction
std::unique_ptr<proximity_auth::BluetoothLowEnergyConnectionFinder>
connection_finder_;
- // The connection throttler passed to the BLE connection finder.
- std::unique_ptr<cryptauth::BluetoothThrottler> bluetooth_throttler_;
-
// Used for timing out when waiting for the connection finder to return.
std::unique_ptr<base::Timer> timer_;
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
index 6d0d2f32a62..232618e0e92 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
@@ -98,12 +98,10 @@ class TestableGetPermitAccessFunction
DISALLOW_COPY_AND_ASSIGN(TestableGetPermitAccessFunction);
};
-// Converts a string to a base::BinaryValue value whose buffer contains the
+// Converts a string to a base::Value value whose buffer contains the
// string data without the trailing '\0'.
-std::unique_ptr<base::BinaryValue> StringToBinaryValue(
- const std::string& value) {
- return base::BinaryValue::CreateWithCopiedBuffer(value.data(),
- value.length());
+std::unique_ptr<base::Value> StringToBinaryValue(const std::string& value) {
+ return base::Value::CreateWithCopiedBuffer(value.data(), value.length());
}
// Copies |private_key_source| and |public_key_source| to |private_key_target|
@@ -164,7 +162,7 @@ class EasyUnlockPrivateApiTest : public extensions::ExtensionApiUnittest {
return "";
}
- const base::BinaryValue* result_binary_value;
+ const base::Value* result_binary_value;
if (!result_list->GetBinary(0, &result_binary_value) ||
!result_binary_value) {
LOG(ERROR) << "Result not a binary value.";
@@ -193,11 +191,11 @@ TEST_F(EasyUnlockPrivateApiTest, GenerateEcP256KeyPair) {
ASSERT_TRUE(result_list);
ASSERT_EQ(2u, result_list->GetSize());
- const base::BinaryValue* public_key;
+ const base::Value* public_key;
ASSERT_TRUE(result_list->GetBinary(0, &public_key));
ASSERT_TRUE(public_key);
- const base::BinaryValue* private_key;
+ const base::Value* private_key;
ASSERT_TRUE(result_list->GetBinary(1, &private_key));
ASSERT_TRUE(private_key);
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.cc
index 88fe91ba818..f5cb2fdcf48 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.cc
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.cc
@@ -10,8 +10,8 @@
namespace extensions {
static base::LazyInstance<BrowserContextKeyedAPIFactory<
- ApiResourceManager<EasyUnlockPrivateConnection>>> g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ ApiResourceManager<EasyUnlockPrivateConnection>>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
template <>
BrowserContextKeyedAPIFactory<ApiResourceManager<EasyUnlockPrivateConnection>>*
diff --git a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS
index 7e61e8ee327..eca977606f0 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS
+++ b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS
@@ -1,2 +1,2 @@
-cschuet@chromium.org
+emaxx@chromium.org
pbond@chromium.org
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 8a40a6bcab6..2fdbbc356aa 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
@@ -99,7 +99,7 @@ class EnterpriseDeviceAttributesTest :
std::unique_ptr<chromeos::StubInstallAttributes> attributes =
base::MakeUnique<chromeos::StubInstallAttributes>();
- attributes->SetEnterprise("fake-domain", "fake-id");
+ attributes->SetCloudManaged("fake-domain", "fake-id");
policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
attributes.release());
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 fe4603665fd..3a0a01ad53a 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
@@ -119,7 +119,7 @@ void EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates(
++it) {
std::string der_encoding;
net::X509Certificate::GetDEREncoded((*it)->os_cert_handle(), &der_encoding);
- client_certs->Append(base::BinaryValue::CreateWithCopiedBuffer(
+ client_certs->Append(base::Value::CreateWithCopiedBuffer(
der_encoding.data(), der_encoding.size()));
}
@@ -269,7 +269,8 @@ EnterprisePlatformKeysChallengeMachineKeyFunction::Run() {
base::Closure task = base::Bind(
&EPKPChallengeMachineKey::Run, base::Unretained(impl_),
scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
- callback, StringFromVector(params->challenge));
+ callback, StringFromVector(params->challenge),
+ params->register_key ? *params->register_key : false);
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, task);
return RespondLater();
}
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
index 4a71583f67a..29bda417906 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -161,7 +161,7 @@ class EPKChallengeKeyTestBase : public BrowserWithTestWindowTest {
ON_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
.WillByDefault(Invoke(GetCertificateCallbackTrue));
- stub_install_attributes_.SetEnterprise("google.com", "device_id");
+ stub_install_attributes_.SetCloudManaged("google.com", "device_id");
settings_helper_.ReplaceProvider(chromeos::kDeviceAttestationEnabled);
settings_helper_.SetBoolean(chromeos::kDeviceAttestationEnabled, true);
@@ -262,8 +262,24 @@ class EPKChallengeMachineKeyTest : public EPKChallengeKeyTestBase {
}
std::unique_ptr<base::ListValue> CreateArgs() {
+ return CreateArgsInternal(nullptr);
+ }
+
+ std::unique_ptr<base::ListValue> CreateArgsNoRegister() {
+ return CreateArgsInternal(base::MakeUnique<bool>(false));
+ }
+
+ std::unique_ptr<base::ListValue> CreateArgsRegister() {
+ return CreateArgsInternal(base::MakeUnique<bool>(true));
+ }
+
+ std::unique_ptr<base::ListValue> CreateArgsInternal(
+ std::unique_ptr<bool> register_key) {
std::unique_ptr<base::ListValue> args(new base::ListValue);
- args->Append(base::BinaryValue::CreateWithCopiedBuffer("challenge", 9));
+ args->Append(base::Value::CreateWithCopiedBuffer("challenge", 9));
+ if (register_key) {
+ args->AppendBoolean(*register_key);
+ }
return args;
}
@@ -273,7 +289,7 @@ class EPKChallengeMachineKeyTest : public EPKChallengeKeyTestBase {
};
TEST_F(EPKChallengeMachineKeyTest, NonEnterpriseDevice) {
- stub_install_attributes_.SetConsumer();
+ stub_install_attributes_.SetConsumerOwned();
EXPECT_EQ(EPKPChallengeMachineKey::kNonEnterpriseDeviceError,
RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
@@ -320,6 +336,15 @@ TEST_F(EPKChallengeMachineKeyTest, SignChallengeFailed) {
RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
}
+TEST_F(EPKChallengeMachineKeyTest, KeyRegistrationFailed) {
+ EXPECT_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
+ .WillRepeatedly(Invoke(RegisterKeyCallbackFalse));
+
+ EXPECT_EQ(
+ EPKPChallengeMachineKey::kKeyRegistrationFailedError,
+ RunFunctionAndReturnError(func_.get(), CreateArgsRegister(), browser()));
+}
+
TEST_F(EPKChallengeMachineKeyTest, KeyExists) {
EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
.WillRepeatedly(WithArgs<3>(Invoke(
@@ -331,6 +356,22 @@ TEST_F(EPKChallengeMachineKeyTest, KeyExists) {
utils::RunFunction(func_.get(), CreateArgs(), browser(), utils::NONE));
}
+TEST_F(EPKChallengeMachineKeyTest, KeyNotRegisteredByDefault) {
+ EXPECT_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
+ .Times(0);
+
+ EXPECT_TRUE(
+ utils::RunFunction(func_.get(), CreateArgs(), browser(), utils::NONE));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, KeyNotRegistered) {
+ EXPECT_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
+ .Times(0);
+
+ EXPECT_TRUE(utils::RunFunction(func_.get(), CreateArgsNoRegister(), browser(),
+ utils::NONE));
+}
+
TEST_F(EPKChallengeMachineKeyTest, Success) {
// GetCertificate must be called exactly once.
EXPECT_CALL(mock_attestation_flow_,
@@ -349,7 +390,37 @@ TEST_F(EPKChallengeMachineKeyTest, Success) {
std::unique_ptr<base::Value> value(
RunFunctionAndReturnSingleResult(func_.get(), CreateArgs(), browser()));
- const base::BinaryValue* response;
+ const base::Value* response;
+ ASSERT_TRUE(value->GetAsBinary(&response));
+ EXPECT_EQ("response",
+ std::string(response->GetBuffer(), response->GetSize()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, KeyRegisteredSuccess) {
+ // GetCertificate must be called exactly once.
+ EXPECT_CALL(mock_attestation_flow_,
+ GetCertificate(
+ chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
+ _, _, _, _))
+ .Times(1);
+ // TpmAttestationRegisterKey must be called exactly once.
+ EXPECT_CALL(mock_async_method_caller_,
+ TpmAttestationRegisterKey(chromeos::attestation::KEY_DEVICE,
+ _ /* Unused by the API. */,
+ "attest-ent-machine", _))
+ .Times(1);
+ // SignEnterpriseChallenge must be called exactly once.
+ EXPECT_CALL(
+ mock_async_method_caller_,
+ TpmAttestationSignEnterpriseChallenge(
+ chromeos::attestation::KEY_DEVICE, cryptohome::Identification(),
+ "attest-ent-machine", "google.com", "device_id", _, "challenge", _))
+ .Times(1);
+
+ std::unique_ptr<base::Value> value(RunFunctionAndReturnSingleResult(
+ func_.get(), CreateArgsRegister(), browser()));
+
+ const base::Value* response;
ASSERT_TRUE(value->GetAsBinary(&response));
EXPECT_EQ("response",
std::string(response->GetBuffer(), response->GetSize()));
@@ -407,7 +478,7 @@ class EPKChallengeUserKeyTest : public EPKChallengeKeyTestBase {
std::unique_ptr<base::ListValue> CreateArgsInternal(bool register_key) {
std::unique_ptr<base::ListValue> args(new base::ListValue);
- args->Append(base::BinaryValue::CreateWithCopiedBuffer("challenge", 9));
+ args->Append(base::Value::CreateWithCopiedBuffer("challenge", 9));
args->AppendBoolean(register_key);
return args;
}
@@ -492,7 +563,7 @@ TEST_F(EPKChallengeUserKeyTest, KeyNotRegistered) {
}
TEST_F(EPKChallengeUserKeyTest, PersonalDevice) {
- stub_install_attributes_.SetConsumer();
+ stub_install_attributes_.SetConsumerOwned();
// Currently personal devices are not supported.
EXPECT_EQ(GetCertificateError(kUserRejected),
@@ -524,7 +595,7 @@ TEST_F(EPKChallengeUserKeyTest, Success) {
std::unique_ptr<base::Value> value(
RunFunctionAndReturnSingleResult(func_.get(), CreateArgs(), browser()));
- const base::BinaryValue* response;
+ const base::Value* response;
ASSERT_TRUE(value->GetAsBinary(&response));
EXPECT_EQ("response",
std::string(response->GetBuffer(), response->GetSize()));
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 436584a9f4e..37f1701a108 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
@@ -326,7 +326,7 @@ class EnterprisePlatformKeysTest
ExtensionApiTest::TearDownOnMainThread();
if (chromeos::LoginDisplayHost::default_host())
- chromeos::LoginDisplayHost::default_host()->Finalize();
+ chromeos::LoginDisplayHost::default_host()->Finalize(base::OnceClosure());
base::RunLoop().RunUntilIdle();
if (GetParam().system_token_ == SYSTEM_TOKEN_EXISTS) {
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 38ddb5c0ef7..4b69f12dfd8 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
@@ -142,7 +142,7 @@ bool EPKPChallengeKeyBase::IsEnterpriseDevice() const {
bool EPKPChallengeKeyBase::IsExtensionWhitelisted() const {
const base::ListValue* list =
profile_->GetPrefs()->GetList(prefs::kAttestationExtensionWhitelist);
- base::StringValue value(extension_id_);
+ base::Value value(extension_id_);
return list->Find(value) != list->end();
}
@@ -287,6 +287,8 @@ void EPKPChallengeKeyBase::GetCertificateCallback(
const char EPKPChallengeMachineKey::kGetCertificateFailedError[] =
"Failed to get Enterprise machine certificate. Error code = %d";
+const char EPKPChallengeMachineKey::kKeyRegistrationFailedError[] =
+ "Machine key registration failed.";
const char EPKPChallengeMachineKey::kNonEnterpriseDeviceError[] =
"The device is not enterprise enrolled.";
@@ -312,7 +314,8 @@ EPKPChallengeMachineKey::~EPKPChallengeMachineKey() {
void EPKPChallengeMachineKey::Run(
scoped_refptr<UIThreadExtensionFunction> caller,
const ChallengeKeyCallback& callback,
- const std::string& challenge) {
+ const std::string& challenge,
+ bool register_key) {
callback_ = callback;
profile_ = ChromeExtensionFunctionDetails(caller.get()).GetProfile();
extension_id_ = caller->extension_id();
@@ -337,23 +340,26 @@ void EPKPChallengeMachineKey::Run(
// Check if RA is enabled in the device policy.
GetDeviceAttestationEnabled(
base::Bind(&EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback,
- base::Unretained(this), challenge));
+ base::Unretained(this), challenge, register_key));
}
void EPKPChallengeMachineKey::DecodeAndRun(
scoped_refptr<UIThreadExtensionFunction> caller,
const ChallengeKeyCallback& callback,
- const std::string& encoded_challenge) {
+ const std::string& encoded_challenge,
+ bool register_key) {
std::string challenge;
if (!base::Base64Decode(encoded_challenge, &challenge)) {
callback.Run(false, kChallengeBadBase64Error);
return;
}
- Run(caller, callback, challenge);
+ Run(caller, callback, challenge, register_key);
}
void EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback(
- const std::string& challenge, bool enabled) {
+ const std::string& challenge,
+ bool register_key,
+ bool enabled) {
if (!enabled) {
callback_.Run(false, kDevicePolicyDisabledError);
return;
@@ -365,11 +371,12 @@ void EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback(
chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
false, // user consent is not required.
base::Bind(&EPKPChallengeMachineKey::PrepareKeyCallback,
- base::Unretained(this), challenge));
+ base::Unretained(this), challenge, register_key));
}
-void EPKPChallengeMachineKey::PrepareKeyCallback(
- const std::string& challenge, PrepareKeyResult result) {
+void EPKPChallengeMachineKey::PrepareKeyCallback(const std::string& challenge,
+ bool register_key,
+ PrepareKeyResult result) {
if (result != PREPARE_KEY_OK) {
callback_.Run(false,
base::StringPrintf(kGetCertificateFailedError, result));
@@ -381,17 +388,41 @@ void EPKPChallengeMachineKey::PrepareKeyCallback(
chromeos::attestation::KEY_DEVICE,
cryptohome::Identification(), // Not used.
kKeyName, GetEnterpriseDomain(), GetDeviceId(),
- chromeos::attestation::CHALLENGE_OPTION_NONE, challenge,
+ register_key ? chromeos::attestation::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY
+ : chromeos::attestation::CHALLENGE_OPTION_NONE,
+ challenge,
base::Bind(&EPKPChallengeMachineKey::SignChallengeCallback,
- base::Unretained(this)));
+ base::Unretained(this), register_key));
}
void EPKPChallengeMachineKey::SignChallengeCallback(
- bool success, const std::string& response) {
+ bool register_key,
+ bool success,
+ const std::string& response) {
if (!success) {
callback_.Run(false, kSignChallengeFailedError);
return;
}
+ if (register_key) {
+ async_caller_->TpmAttestationRegisterKey(
+ chromeos::attestation::KEY_DEVICE,
+ cryptohome::Identification(), // Not used.
+ kKeyName,
+ base::Bind(&EPKPChallengeMachineKey::RegisterKeyCallback,
+ base::Unretained(this), response));
+ } else {
+ RegisterKeyCallback(response, true, cryptohome::MOUNT_ERROR_NONE);
+ }
+}
+
+void EPKPChallengeMachineKey::RegisterKeyCallback(
+ const std::string& response,
+ bool success,
+ cryptohome::MountError return_code) {
+ if (!success || return_code != cryptohome::MOUNT_ERROR_NONE) {
+ callback_.Run(false, kKeyRegistrationFailedError);
+ return;
+ }
callback_.Run(true, response);
}
@@ -579,7 +610,7 @@ EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::Run() {
base::Closure task = base::Bind(
&EPKPChallengeMachineKey::DecodeAndRun, base::Unretained(impl_),
scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
- callback, params->challenge);
+ callback, params->challenge, false);
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, task);
return RespondLater();
}
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
index 2923b3436e6..99e0b9985ce 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
@@ -163,6 +163,7 @@ class EPKPChallengeKeyBase {
class EPKPChallengeMachineKey : public EPKPChallengeKeyBase {
public:
static const char kGetCertificateFailedError[];
+ static const char kKeyRegistrationFailedError[];
static const char kNonEnterpriseDeviceError[];
EPKPChallengeMachineKey();
@@ -177,21 +178,30 @@ class EPKPChallengeMachineKey : public EPKPChallengeKeyBase {
// context.
void Run(scoped_refptr<UIThreadExtensionFunction> caller,
const ChallengeKeyCallback& callback,
- const std::string& encoded_challenge);
+ const std::string& encoded_challenge,
+ bool register_key);
// Like |Run| but expects a Base64 |encoded_challenge|.
void DecodeAndRun(scoped_refptr<UIThreadExtensionFunction> caller,
const ChallengeKeyCallback& callback,
- const std::string& encoded_challenge);
+ const std::string& encoded_challenge,
+ bool register_key);
private:
static const char kKeyName[];
void GetDeviceAttestationEnabledCallback(const std::string& challenge,
+ bool register_key,
bool enabled);
void PrepareKeyCallback(const std::string& challenge,
+ bool register_key,
PrepareKeyResult result);
- void SignChallengeCallback(bool success, const std::string& response);
+ void SignChallengeCallback(bool register_key,
+ bool success,
+ const std::string& response);
+ void RegisterKeyCallback(const std::string& response,
+ bool success,
+ cryptohome::MountError return_code);
};
class EPKPChallengeUserKey : public EPKPChallengeKeyBase {
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
index 6d9e2699010..daefe0cc445 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -170,7 +170,7 @@ class EPKPChallengeKeyTestBase : public BrowserWithTestWindowTest {
ON_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
.WillByDefault(Invoke(GetCertificateCallbackTrue));
- stub_install_attributes_.SetEnterprise("google.com", "device_id");
+ stub_install_attributes_.SetCloudManaged("google.com", "device_id");
settings_helper_.ReplaceProvider(chromeos::kDeviceAttestationEnabled);
settings_helper_.SetBoolean(chromeos::kDeviceAttestationEnabled, true);
@@ -258,7 +258,7 @@ TEST_F(EPKPChallengeMachineKeyTest, ChallengeBadBase64) {
}
TEST_F(EPKPChallengeMachineKeyTest, NonEnterpriseDevice) {
- stub_install_attributes_.SetConsumer();
+ stub_install_attributes_.SetConsumerOwned();
EXPECT_EQ(EPKPChallengeMachineKey::kNonEnterpriseDeviceError,
utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
@@ -473,7 +473,7 @@ TEST_F(EPKPChallengeUserKeyTest, KeyNotRegistered) {
}
TEST_F(EPKPChallengeUserKeyTest, PersonalDevice) {
- stub_install_attributes_.SetConsumer();
+ stub_install_attributes_.SetConsumerOwned();
// Currently personal devices are not supported.
EXPECT_EQ(GetCertificateError(kUserRejected),
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 5dc36adfd40..8b6976f9732 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
@@ -18,14 +18,12 @@
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_action_runner.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/location_bar/location_bar.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/common/extensions/api/extension_action/action_info.h"
@@ -34,6 +32,7 @@
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_util.h"
#include "extensions/browser/notification_types.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/feature_switch.h"
@@ -91,8 +90,8 @@ ExtensionActionAPI::Observer::~Observer() {
// ExtensionActionAPI
//
-static base::LazyInstance<BrowserContextKeyedAPIFactory<ExtensionActionAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<ExtensionActionAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
ExtensionActionAPI::ExtensionActionAPI(content::BrowserContext* context)
: browser_context_(context),
@@ -164,8 +163,9 @@ void ExtensionActionAPI::SetBrowserActionVisibility(
if (GetBrowserActionVisibility(extension_id) == visible)
return;
- GetExtensionPrefs()->UpdateExtensionPref(extension_id, kBrowserActionVisible,
- new base::Value(visible));
+ GetExtensionPrefs()->UpdateExtensionPref(
+ extension_id, kBrowserActionVisible,
+ base::MakeUnique<base::Value>(visible));
for (auto& observer : observers_)
observer.OnExtensionActionVisibilityChanged(extension_id, visible);
}
@@ -180,14 +180,6 @@ bool ExtensionActionAPI::ShowExtensionActionPopup(
if (!extension_action)
return false;
- if (extension_action->action_type() == ActionInfo::TYPE_PAGE &&
- !FeatureSwitch::extension_action_redesign()->IsEnabled()) {
- // We show page actions in the location bar unless the new toolbar is
- // enabled.
- return browser->window()->GetLocationBar()->ShowPageActionPopup(
- extension, grant_active_tab_permissions);
- }
-
// Don't support showing action popups in a popup window.
if (!browser->SupportsWindowFeature(Browser::FEATURE_TOOLBAR))
return false;
@@ -293,11 +285,6 @@ void ExtensionActionAPI::NotifyPageActionsChanged(
Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
if (!browser)
return;
- LocationBar* location_bar =
- browser->window() ? browser->window()->GetLocationBar() : NULL;
- if (!location_bar)
- return;
- location_bar->UpdatePageActions();
for (auto& observer : observers_)
observer.OnPageActionsUpdated(web_contents);
@@ -527,20 +514,20 @@ ExtensionActionSetBadgeBackgroundColorFunction::RunExtensionAction() {
ExtensionFunction::ResponseAction
ExtensionActionGetTitleFunction::RunExtensionAction() {
- return RespondNow(OneArgument(base::MakeUnique<base::StringValue>(
- extension_action_->GetTitle(tab_id_))));
+ return RespondNow(OneArgument(
+ base::MakeUnique<base::Value>(extension_action_->GetTitle(tab_id_))));
}
ExtensionFunction::ResponseAction
ExtensionActionGetPopupFunction::RunExtensionAction() {
- return RespondNow(OneArgument(base::MakeUnique<base::StringValue>(
+ return RespondNow(OneArgument(base::MakeUnique<base::Value>(
extension_action_->GetPopupUrl(tab_id_).spec())));
}
ExtensionFunction::ResponseAction
ExtensionActionGetBadgeTextFunction::RunExtensionAction() {
- return RespondNow(OneArgument(base::MakeUnique<base::StringValue>(
- extension_action_->GetBadgeText(tab_id_))));
+ return RespondNow(OneArgument(
+ base::MakeUnique<base::Value>(extension_action_->GetBadgeText(tab_id_))));
}
ExtensionFunction::ResponseAction
diff --git a/chromium/chrome/browser/extensions/api/feedback_private/OWNERS b/chromium/chrome/browser/extensions/api/feedback_private/OWNERS
index 13e3b599939..806a1cef4fb 100644
--- a/chromium/chrome/browser/extensions/api/feedback_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/feedback_private/OWNERS
@@ -1,2 +1,4 @@
afakhry@chromium.org
-steel@chromium.org
+rkc@chromium.org
+
+# COMPONENT: Platform>Apps>Feedback
diff --git a/chromium/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc b/chromium/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
index bf70275158a..d96b83023e1 100644
--- a/chromium/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/statistics_recorder.h"
+#include "base/metrics/user_metrics.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -27,7 +28,6 @@
#include "components/feedback/tracing_manager.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/user_metrics.h"
#include "extensions/browser/event_router.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
@@ -77,8 +77,8 @@ using feedback_private::FeedbackFlow;
using SystemInformationList =
std::vector<api::feedback_private::SystemInformation>;
-static base::LazyInstance<BrowserContextKeyedAPIFactory<FeedbackPrivateAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>*
@@ -223,7 +223,7 @@ ExtensionFunction::ResponseAction FeedbackPrivateGetStringsFunction::Run() {
ExtensionFunction::ResponseAction FeedbackPrivateGetUserEmailFunction::Run() {
SigninManagerBase* signin_manager = SigninManagerFactory::GetForProfile(
Profile::FromBrowserContext(browser_context()));
- return RespondNow(OneArgument(base::MakeUnique<base::StringValue>(
+ return RespondNow(OneArgument(base::MakeUnique<base::Value>(
signin_manager ? signin_manager->GetAuthenticatedAccountInfo().email
: std::string())));
}
@@ -347,16 +347,13 @@ FeedbackPrivateLogSrtPromptResultFunction::Run() {
switch (result) {
case feedback_private::SRT_PROMPT_RESULT_ACCEPTED:
- content::RecordAction(
- base::UserMetricsAction("Feedback.SrtPromptAccepted"));
+ base::RecordAction(base::UserMetricsAction("Feedback.SrtPromptAccepted"));
break;
case feedback_private::SRT_PROMPT_RESULT_DECLINED:
- content::RecordAction(
- base::UserMetricsAction("Feedback.SrtPromptDeclined"));
+ base::RecordAction(base::UserMetricsAction("Feedback.SrtPromptDeclined"));
break;
case feedback_private::SRT_PROMPT_RESULT_CLOSED:
- content::RecordAction(
- base::UserMetricsAction("Feedback.SrtPromptClosed"));
+ base::RecordAction(base::UserMetricsAction("Feedback.SrtPromptClosed"));
break;
default:
return RespondNow(Error("Invalid arugment."));
diff --git a/chromium/chrome/browser/extensions/api/file_system/file_system_api.cc b/chromium/chrome/browser/extensions/api/file_system/file_system_api.cc
index 07de8dd8ab4..cd8b6f8cdac 100644
--- a/chromium/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chromium/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -272,6 +272,24 @@ void FillVolumeList(Profile* profile,
result->push_back(std::move(result_volume));
}
}
+
+// Converts the clicked button to a consent result and passes it via the
+// |callback|.
+void DialogResultToConsent(
+ const file_system_api::ConsentProvider::ConsentCallback& callback,
+ ui::DialogButton button) {
+ switch (button) {
+ case ui::DIALOG_BUTTON_NONE:
+ callback.Run(file_system_api::ConsentProvider::CONSENT_IMPOSSIBLE);
+ break;
+ case ui::DIALOG_BUTTON_OK:
+ callback.Run(file_system_api::ConsentProvider::CONSENT_GRANTED);
+ break;
+ case ui::DIALOG_BUTTON_CANCEL:
+ callback.Run(file_system_api::ConsentProvider::CONSENT_REJECTED);
+ break;
+ }
+}
#endif
} // namespace
@@ -293,8 +311,7 @@ base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs,
void SetLastChooseEntryDirectory(ExtensionPrefs* prefs,
const std::string& extension_id,
const base::FilePath& path) {
- prefs->UpdateExtensionPref(extension_id,
- kLastChooseEntryDirectory,
+ prefs->UpdateExtensionPref(extension_id, kLastChooseEntryDirectory,
base::CreateFilePathValue(path));
}
@@ -362,8 +379,7 @@ void ConsentProvider::RequestConsent(
if (KioskModeInfo::IsKioskOnly(&extension) &&
user_manager::UserManager::Get()->IsLoggedInAsKioskApp()) {
delegate_->ShowDialog(extension, volume, writable,
- base::Bind(&ConsentProvider::DialogResultToConsent,
- base::Unretained(this), callback));
+ base::Bind(&DialogResultToConsent, callback));
return;
}
@@ -381,21 +397,6 @@ bool ConsentProvider::IsGrantable(const Extension& extension) {
return is_whitelisted_component || is_running_in_kiosk_session;
}
-void ConsentProvider::DialogResultToConsent(const ConsentCallback& callback,
- ui::DialogButton button) {
- switch (button) {
- case ui::DIALOG_BUTTON_NONE:
- callback.Run(CONSENT_IMPOSSIBLE);
- break;
- case ui::DIALOG_BUTTON_OK:
- callback.Run(CONSENT_GRANTED);
- break;
- case ui::DIALOG_BUTTON_CANCEL:
- callback.Run(CONSENT_REJECTED);
- break;
- }
-}
-
ConsentProviderDelegate::ConsentProviderDelegate(Profile* profile,
content::RenderFrameHost* host)
: profile_(profile), host_(host) {
@@ -490,7 +491,7 @@ ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() {
file_path = path_util::PrettifyPath(file_path);
return RespondNow(
- OneArgument(base::MakeUnique<base::StringValue>(file_path.value())));
+ OneArgument(base::MakeUnique<base::Value>(file_path.value())));
}
FileSystemEntryFunction::FileSystemEntryFunction()
@@ -1327,6 +1328,12 @@ void FileSystemRequestFileSystemFunction::OnConsentReceived(
using file_manager::VolumeManager;
using file_manager::Volume;
+ // Render frame host can be gone before this callback method is executed.
+ if (!render_frame_host()) {
+ Respond(Error(""));
+ return;
+ }
+
switch (result) {
case ConsentProvider::CONSENT_REJECTED:
Respond(Error(kSecurityError));
diff --git a/chromium/chrome/browser/extensions/api/file_system/file_system_api.h b/chromium/chrome/browser/extensions/api/file_system/file_system_api.h
index 740c44706c1..12b53c70479 100644
--- a/chromium/chrome/browser/extensions/api/file_system/file_system_api.h
+++ b/chromium/chrome/browser/extensions/api/file_system/file_system_api.h
@@ -100,11 +100,6 @@ class ConsentProvider {
private:
DelegateInterface* const delegate_;
- // Converts the clicked button to a consent result and passes it via the
- // |callback|.
- void DialogResultToConsent(const ConsentCallback& callback,
- ui::DialogButton button);
-
DISALLOW_COPY_AND_ASSIGN(ConsentProvider);
};
diff --git a/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc b/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc
index 1d3420a8276..31f9f9d8003 100644
--- a/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc
+++ b/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc
@@ -15,6 +15,7 @@
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -186,7 +187,7 @@ void FontSettingsEventRouter::OnFontPrefChanged(
base::ListValue args;
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->Set(key, pref->GetValue()->DeepCopy());
+ dict->Set(key, pref->GetValue()->CreateDeepCopy());
args.Append(std::move(dict));
extensions::preference_helpers::DispatchEventToExtensions(
@@ -201,8 +202,8 @@ FontSettingsAPI::FontSettingsAPI(content::BrowserContext* context)
FontSettingsAPI::~FontSettingsAPI() {
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<FontSettingsAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<FontSettingsAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<FontSettingsAPI>*
@@ -278,7 +279,7 @@ ExtensionFunction::ResponseAction FontSettingsSetFontFunction::Run() {
PreferenceAPI::Get(profile)->SetExtensionControlledPref(
extension_id(), pref_path, kExtensionPrefsScopeRegular,
- new base::StringValue(params->details.font_id));
+ new base::Value(params->details.font_id));
return RespondNow(NoArguments());
}
@@ -300,7 +301,7 @@ bool FontSettingsGetFontListFunction::CopyFontsToResult(
for (base::ListValue::iterator it = fonts->begin();
it != fonts->end(); ++it) {
base::ListValue* font_list_value;
- if (!(*it)->GetAsList(&font_list_value)) {
+ if (!it->GetAsList(&font_list_value)) {
NOTREACHED();
return false;
}
@@ -319,8 +320,9 @@ bool FontSettingsGetFontListFunction::CopyFontsToResult(
std::unique_ptr<base::DictionaryValue> font_name(
new base::DictionaryValue());
- font_name->Set(kFontIdKey, new base::StringValue(name));
- font_name->Set(kDisplayNameKey, new base::StringValue(localized_name));
+ font_name->Set(kFontIdKey, base::MakeUnique<base::Value>(name));
+ font_name->Set(kDisplayNameKey,
+ base::MakeUnique<base::Value>(localized_name));
result->Append(std::move(font_name));
}
@@ -353,7 +355,7 @@ ExtensionFunction::ResponseAction GetFontPrefExtensionFunction::Run() {
profile, extension_id(), GetPrefName(), kIncognito);
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->Set(GetKey(), pref->GetValue()->DeepCopy());
+ result->Set(GetKey(), pref->GetValue()->CreateDeepCopy());
result->SetString(kLevelOfControlKey, level_of_control);
return RespondNow(OneArgument(std::move(result)));
}
diff --git a/chromium/chrome/browser/extensions/api/gcm/OWNERS b/chromium/chrome/browser/extensions/api/gcm/OWNERS
index 46bb26677a4..b3ca3adfed5 100644
--- a/chromium/chrome/browser/extensions/api/gcm/OWNERS
+++ b/chromium/chrome/browser/extensions/api/gcm/OWNERS
@@ -1,2 +1,4 @@
fgorski@chromium.org
jianli@chromium.org
+
+# COMPONENT: Services>CloudMessaging
diff --git a/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc b/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc
index dab662178a3..7f878c3b4fd 100644
--- a/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc
+++ b/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc
@@ -128,7 +128,7 @@ bool GcmRegisterFunction::DoWork() {
void GcmRegisterFunction::CompleteFunctionWithResult(
const std::string& registration_id,
gcm::GCMClient::Result result) {
- SetResult(base::MakeUnique<base::StringValue>(registration_id));
+ SetResult(base::MakeUnique<base::Value>(registration_id));
SetError(GcmResultToError(result));
SendResponse(gcm::GCMClient::SUCCESS == result);
}
@@ -182,7 +182,7 @@ bool GcmSendFunction::DoWork() {
void GcmSendFunction::CompleteFunctionWithResult(
const std::string& message_id,
gcm::GCMClient::Result result) {
- SetResult(base::MakeUnique<base::StringValue>(message_id));
+ SetResult(base::MakeUnique<base::Value>(message_id));
SetError(GcmResultToError(result));
SendResponse(gcm::GCMClient::SUCCESS == result);
}
diff --git a/chromium/chrome/browser/extensions/api/history/history_api.cc b/chromium/chrome/browser/extensions/api/history/history_api.cc
index e940c709fb3..a10c6f69f64 100644
--- a/chromium/chrome/browser/extensions/api/history/history_api.cc
+++ b/chromium/chrome/browser/extensions/api/history/history_api.cc
@@ -196,8 +196,9 @@ void HistoryAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<HistoryAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<HistoryAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<HistoryAPI>* HistoryAPI::GetFactoryInstance() {
diff --git a/chromium/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc b/chromium/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
index 61aac818a5b..501102604e7 100644
--- a/chromium/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
@@ -30,7 +30,7 @@
#include "ui/base/webui/web_ui_util.h"
#if defined(OS_CHROMEOS)
-#include "ash/common/system/chromeos/devicetype_utils.h"
+#include "ash/system/devicetype_utils.h"
#endif
namespace extensions {
@@ -45,8 +45,8 @@ namespace OnEnabledChanged =
api::hotword_private::OnEnabledChanged;
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<HotwordPrivateEventService> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<HotwordPrivateEventService>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
HotwordPrivateEventService::HotwordPrivateEventService(
content::BrowserContext* context)
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
index b9387b1aa13..99b078dc13a 100644
--- a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -55,9 +56,9 @@ GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate,
"&device_id=%s&"
"device_type=chrome";
- std::vector<std::string> scopes(token_key->scopes.begin(),
- token_key->scopes.end());
- std::vector<std::string> client_id_parts = base::SplitString(
+ std::vector<base::StringPiece> scopes(token_key->scopes.begin(),
+ token_key->scopes.end());
+ std::vector<base::StringPiece> client_id_parts = base::SplitStringPiece(
oauth2_client_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
std::reverse(client_id_parts.begin(), client_id_parts.end());
redirect_scheme_ = base::JoinString(client_id_parts, ".");
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_api.cc b/chromium/chrome/browser/extensions/api/identity/identity_api.cc
index 90e95c7b1f8..eb0087d6b68 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_api.cc
@@ -184,8 +184,9 @@ void IdentityAPI::Shutdown() {
account_tracker_.Shutdown();
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<IdentityAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<IdentityAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
index cc64fd81eb9..db214edbb9e 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -422,7 +422,7 @@ class IdentityGetAccountsFunctionTest : public ExtensionBrowserTest {
it != results->end();
++it) {
std::unique_ptr<api::identity::AccountInfo> info =
- api::identity::AccountInfo::FromValue(**it);
+ api::identity::AccountInfo::FromValue(*it);
if (info.get())
result_ids.insert(info->id);
else
@@ -454,11 +454,11 @@ class IdentityGetAccountsFunctionTest : public ExtensionBrowserTest {
} else {
for (const auto& result : *results) {
std::unique_ptr<api::identity::AccountInfo> info =
- api::identity::AccountInfo::FromValue(*result);
+ api::identity::AccountInfo::FromValue(result);
if (info.get())
msg << info->id << " ";
else
- msg << *result << "<-" << result->GetType() << " ";
+ msg << result << "<-" << result.GetType() << " ";
}
}
@@ -1602,7 +1602,7 @@ class GetAuthTokenFunctionPublicSessionTest : public GetAuthTokenFunctionTest {
// enterprise-managed.
std::unique_ptr<chromeos::StubInstallAttributes> attributes
= base::MakeUnique<chromeos::StubInstallAttributes>();
- attributes->SetEnterprise("example.com", "fake-id");
+ attributes->SetCloudManaged("example.com", "fake-id");
policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
attributes.release());
}
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 6f52b003546..3ebce8aeba8 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
@@ -186,7 +186,7 @@ void IdentityGetAuthTokenFunction::CompleteAsyncRun(bool success) {
void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
const std::string& access_token) {
- SetResult(base::MakeUnique<base::StringValue>(access_token));
+ SetResult(base::MakeUnique<base::Value>(access_token));
CompleteAsyncRun(true);
}
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc b/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc
index 0940586623b..84a1253fb71 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc
@@ -6,11 +6,12 @@
#include "chrome/browser/extensions/api/identity/identity_constants.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/common/extensions/api/identity.h"
-#include "components/signin/core/browser/signin_manager.h"
+#include "content/public/common/service_manager_connection.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h"
+#include "services/identity/public/interfaces/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace extensions {
@@ -25,16 +26,35 @@ ExtensionFunction::ResponseAction IdentityGetProfileUserInfoFunction::Run() {
return RespondNow(Error(identity_constants::kOffTheRecord));
}
- AccountInfo account = SigninManagerFactory::GetForProfile(
- GetProfile())->GetAuthenticatedAccountInfo();
- api::identity::ProfileUserInfo profile_user_info;
- if (extension()->permissions_data()->HasAPIPermission(
+ if (!extension()->permissions_data()->HasAPIPermission(
APIPermission::kIdentityEmail)) {
- profile_user_info.email = account.email;
- profile_user_info.id = account.gaia;
+ api::identity::ProfileUserInfo profile_user_info;
+ return RespondNow(OneArgument(profile_user_info.ToValue()));
+ }
+
+ content::BrowserContext::GetConnectorFor(GetProfile())
+ ->BindInterface(identity::mojom::kServiceName,
+ mojo::MakeRequest(&identity_manager_));
+
+ identity_manager_->GetPrimaryAccountId(base::Bind(
+ &IdentityGetProfileUserInfoFunction::OnReceivedPrimaryAccountId, this));
+
+ return RespondLater();
+}
+
+void IdentityGetProfileUserInfoFunction::OnReceivedPrimaryAccountId(
+ const base::Optional<AccountId>& account_id) {
+ DCHECK(extension()->permissions_data()->HasAPIPermission(
+ APIPermission::kIdentityEmail));
+
+ api::identity::ProfileUserInfo profile_user_info;
+
+ if (account_id) {
+ profile_user_info.email = account_id->GetUserEmail();
+ profile_user_info.id = account_id->GetGaiaId();
}
- return RespondNow(OneArgument(profile_user_info.ToValue()));
+ Respond(OneArgument(profile_user_info.ToValue()));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h b/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h
index 2d3b434705d..c2a1ce9137a 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h
@@ -6,7 +6,9 @@
#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_PROFILE_USER_INFO_FUNCTION_H_
#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "components/signin/core/account_id/account_id.h"
#include "extensions/browser/extension_function_histogram_value.h"
+#include "services/identity/public/interfaces/identity_manager.mojom.h"
namespace extensions {
@@ -20,9 +22,12 @@ class IdentityGetProfileUserInfoFunction
private:
~IdentityGetProfileUserInfoFunction() override;
+ void OnReceivedPrimaryAccountId(const base::Optional<AccountId>& account_id);
// UIThreadExtensionFunction implementation.
ExtensionFunction::ResponseAction Run() override;
+
+ identity::mojom::IdentityManagerPtr identity_manager_;
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc b/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
index 2f000686f00..882c858b85a 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
@@ -91,7 +91,7 @@ void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure(
void IdentityLaunchWebAuthFlowFunction::OnAuthFlowURLChange(
const GURL& redirect_url) {
if (redirect_url.GetWithEmptyPath() == final_url_prefix_) {
- SetResult(base::MakeUnique<base::StringValue>(redirect_url.spec()));
+ SetResult(base::MakeUnique<base::Value>(redirect_url.spec()));
SendResponse(true);
if (auth_flow_)
auth_flow_.release()->DetachDelegateAndDelete();
diff --git a/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc b/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc
index 1864fd8e3c5..da7ba52e646 100644
--- a/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc
+++ b/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc
@@ -10,12 +10,12 @@
#include "base/values.h"
-using base::BinaryValue;
+using base::Value;
namespace {
std::unique_ptr<base::ListValue> CopyBinaryValueToIntegerList(
- const BinaryValue* input) {
+ const Value* input) {
std::unique_ptr<base::ListValue> output(new base::ListValue());
const char* input_buffer = input->GetBuffer();
for (size_t i = 0; i < input->GetSize(); i++) {
@@ -27,19 +27,19 @@ std::unique_ptr<base::ListValue> CopyBinaryValueToIntegerList(
} // namespace
ExtensionFunction::ResponseAction IdltestSendArrayBufferFunction::Run() {
- BinaryValue* input = NULL;
+ Value* input = NULL;
EXTENSION_FUNCTION_VALIDATE(args_ != NULL && args_->GetBinary(0, &input));
return RespondNow(OneArgument(CopyBinaryValueToIntegerList(input)));
}
ExtensionFunction::ResponseAction IdltestSendArrayBufferViewFunction::Run() {
- BinaryValue* input = NULL;
+ Value* input = NULL;
EXTENSION_FUNCTION_VALIDATE(args_ != NULL && args_->GetBinary(0, &input));
return RespondNow(OneArgument(CopyBinaryValueToIntegerList(input)));
}
ExtensionFunction::ResponseAction IdltestGetArrayBufferFunction::Run() {
std::string hello = "hello world";
- return RespondNow(OneArgument(
- BinaryValue::CreateWithCopiedBuffer(hello.c_str(), hello.size())));
+ return RespondNow(
+ OneArgument(Value::CreateWithCopiedBuffer(hello.c_str(), hello.size())));
}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
index 30ab7cd16c5..8e2a1e1771f 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
@@ -25,7 +25,7 @@ class ImageWriterUtilityClient::RemovableStorageWriterClientImpl
ImageWriterUtilityClient* owner,
extensions::mojom::RemovableStorageWriterClientPtr* interface)
: binding_(this, interface), image_writer_utility_client_(owner) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
binding_.set_connection_error_handler(
base::Bind(&ImageWriterUtilityClient::UtilityProcessError,
@@ -54,9 +54,7 @@ class ImageWriterUtilityClient::RemovableStorageWriterClientImpl
DISALLOW_COPY_AND_ASSIGN(RemovableStorageWriterClientImpl);
};
-ImageWriterUtilityClient::ImageWriterUtilityClient()
- : task_runner_(base::ThreadTaskRunnerHandle::Get()) {
-}
+ImageWriterUtilityClient::ImageWriterUtilityClient() = default;
ImageWriterUtilityClient::~ImageWriterUtilityClient() = default;
@@ -65,14 +63,14 @@ void ImageWriterUtilityClient::Write(const ProgressCallback& progress_callback,
const ErrorCallback& error_callback,
const base::FilePath& source,
const base::FilePath& target) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
DCHECK(!removable_storage_writer_client_);
progress_callback_ = progress_callback;
success_callback_ = success_callback;
error_callback_ = error_callback;
- StartUtilityProcess();
+ StartUtilityProcessIfNeeded();
extensions::mojom::RemovableStorageWriterClientPtr client;
removable_storage_writer_client_ =
@@ -87,14 +85,14 @@ void ImageWriterUtilityClient::Verify(const ProgressCallback& progress_callback,
const ErrorCallback& error_callback,
const base::FilePath& source,
const base::FilePath& target) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
DCHECK(!removable_storage_writer_client_);
progress_callback_ = progress_callback;
success_callback_ = success_callback;
error_callback_ = error_callback;
- StartUtilityProcess();
+ StartUtilityProcessIfNeeded();
extensions::mojom::RemovableStorageWriterClientPtr client;
removable_storage_writer_client_ =
@@ -105,31 +103,30 @@ void ImageWriterUtilityClient::Verify(const ProgressCallback& progress_callback,
}
void ImageWriterUtilityClient::Cancel(const CancelCallback& cancel_callback) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
+ DCHECK(cancel_callback);
ResetRequest();
- task_runner_->PostTask(FROM_HERE, cancel_callback);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, cancel_callback);
}
void ImageWriterUtilityClient::Shutdown() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
ResetRequest();
utility_process_mojo_client_.reset();
}
-void ImageWriterUtilityClient::StartUtilityProcess() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+void ImageWriterUtilityClient::StartUtilityProcessIfNeeded() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
if (utility_process_mojo_client_)
return;
- const base::string16 utility_process_name =
- l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_IMAGE_WRITER_NAME);
-
- utility_process_mojo_client_.reset(
- new content::UtilityProcessMojoClient<
- extensions::mojom::RemovableStorageWriter>(utility_process_name));
+ utility_process_mojo_client_ =
+ base::MakeUnique<content::UtilityProcessMojoClient<
+ extensions::mojom::RemovableStorageWriter>>(
+ l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_IMAGE_WRITER_NAME));
utility_process_mojo_client_->set_error_callback(
base::Bind(&ImageWriterUtilityClient::UtilityProcessError, this));
@@ -142,7 +139,7 @@ void ImageWriterUtilityClient::StartUtilityProcess() {
}
void ImageWriterUtilityClient::UtilityProcessError() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
OperationFailed("Utility process crashed or failed.");
utility_process_mojo_client_.reset();
@@ -150,21 +147,21 @@ void ImageWriterUtilityClient::UtilityProcessError() {
void ImageWriterUtilityClient::OperationProgress(int64_t progress) {
if (progress_callback_)
- task_runner_->PostTask(FROM_HERE, base::Bind(progress_callback_, progress));
+ progress_callback_.Run(progress);
}
void ImageWriterUtilityClient::OperationSucceeded() {
SuccessCallback success_callback = success_callback_;
ResetRequest();
if (success_callback)
- task_runner_->PostTask(FROM_HERE, success_callback);
+ success_callback.Run();
}
void ImageWriterUtilityClient::OperationFailed(const std::string& error) {
ErrorCallback error_callback = error_callback_;
ResetRequest();
if (error_callback)
- task_runner_->PostTask(FROM_HERE, base::Bind(error_callback, error));
+ error_callback.Run(error);
}
void ImageWriterUtilityClient::ResetRequest() {
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.h b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.h
index 0aa0a6dfd9c..0df6304205c 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.h
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.h
@@ -15,7 +15,8 @@
#include "chrome/common/extensions/removable_storage_writer.mojom.h"
#include "content/public/browser/utility_process_mojo_client.h"
-// Writes a disk image to a device inside the utility process.
+// Writes a disk image to a device inside the utility process. This
+// class lives on the FILE thread.
class ImageWriterUtilityClient
: public base::RefCountedThreadSafe<ImageWriterUtilityClient> {
public:
@@ -52,6 +53,7 @@ class ImageWriterUtilityClient
// Cancels any pending write or verify operation.
// |cancel_callback|: Called when the cancel has actually occurred.
+ // TODO(crbug.com/703514): Consider removing this API.
virtual void Cancel(const CancelCallback& cancel_callback);
// Shuts down the utility process that may have been created.
@@ -65,9 +67,7 @@ class ImageWriterUtilityClient
private:
class RemovableStorageWriterClientImpl;
- // Ensures the utility process has been created.
- void StartUtilityProcess();
-
+ void StartUtilityProcessIfNeeded();
void UtilityProcessError();
void OperationProgress(int64_t progress);
@@ -80,8 +80,6 @@ class ImageWriterUtilityClient
SuccessCallback success_callback_;
ErrorCallback error_callback_;
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
std::unique_ptr<content::UtilityProcessMojoClient<
extensions::mojom::RemovableStorageWriter>>
utility_process_mojo_client_;
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 f3307b455b7..dd5006a6cde 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
@@ -11,6 +11,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task_scheduler/post_task.h"
#include "chrome/common/extensions/removable_storage_writer.mojom.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/browser_thread.h"
@@ -29,8 +30,8 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &image_));
base::RunLoop run_loop;
- content::BrowserThread::PostBlockingPoolTaskAndReply(
- FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, base::TaskTraits().MayBlock(),
base::Bind(&ImageWriterUtilityClientTest::FillFile, image_, pattern),
run_loop.QuitClosure());
@@ -41,8 +42,8 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
device_ = image_.ReplaceExtension(FILE_PATH_LITERAL("out"));
base::RunLoop run_loop;
- content::BrowserThread::PostBlockingPoolTaskAndReply(
- FROM_HERE,
+ base::PostTaskWithTraitsAndReply(
+ FROM_HERE, base::TaskTraits().MayBlock(),
base::Bind(&ImageWriterUtilityClientTest::FillFile, device_, pattern),
run_loop.QuitClosure());
@@ -59,7 +60,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
cancel_ = (option == CANCEL);
content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ content::BrowserThread::FILE, FROM_HERE,
base::Bind(&ImageWriterUtilityClientTest::StartWriteTest,
base::Unretained(this)));
run_loop.Run();
@@ -75,7 +76,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
cancel_ = (option == CANCEL);
content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ content::BrowserThread::FILE, FROM_HERE,
base::Bind(&ImageWriterUtilityClientTest::StartVerifyTest,
base::Unretained(this)));
run_loop.Run();
@@ -89,7 +90,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
private:
void StartWriteTest() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
if (!image_writer_utility_client_)
image_writer_utility_client_ = new ImageWriterUtilityClient();
@@ -107,7 +108,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
}
void Progress(int64_t progress) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
progress_ = progress;
if (!cancel_)
@@ -118,7 +119,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
}
void Success() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
EXPECT_EQ(kTestFileSize, progress_);
EXPECT_FALSE(cancel_);
@@ -130,13 +131,13 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
}
content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ content::BrowserThread::FILE, FROM_HERE,
base::Bind(&ImageWriterUtilityClientTest::Shutdown,
base::Unretained(this)));
}
void StartVerifyTest() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
if (!image_writer_utility_client_)
image_writer_utility_client_ = new ImageWriterUtilityClient();
@@ -154,33 +155,33 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
}
void Failure(const std::string& error) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
EXPECT_FALSE(error.empty());
success_ = false;
error_ = error;
content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ content::BrowserThread::FILE, FROM_HERE,
base::Bind(&ImageWriterUtilityClientTest::Shutdown,
base::Unretained(this)));
}
void Verified() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
EXPECT_EQ(kTestFileSize, progress_);
EXPECT_FALSE(cancel_);
success_ = !cancel_;
content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
+ content::BrowserThread::FILE, FROM_HERE,
base::Bind(&ImageWriterUtilityClientTest::Shutdown,
base::Unretained(this)));
}
void Cancelled() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
EXPECT_TRUE(cancel_);
success_ = cancel_;
@@ -191,7 +192,7 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
}
void Shutdown() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
image_writer_utility_client_->Shutdown();
@@ -259,8 +260,7 @@ IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, WriteVerify) {
EXPECT_TRUE(error().empty());
}
-// TODO(crbug.com/690717): test is flaky.
-IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, DISABLED_WriteCancel) {
+IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, WriteCancel) {
FillImageFileWithPattern('a');
FillDeviceFileWithPattern(0);
@@ -306,8 +306,7 @@ IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, Verify) {
EXPECT_TRUE(error().empty());
}
-// TODO(crbug.com/690717): test is flaky.
-IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, DISABLED_VerifyCancel) {
+IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, VerifyCancel) {
FillImageFileWithPattern('s');
FillDeviceFileWithPattern('s');
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 f06a7cc7e37..f4c1aa3402a 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -24,8 +24,8 @@ using content::BrowserThread;
const int kMD5BufferSize = 1024;
#if !defined(OS_CHROMEOS)
-static base::LazyInstance<scoped_refptr<ImageWriterUtilityClient> >
- g_utility_client = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<scoped_refptr<ImageWriterUtilityClient>>::
+ DestructorAtExit g_utility_client = LAZY_INSTANCE_INITIALIZER;
#endif
Operation::Operation(base::WeakPtr<OperationManager> manager,
@@ -263,10 +263,7 @@ void Operation::StartUtilityClient() {
void Operation::StopUtilityClient() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ImageWriterUtilityClient::Shutdown, image_writer_client_));
+ image_writer_client_->Shutdown();
}
void Operation::WriteImageProgress(int64_t total_bytes, int64_t curr_bytes) {
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index aaa05ff03c7..036ce23554c 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -277,8 +277,8 @@ OperationManager* OperationManager::Get(content::BrowserContext* context) {
return BrowserContextKeyedAPIFactory<OperationManager>::Get(context);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<OperationManager> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<OperationManager>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
BrowserContextKeyedAPIFactory<OperationManager>*
OperationManager::GetFactoryInstance() {
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc
index b19330f921d..8b257b5a0fb 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc
@@ -32,17 +32,10 @@ void Operation::Write(const base::Closure& continuation) {
return;
}
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &ImageWriterUtilityClient::Write,
- image_writer_client_,
- base::Bind(&Operation::WriteImageProgress, this, file_size),
- base::Bind(&Operation::CompleteAndContinue, this, continuation),
- base::Bind(&Operation::Error, this),
- image_path_,
- device_path_));
+ image_writer_client_->Write(
+ base::Bind(&Operation::WriteImageProgress, this, file_size),
+ base::Bind(&Operation::CompleteAndContinue, this, continuation),
+ base::Bind(&Operation::Error, this), image_path_, device_path_);
}
void Operation::VerifyWrite(const base::Closure& continuation) {
@@ -61,17 +54,10 @@ void Operation::VerifyWrite(const base::Closure& continuation) {
return;
}
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &ImageWriterUtilityClient::Verify,
- image_writer_client_,
- base::Bind(&Operation::WriteImageProgress, this, file_size),
- base::Bind(&Operation::CompleteAndContinue, this, continuation),
- base::Bind(&Operation::Error, this),
- image_path_,
- device_path_));
+ image_writer_client_->Verify(
+ base::Bind(&Operation::WriteImageProgress, this, file_size),
+ base::Bind(&Operation::CompleteAndContinue, this, continuation),
+ base::Bind(&Operation::Error, this), image_path_, device_path_);
}
} // namespace image_writer
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
index 42b40f7f499..6ad662c42bf 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
@@ -10,7 +10,8 @@
namespace extensions {
// A device list to be returned when testing.
-static base::LazyInstance<scoped_refptr<StorageDeviceList> > g_test_device_list;
+static base::LazyInstance<scoped_refptr<StorageDeviceList>>::DestructorAtExit
+ g_test_device_list = LAZY_INSTANCE_INITIALIZER;
// TODO(haven): Udev code may be duplicated in the Chrome codebase.
// https://code.google.com/p/chromium/issues/detail?id=284898
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 0a78eb6254f..70a01b69bdb 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
@@ -416,13 +416,16 @@ void InputImeAPI::Observe(int type,
content::Source<Profile>(source).ptr());
}
-InputImeAPI::~InputImeAPI() {
+InputImeAPI::~InputImeAPI() = default;
+
+void InputImeAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
registrar_.RemoveAll();
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<InputImeAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<InputImeAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<InputImeAPI>* InputImeAPI::GetFactoryInstance() {
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 a4b849daa20..4dcdce5eff8 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
@@ -179,6 +179,7 @@ class InputImeAPI : public BrowserContextKeyedAPI,
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<InputImeAPI>* GetFactoryInstance();
+ void Shutdown() override;
// ExtensionRegistryObserver implementation.
void OnExtensionLoaded(content::BrowserContext* browser_context,
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
index f7663ed3f89..4180966a5bb 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
@@ -12,6 +12,8 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.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"
@@ -148,7 +150,8 @@ void InputImeAPI::OnExtensionLoaded(content::BrowserContext* browser_context,
// input.ime.activate API has been never called since loaded.
Profile* profile = Profile::FromBrowserContext(browser_context);
ExtensionPrefs::Get(profile)->UpdateExtensionPref(
- extension->id(), kPrefNeverActivatedSinceLoaded, new base::Value(true));
+ extension->id(), kPrefNeverActivatedSinceLoaded,
+ base::MakeUnique<base::Value>(true));
}
void InputImeAPI::OnExtensionUnloaded(content::BrowserContext* browser_context,
@@ -160,7 +163,7 @@ void InputImeAPI::OnExtensionUnloaded(content::BrowserContext* browser_context,
// Records the extension is not the last active IME engine.
ExtensionPrefs::Get(Profile::FromBrowserContext(browser_context))
->UpdateExtensionPref(extension->id(), kPrefLastActiveEngine,
- new base::Value(false));
+ base::MakeUnique<base::Value>(false));
event_router->DeleteInputMethodEngine(extension->id());
}
}
@@ -188,7 +191,7 @@ void InputImeEventRouter::SetActiveEngine(const std::string& extension_id) {
// Records the extension is the last active IME engine.
ExtensionPrefs::Get(GetProfile())
->UpdateExtensionPref(extension_id, kPrefLastActiveEngine,
- new base::Value(true));
+ base::MakeUnique<base::Value>(true));
if (active_engine_) {
if (active_engine_->GetExtensionId() == extension_id) {
active_engine_->Enable(std::string());
@@ -198,7 +201,8 @@ void InputImeEventRouter::SetActiveEngine(const std::string& extension_id) {
// Records the extension is not the last active IME engine.
ExtensionPrefs::Get(GetProfile())
->UpdateExtensionPref(active_engine_->GetExtensionId(),
- kPrefLastActiveEngine, new base::Value(false));
+ kPrefLastActiveEngine,
+ base::MakeUnique<base::Value>(false));
DeleteInputMethodEngine(active_engine_->GetExtensionId());
}
@@ -249,12 +253,14 @@ ExtensionFunction::ResponseAction InputImeActivateFunction::Run() {
// chrome. No need for user gesture checking.
event_router->SetActiveEngine(extension_id());
ExtensionPrefs::Get(profile)->UpdateExtensionPref(
- extension_id(), kPrefNeverActivatedSinceLoaded, new base::Value(false));
+ extension_id(), kPrefNeverActivatedSinceLoaded,
+ base::MakeUnique<base::Value>(false));
return RespondNow(NoArguments());
}
// The API has already been called at least once.
ExtensionPrefs::Get(profile)->UpdateExtensionPref(
- extension_id(), kPrefNeverActivatedSinceLoaded, new base::Value(false));
+ extension_id(), kPrefNeverActivatedSinceLoaded,
+ base::MakeUnique<base::Value>(false));
// Otherwise, this API is only allowed to be called from a user action.
if (!user_gesture())
@@ -315,7 +321,8 @@ void InputImeActivateFunction::OnPermissionBubbleFinished(
// 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, new base::Value(true));
+ extension_id(), kPrefWarningBubbleNeverShow,
+ base::MakeUnique<base::Value>(true));
}
Respond(NoArguments());
@@ -373,7 +380,7 @@ ExtensionFunction::ResponseAction InputImeCreateWindowFunction::Run() {
return RespondNow(Error(error));
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->Set("frameId", new base::Value(frame_id));
+ result->Set("frameId", base::MakeUnique<base::Value>(frame_id));
return RespondNow(OneArgument(std::move(result)));
}
diff --git a/chromium/chrome/browser/extensions/api/instance_id/OWNERS b/chromium/chrome/browser/extensions/api/instance_id/OWNERS
index e8e7e8ba1ce..331d36d9620 100644
--- a/chromium/chrome/browser/extensions/api/instance_id/OWNERS
+++ b/chromium/chrome/browser/extensions/api/instance_id/OWNERS
@@ -1,2 +1,4 @@
fgorski@chromium.org
-jianli@chromium.org \ No newline at end of file
+jianli@chromium.org
+
+# COMPONENT: Platform>Extensions>API
diff --git a/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc b/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc
index afa6dafb41a..0a897d47a7a 100644
--- a/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc
+++ b/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc
@@ -95,7 +95,7 @@ ExtensionFunction::ResponseAction InstanceIDGetIDFunction::DoWork() {
}
void InstanceIDGetIDFunction::GetIDCompleted(const std::string& id) {
- Respond(OneArgument(base::MakeUnique<base::StringValue>(id)));
+ Respond(OneArgument(base::MakeUnique<base::Value>(id)));
}
InstanceIDGetCreationTimeFunction::InstanceIDGetCreationTimeFunction() {}
@@ -141,7 +141,7 @@ void InstanceIDGetTokenFunction::GetTokenCompleted(
const std::string& token,
instance_id::InstanceID::Result result) {
if (result == instance_id::InstanceID::SUCCESS)
- Respond(OneArgument(base::MakeUnique<base::StringValue>(token)));
+ Respond(OneArgument(base::MakeUnique<base::Value>(token)));
else
Respond(Error(InstanceIDResultToError(result)));
}
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 514a1be373a..b2c3ae921d5 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
@@ -440,7 +440,7 @@ LanguageSettingsPrivateGetTranslateTargetLanguageFunction::
ExtensionFunction::ResponseAction
LanguageSettingsPrivateGetTranslateTargetLanguageFunction::Run() {
return RespondNow(OneArgument(
- base::MakeUnique<base::StringValue>(TranslateService::GetTargetLanguage(
+ base::MakeUnique<base::Value>(TranslateService::GetTargetLanguage(
chrome_details_.GetProfile()->GetPrefs()))));
}
diff --git a/chromium/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc b/chromium/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc
index 4510827c162..2c68152d32f 100644
--- a/chromium/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc
+++ b/chromium/chrome/browser/extensions/api/launcher_page/launcher_page_api.cc
@@ -15,8 +15,8 @@
namespace extensions {
-static base::LazyInstance<BrowserContextKeyedAPIFactory<LauncherPageAPI>>
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<LauncherPageAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<LauncherPageAPI>*
diff --git a/chromium/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc b/chromium/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
index 7ede50fea12..822e9ff45c0 100644
--- a/chromium/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
@@ -15,6 +15,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_prefs.h"
@@ -206,8 +207,9 @@ void LogPrivateAPI::RegisterTempFile(const std::string& owner_extension_id,
base::Unretained(this), owner_extension_id, file_path));
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<LogPrivateAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<LogPrivateAPI>*
@@ -542,9 +544,9 @@ void LogPrivateDumpLogsFunction::OnStoreLogsCompleted(
entry->SetString("baseName", file_entry.registered_name);
entry->SetString("id", file_entry.id);
entry->SetBoolean("isDirectory", false);
- base::ListValue* entry_list = new base::ListValue();
+ auto entry_list = base::MakeUnique<base::ListValue>();
entry_list->Append(std::move(entry));
- response->Set("entries", entry_list);
+ response->Set("entries", std::move(entry_list));
response->SetBoolean("multiple", false);
SetResult(std::move(response));
SendResponse(succeeded);
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 9d52108e54c..8fd3eff8255 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
@@ -10,7 +10,6 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/bookmark_app_helper.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
-#include "chrome/browser/extensions/chrome_requirements_checker.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/launch_util.h"
@@ -225,11 +224,6 @@ ChromeManagementAPIDelegate::SetEnabledFunctionDelegate(
web_contents, browser_context, extension, callback));
}
-std::unique_ptr<extensions::RequirementsChecker>
-ChromeManagementAPIDelegate::CreateRequirementsChecker() const {
- return base::MakeUnique<extensions::ChromeRequirementsChecker>();
-}
-
std::unique_ptr<extensions::UninstallDialogDelegate>
ChromeManagementAPIDelegate::UninstallFunctionDelegate(
extensions::ManagementUninstallFunctionBase* function,
diff --git a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h
index 6c127360516..dec94239580 100644
--- a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h
+++ b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h
@@ -31,8 +31,6 @@ class ChromeManagementAPIDelegate : public extensions::ManagementAPIDelegate {
content::BrowserContext* browser_context,
const extensions::Extension* extension,
const base::Callback<void(bool)>& callback) const override;
- std::unique_ptr<extensions::RequirementsChecker> CreateRequirementsChecker()
- const override;
std::unique_ptr<extensions::UninstallDialogDelegate>
UninstallFunctionDelegate(
extensions::ManagementUninstallFunctionBase* function,
diff --git a/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc b/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc
index 93613c74bb4..7af397ad375 100644
--- a/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc
+++ b/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc
@@ -54,7 +54,8 @@ MDnsAPI* MDnsAPI::Get(content::BrowserContext* context) {
return BrowserContextKeyedAPIFactory<MDnsAPI>::Get(context);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<MDnsAPI> > g_factory =
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<MDnsAPI>>::DestructorAtExit g_factory =
LAZY_INSTANCE_INITIALIZER;
// static
diff --git a/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc b/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
index 1158bb2d835..490e2eb42a5 100644
--- a/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
@@ -11,6 +11,7 @@
#include <vector>
#include "base/memory/ptr_util.h"
+#include "base/values.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/test_extension_system.h"
@@ -245,7 +246,7 @@ class MDnsAPITest : public extensions::ExtensionServiceTestBase {
// Setting app.background.page = "background.html" is sufficient to make
// the extension type TYPE_PLATFORM_APP.
manifest.Set(extensions::manifest_keys::kPlatformAppBackgroundPage,
- new base::StringValue("background.html"));
+ base::MakeUnique<base::Value>("background.html"));
}
std::string error;
diff --git a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
index 57abe0f8b1e..99847806978 100644
--- a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -316,8 +316,8 @@ void MediaGalleriesEventRouter::Shutdown() {
}
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
@@ -585,7 +585,7 @@ void MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId(
}
}
std::unique_ptr<base::DictionaryValue> results(new base::DictionaryValue);
- results->SetWithoutPathExpansion("mediaFileSystems", list.release());
+ results->SetWithoutPathExpansion("mediaFileSystems", std::move(list));
results->SetIntegerWithoutPathExpansion("selectedFileSystemIndex", index);
SetResult(std::move(results));
SendResponse(true);
@@ -743,10 +743,8 @@ void MediaGalleriesGetMetadataFunction::ConstructNextBlob(
&(*attached_images)[blob_uuids->size()];
std::unique_ptr<base::DictionaryValue> attached_image(
new base::DictionaryValue);
- attached_image->Set(kBlobUUIDKey, new base::StringValue(
- current_blob->GetUUID()));
- attached_image->Set(kTypeKey, new base::StringValue(
- current_image->type));
+ attached_image->Set(kBlobUUIDKey, new base::Value(current_blob->GetUUID()));
+ attached_image->Set(kTypeKey, new base::Value(current_image->type));
attached_image->Set(
kSizeKey,
new base::Value(base::checked_cast<int>(current_image->data.size())));
diff --git a/chromium/chrome/browser/extensions/api/messaging/extension_message_port.cc b/chromium/chrome/browser/extensions/api/messaging/extension_message_port.cc
index fe073287147..a53fc70c4cc 100644
--- a/chromium/chrome/browser/extensions/api/messaging/extension_message_port.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/extension_message_port.cc
@@ -60,8 +60,10 @@ class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override {
- if (navigation_handle->HasCommitted() && !navigation_handle->IsSamePage())
+ if (navigation_handle->HasCommitted() &&
+ !navigation_handle->IsSameDocument()) {
port_->UnregisterFrame(navigation_handle->GetRenderFrameHost());
+ }
}
void DidDetachInterstitialPage() override {
diff --git a/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.cc b/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.cc
index f361ab5819d..39818de0a6d 100644
--- a/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.cc
@@ -290,8 +290,8 @@ bool IncognitoConnectability::IsInMap(const Extension* extension,
}
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<IncognitoConnectability> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<IncognitoConnectability>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<IncognitoConnectability>*
diff --git a/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.h b/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.h
index 026ade958ec..9686db2b4f2 100644
--- a/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.h
+++ b/chromium/chrome/browser/extensions/api/messaging/incognito_connectability.h
@@ -27,11 +27,10 @@ class Extension;
// Tracks the web connectability of domains to extensions in incognito mode.
//
// The most important functionality is prompting the user to allow or disallow
-// connections from incognito tabs to extensions or apps. Even if an extension
-// hasn't been enabled in incognito mode, it's still useful for web sites to be
-// able to send messages to them, with user constent. For apps, it's essential
-// we have this functionality because there is no way for them to be enabled in
-// incognito.
+// connections from incognito tabs to extensions or apps. Users are not prompted
+// for extensions which can be enabled in incognito mode. However for apps, it's
+// essential we have this functionality because there is no way for them to be
+// enabled in incognito.
class IncognitoConnectability : public BrowserContextKeyedAPI {
public:
// While in scope, immediately either accepts or denies the alerts that show
diff --git a/chromium/chrome/browser/extensions/api/messaging/message_service.cc b/chromium/chrome/browser/extensions/api/messaging/message_service.cc
index 56d2f39a8be..801f3b6f7a5 100644
--- a/chromium/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/message_service.cc
@@ -22,7 +22,6 @@
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "components/guest_view/common/guest_view_constants.h"
@@ -85,8 +84,8 @@ MessageService::PolicyPermission MessageService::IsNativeMessagingHostAllowed(
return allow_result;
// Check if the name or the wildcard is in the blacklist.
- base::StringValue name_value(native_host_name);
- base::StringValue wildcard_value("*");
+ base::Value name_value(native_host_name);
+ base::Value wildcard_value("*");
if (blacklist->Find(name_value) == blacklist->end() &&
blacklist->Find(wildcard_value) == blacklist->end()) {
return allow_result;
@@ -199,8 +198,9 @@ MessageService::~MessageService() {
channels_.clear();
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<MessageService> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<MessageService>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<MessageService>*
@@ -329,7 +329,7 @@ void MessageService::OpenChannelToExtension(
!util::IsIncognitoEnabled(target_extension_id, context)) {
// Give the user a chance to accept an incognito connection from the web if
// they haven't already, with the conditions:
- // - Only for spanning-mode incognito. We don't want the complication of
+ // - Only for non-split mode incognito. We don't want the complication of
// spinning up an additional process here which might need to do some
// setup that we're not expecting.
// - Only for extensions that can't normally be enabled in incognito, since
@@ -561,8 +561,8 @@ void MessageService::OpenChannelImpl(BrowserContext* browser_context,
std::unique_ptr<MessageChannel> channel_ptr =
base::MakeUnique<MessageChannel>();
MessageChannel* channel = channel_ptr.get();
- channel->opener.reset(opener.release());
- channel->receiver.reset(params->receiver.release());
+ channel->opener = std::move(opener);
+ channel->receiver = std::move(params->receiver);
AddChannel(std::move(channel_ptr), params->receiver_port_id);
int guest_process_id = content::ChildProcessHost::kInvalidUniqueID;
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest.cc
index e54984f45d9..b5106121b37 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest.cc
@@ -112,7 +112,7 @@ bool NativeMessagingHostManifest::Parse(base::DictionaryValue* dictionary,
for (base::ListValue::const_iterator it = allowed_origins_list->begin();
it != allowed_origins_list->end(); ++it) {
std::string pattern_string;
- if (!(*it)->GetAsString(&pattern_string)) {
+ if (!it->GetAsString(&pattern_string)) {
*error_message = "allowed_origins must be list of strings.";
return false;
}
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest_unittest.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest_unittest.cc
index 41707f36c35..d8c9e694778 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_host_manifest_unittest.cc
@@ -47,8 +47,9 @@ class NativeMessagingHostManifestTest : public ::testing::Test {
}
bool WriteManifest(const std::string& manifest_content) {
- return base::WriteFile(
- manifest_path_, manifest_content.data(), manifest_content.size());
+ return base::WriteFile(manifest_path_, manifest_content.data(),
+ manifest_content.size()) ==
+ static_cast<int>(manifest_content.size());
}
base::ScopedTempDir temp_dir_;
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
index bb153dc8f1a..8f9410f00a4 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
@@ -68,7 +68,7 @@ bool NativeMessagingHostListPolicyHandler::CheckAndGetList(
for (base::ListValue::const_iterator entry(list_value->begin());
entry != list_value->end(); ++entry) {
std::string name;
- if (!(*entry)->GetAsString(&name)) {
+ if (!entry->GetAsString(&name)) {
errors->AddError(policy_name(), entry - list_value->begin(),
IDS_POLICY_TYPE_ERROR,
base::Value::GetTypeName(base::Value::Type::STRING));
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc
index 783b0b656b0..ebd91a7b10b 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
#include <memory>
+#include <utility>
#include "base/files/file_path.h"
#include "base/json/json_file_value_serializer.h"
@@ -37,7 +38,7 @@ void WriteTestNativeHostManifest(const base::FilePath& target_dir,
std::unique_ptr<base::ListValue> origins(new base::ListValue());
origins->AppendString(base::StringPrintf(
"chrome-extension://%s/", ScopedTestNativeMessagingHost::kExtensionId));
- manifest->Set("allowed_origins", origins.release());
+ manifest->Set("allowed_origins", std::move(origins));
base::FilePath manifest_path = target_dir.AppendASCII(host_name + ".json");
JSONFileValueSerializer serializer(manifest_path);
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
index 1d51922fd27..0fca48c50ac 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
@@ -152,7 +152,7 @@ bool NativeProcessLauncher::LaunchNativeProcess(
base::LaunchOptions options;
options.start_hidden = true;
options.current_directory = command_line.GetProgram().DirName();
- base::Process cmd_process = base::LaunchProcess(command.c_str(), options);
+ base::Process cmd_process = base::LaunchProcess(command, options);
if (!cmd_process.IsValid()) {
LOG(ERROR) << "Error launching process "
<< command_line.GetProgram().MaybeAsASCII();
diff --git a/chromium/chrome/browser/extensions/api/metrics_private/OWNERS b/chromium/chrome/browser/extensions/api/metrics_private/OWNERS
index feb8271f7ed..816cc8b5361 100644
--- a/chromium/chrome/browser/extensions/api/metrics_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/metrics_private/OWNERS
@@ -1,2 +1,4 @@
asvitkine@chromium.org
isherman@chromium.org
+
+# COMPONENT: Internals>Metrics
diff --git a/chromium/chrome/browser/extensions/api/module/module.cc b/chromium/chrome/browser/extensions/api/module/module.cc
index 8c575be5854..b3874b883c9 100644
--- a/chromium/chrome/browser/extensions/api/module/module.cc
+++ b/chromium/chrome/browser/extensions/api/module/module.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/profiles/profile.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/browser/extension_util.h"
#include "extensions/common/manifest_url_handlers.h"
namespace extensions {
@@ -47,7 +48,7 @@ ExtensionFunction::ResponseAction ExtensionSetUpdateUrlDataFunction::Run() {
ExtensionPrefs::Get(browser_context())
->UpdateExtensionPref(extension_id(), extension::kUpdateURLData,
- new base::StringValue(data));
+ base::MakeUnique<base::Value>(data));
return RespondNow(NoArguments());
}
diff --git a/chromium/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc b/chromium/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc
index cb0f24b541c..341e4cb6461 100644
--- a/chromium/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc
@@ -45,7 +45,7 @@ void MusicManagerPrivateGetDeviceIdFunction::DeviceIdCallback(
SetError(kDeviceIdNotSupported);
response = false;
} else {
- SetResult(base::MakeUnique<base::StringValue>(device_id));
+ SetResult(base::MakeUnique<base::Value>(device_id));
response = true;
}
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/OWNERS b/chromium/chrome/browser/extensions/api/networking_cast_private/OWNERS
new file mode 100644
index 00000000000..b321c2ff0b2
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/OWNERS
@@ -0,0 +1,2 @@
+stevenjb@chromium.org
+tbarzic@chromium.org
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
new file mode 100644
index 00000000000..cd8eb80034e
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
@@ -0,0 +1,231 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
+
+#include <stdint.h>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace extensions {
+
+namespace {
+
+const char kErrorEncryptionError[] = "Error.EncryptionError";
+
+ChromeNetworkingCastPrivateDelegate::FactoryCallback* g_factory_callback =
+ nullptr;
+
+enum class VerificationResult { SUCCESS, VERIFY_FAILURE, DECODE_FAILURE };
+
+// Called from a blocking pool task runner. Tries to decode and verify the
+// provided credentials.
+VerificationResult DecodeAndVerifyCredentials(
+ const NetworkingCastPrivateDelegate::Credentials& credentials) {
+ std::string decoded_signed_data;
+ if (!base::Base64Decode(credentials.signed_data(), &decoded_signed_data)) {
+ LOG(ERROR) << "Failed to decode signed data";
+ return VerificationResult::DECODE_FAILURE;
+ }
+
+ if (networking_private_crypto::VerifyCredentials(
+ credentials.certificate(), credentials.intermediate_certificates(),
+ decoded_signed_data, credentials.unsigned_data(),
+ credentials.device_bssid())) {
+ return VerificationResult::SUCCESS;
+ }
+
+ return VerificationResult::VERIFY_FAILURE;
+}
+
+VerificationResult RunDecodeAndVerifyCredentials(
+ std::unique_ptr<NetworkingCastPrivateDelegate::Credentials> credentials) {
+ return DecodeAndVerifyCredentials(*credentials);
+}
+
+void VerifyDestinationCompleted(
+ const NetworkingCastPrivateDelegate::VerifiedCallback& success_callback,
+ const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
+ VerificationResult result) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (result == VerificationResult::DECODE_FAILURE) {
+ failure_callback.Run(kErrorEncryptionError);
+ return;
+ }
+
+ success_callback.Run(result == VerificationResult::SUCCESS);
+}
+
+// Called from a blocking pool task runner. Returns |data| encoded using
+// |credentials| on success, or an empty string on failure.
+std::string RunVerifyAndEncryptData(
+ const std::string& data,
+ std::unique_ptr<NetworkingCastPrivateDelegate::Credentials> credentials) {
+ if (DecodeAndVerifyCredentials(*credentials) != VerificationResult::SUCCESS)
+ return std::string();
+
+ std::string decoded_public_key;
+ if (!base::Base64Decode(credentials->public_key(), &decoded_public_key)) {
+ LOG(ERROR) << "Failed to decode public key";
+ return std::string();
+ }
+
+ std::vector<uint8_t> public_key_data(decoded_public_key.begin(),
+ decoded_public_key.end());
+ std::vector<uint8_t> ciphertext;
+ if (!networking_private_crypto::EncryptByteString(public_key_data, data,
+ &ciphertext)) {
+ LOG(ERROR) << "Failed to encrypt data";
+ return std::string();
+ }
+
+ std::string base64_encoded_ciphertext;
+ base::Base64Encode(
+ base::StringPiece(reinterpret_cast<const char*>(ciphertext.data()),
+ ciphertext.size()),
+ &base64_encoded_ciphertext);
+ return base64_encoded_ciphertext;
+}
+
+void VerifyAndEncryptDataCompleted(
+ const NetworkingCastPrivateDelegate::DataCallback& success_callback,
+ const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
+ const std::string& encrypted_data) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (encrypted_data.empty())
+ failure_callback.Run(kErrorEncryptionError);
+ else
+ success_callback.Run(encrypted_data);
+}
+
+// Called when NetworkingPrivateCredentialsGetter completes (from an arbitrary
+// thread). Posts the result to the UI thread.
+void CredentialsGetterCompleted(
+ const NetworkingCastPrivateDelegate::DataCallback& success_callback,
+ const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
+ const std::string& key_data,
+ const std::string& error) {
+ if (!error.empty()) {
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(failure_callback, error));
+ } else {
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(success_callback, key_data));
+ }
+}
+
+// Called from a blocking pool task runner. Returns true if
+// NetworkingPrivateCredentialsGetter is successfully started (which will
+// invoke the appropriate callback when completed), or false if unable
+// to start the getter (credentials or public key decode failed).
+bool RunVerifyAndEncryptCredentials(
+ const std::string& guid,
+ std::unique_ptr<NetworkingCastPrivateDelegate::Credentials> credentials,
+ const NetworkingCastPrivateDelegate::DataCallback& success_callback,
+ const NetworkingCastPrivateDelegate::FailureCallback& failure_callback) {
+ if (DecodeAndVerifyCredentials(*credentials) != VerificationResult::SUCCESS)
+ return false;
+
+ std::string decoded_public_key;
+ if (!base::Base64Decode(credentials->public_key(), &decoded_public_key)) {
+ LOG(ERROR) << "Failed to decode public key";
+ return false;
+ }
+
+ // Start getting credentials. CredentialsGetterCompleted will be called on
+ // completion. On Windows it will be called from a different thread after
+ // |credentials_getter| is deleted.
+ std::unique_ptr<NetworkingPrivateCredentialsGetter> credentials_getter(
+ NetworkingPrivateCredentialsGetter::Create());
+ credentials_getter->Start(guid, decoded_public_key,
+ base::Bind(&CredentialsGetterCompleted,
+ success_callback, failure_callback));
+ return true;
+}
+
+void VerifyAndEncryptCredentialsCompleted(
+ const NetworkingCastPrivateDelegate::FailureCallback& failure_callback,
+ bool succeeded) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ // If VerifyAndEncryptCredentials succeeded, then the appropriate callback
+ // will be triggered from CredentialsGetterCompleted.
+ if (succeeded)
+ return;
+ failure_callback.Run(kErrorEncryptionError);
+}
+
+} // namespace
+
+std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
+ChromeNetworkingCastPrivateDelegate::Create() {
+ if (g_factory_callback)
+ return g_factory_callback->Run();
+ return std::unique_ptr<ChromeNetworkingCastPrivateDelegate>(
+ new ChromeNetworkingCastPrivateDelegate);
+}
+
+void ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
+ FactoryCallback* factory_callback) {
+ g_factory_callback = factory_callback;
+}
+
+ChromeNetworkingCastPrivateDelegate::ChromeNetworkingCastPrivateDelegate() {}
+
+ChromeNetworkingCastPrivateDelegate::~ChromeNetworkingCastPrivateDelegate() {}
+
+void ChromeNetworkingCastPrivateDelegate::VerifyDestination(
+ std::unique_ptr<Credentials> credentials,
+ const VerifiedCallback& success_callback,
+ const FailureCallback& failure_callback) {
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ base::TaskTraits().MayBlock().WithPriority(
+ base::TaskPriority::USER_VISIBLE),
+ base::Bind(&RunDecodeAndVerifyCredentials, base::Passed(&credentials)),
+ base::Bind(&VerifyDestinationCompleted, success_callback,
+ failure_callback));
+}
+
+void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptCredentials(
+ const std::string& guid,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) {
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ base::TaskTraits().MayBlock().WithPriority(
+ base::TaskPriority::USER_VISIBLE),
+ base::Bind(&RunVerifyAndEncryptCredentials, guid,
+ base::Passed(&credentials), success_callback,
+ failure_callback),
+ base::Bind(&VerifyAndEncryptCredentialsCompleted, failure_callback));
+}
+
+void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptData(
+ const std::string& data,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) {
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE,
+ base::TaskTraits().MayBlock().WithPriority(
+ base::TaskPriority::USER_VISIBLE),
+ base::Bind(&RunVerifyAndEncryptData, data, base::Passed(&credentials)),
+ base::Bind(&VerifyAndEncryptDataCompleted, success_callback,
+ failure_callback));
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
new file mode 100644
index 00000000000..1207b5cc6b1
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_CHROME_NETWORKING_CAST_PRIVATE_DELEGATE_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_CHROME_NETWORKING_CAST_PRIVATE_DELEGATE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "extensions/browser/api/networking_private/networking_cast_private_delegate.h"
+
+namespace extensions {
+
+// Chrome implementation of extensions::NetworkingCastPrivateDelegate.
+class ChromeNetworkingCastPrivateDelegate
+ : public NetworkingCastPrivateDelegate {
+ public:
+ using FactoryCallback =
+ base::Callback<std::unique_ptr<ChromeNetworkingCastPrivateDelegate>()>;
+ static void SetFactoryCallbackForTest(FactoryCallback* factory_callback);
+
+ static std::unique_ptr<ChromeNetworkingCastPrivateDelegate> Create();
+
+ ~ChromeNetworkingCastPrivateDelegate() override;
+
+ // NetworkingCastPrivateDelegate overrides:
+ void VerifyDestination(std::unique_ptr<Credentials> credentials,
+ const VerifiedCallback& success_callback,
+ const FailureCallback& failure_callback) override;
+ void VerifyAndEncryptCredentials(
+ const std::string& guid,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) override;
+ void VerifyAndEncryptData(const std::string& data,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) override;
+
+ protected:
+ ChromeNetworkingCastPrivateDelegate();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeNetworkingCastPrivateDelegate);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_CHROME_NETWORKING_CAST_PRIVATE_DELEGATE_H_
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc b/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
new file mode 100644
index 00000000000..3fe62342f78
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
@@ -0,0 +1,236 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "chrome/common/extensions/api/networking_cast_private.h"
+#include "extensions/browser/api/extensions_api_client.h"
+#include "extensions/browser/api/networking_private/networking_cast_private_delegate.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/network/network_device_handler.h"
+#include "chromeos/network/network_handler.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+#endif
+
+namespace private_api = extensions::api::networking_private;
+namespace cast_api = extensions::api::networking_cast_private;
+
+namespace extensions {
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+// Parses TDLS status returned by network handler to networking_cast_private
+// TDLS status type.
+cast_api::TDLSStatus ParseTDLSStatus(const std::string& status) {
+ if (status == shill::kTDLSConnectedState)
+ return cast_api::TDLS_STATUS_CONNECTED;
+ if (status == shill::kTDLSNonexistentState)
+ return cast_api::TDLS_STATUS_NONEXISTENT;
+ if (status == shill::kTDLSDisabledState)
+ return cast_api::TDLS_STATUS_DISABLED;
+ if (status == shill::kTDLSDisconnectedState)
+ return cast_api::TDLS_STATUS_DISCONNECTED;
+ if (status == shill::kTDLSUnknownState)
+ return cast_api::TDLS_STATUS_UNKNOWN;
+
+ NOTREACHED() << "Unknown TDLS status " << status;
+ return cast_api::TDLS_STATUS_UNKNOWN;
+}
+#endif
+
+std::unique_ptr<NetworkingCastPrivateDelegate::Credentials> AsCastCredentials(
+ api::networking_cast_private::VerificationProperties& properties) {
+ return base::MakeUnique<NetworkingCastPrivateDelegate::Credentials>(
+ properties.certificate,
+ properties.intermediate_certificates
+ ? *properties.intermediate_certificates
+ : std::vector<std::string>(),
+ properties.signed_data, properties.device_ssid, properties.device_serial,
+ properties.device_bssid, properties.public_key, properties.nonce);
+}
+
+} // namespace
+
+NetworkingCastPrivateVerifyDestinationFunction::
+ ~NetworkingCastPrivateVerifyDestinationFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateVerifyDestinationFunction::Run() {
+ std::unique_ptr<cast_api::VerifyDestination::Params> params =
+ cast_api::VerifyDestination::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ NetworkingCastPrivateDelegate* delegate =
+ ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
+ delegate->VerifyDestination(
+ AsCastCredentials(params->properties),
+ base::Bind(&NetworkingCastPrivateVerifyDestinationFunction::Success,
+ this),
+ base::Bind(&NetworkingCastPrivateVerifyDestinationFunction::Failure,
+ this));
+
+ // VerifyDestination might respond synchronously, e.g. in tests.
+ return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void NetworkingCastPrivateVerifyDestinationFunction::Success(bool result) {
+ Respond(ArgumentList(cast_api::VerifyDestination::Results::Create(result)));
+}
+
+void NetworkingCastPrivateVerifyDestinationFunction::Failure(
+ const std::string& error) {
+ Respond(Error(error));
+}
+
+NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::
+ ~NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Run() {
+ std::unique_ptr<cast_api::VerifyAndEncryptCredentials::Params> params =
+ cast_api::VerifyAndEncryptCredentials::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ NetworkingCastPrivateDelegate* delegate =
+ ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
+ delegate->VerifyAndEncryptCredentials(
+ params->network_guid, AsCastCredentials(params->properties),
+ base::Bind(
+ &NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Success,
+ this),
+ base::Bind(
+ &NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Failure,
+ this));
+
+ // VerifyAndEncryptCredentials might respond synchronously, e.g. in tests.
+ return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Success(
+ const std::string& result) {
+ Respond(ArgumentList(
+ cast_api::VerifyAndEncryptCredentials::Results::Create(result)));
+}
+
+void NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Failure(
+ const std::string& error) {
+ Respond(Error(error));
+}
+
+NetworkingCastPrivateVerifyAndEncryptDataFunction::
+ ~NetworkingCastPrivateVerifyAndEncryptDataFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateVerifyAndEncryptDataFunction::Run() {
+ std::unique_ptr<cast_api::VerifyAndEncryptData::Params> params =
+ cast_api::VerifyAndEncryptData::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ NetworkingCastPrivateDelegate* delegate =
+ ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
+ delegate->VerifyAndEncryptData(
+ params->data, AsCastCredentials(params->properties),
+ base::Bind(&NetworkingCastPrivateVerifyAndEncryptDataFunction::Success,
+ this),
+ base::Bind(&NetworkingCastPrivateVerifyAndEncryptDataFunction::Failure,
+ this));
+
+ // VerifyAndEncryptData might respond synchronously, e.g. in tests.
+ return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void NetworkingCastPrivateVerifyAndEncryptDataFunction::Success(
+ const std::string& result) {
+ Respond(
+ ArgumentList(cast_api::VerifyAndEncryptData::Results::Create(result)));
+}
+
+void NetworkingCastPrivateVerifyAndEncryptDataFunction::Failure(
+ const std::string& error) {
+ Respond(Error(error));
+}
+
+NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::
+ ~NetworkingCastPrivateSetWifiTDLSEnabledStateFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Run() {
+ std::unique_ptr<cast_api::SetWifiTDLSEnabledState::Params> params =
+ cast_api::SetWifiTDLSEnabledState::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+#if defined(OS_CHROMEOS)
+ chromeos::NetworkHandler::Get()->network_device_handler()->SetWifiTDLSEnabled(
+ params->ip_or_mac_address, params->enabled,
+ base::Bind(&NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Success,
+ this),
+ base::Bind(&NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Failure,
+ this));
+
+ // SetWifiTDLSEnabled might respond synchronously, e.g. in tests.
+ return did_respond() ? AlreadyResponded() : RespondLater();
+#else
+ return RespondNow(Error("Not supported"));
+#endif
+}
+
+#if defined(OS_CHROMEOS)
+void NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Success(
+ const std::string& result) {
+ Respond(ArgumentList(cast_api::SetWifiTDLSEnabledState::Results::Create(
+ ParseTDLSStatus(result))));
+}
+
+void NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Failure(
+ const std::string& error,
+ std::unique_ptr<base::DictionaryValue> error_data) {
+ Respond(Error(error));
+}
+#endif
+
+NetworkingCastPrivateGetWifiTDLSStatusFunction::
+ ~NetworkingCastPrivateGetWifiTDLSStatusFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateGetWifiTDLSStatusFunction::Run() {
+ std::unique_ptr<cast_api::GetWifiTDLSStatus::Params> params =
+ cast_api::GetWifiTDLSStatus::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+#if defined(OS_CHROMEOS)
+ chromeos::NetworkHandler::Get()->network_device_handler()->GetWifiTDLSStatus(
+ params->ip_or_mac_address,
+ base::Bind(&NetworkingCastPrivateGetWifiTDLSStatusFunction::Success,
+ this),
+ base::Bind(&NetworkingCastPrivateGetWifiTDLSStatusFunction::Failure,
+ this));
+
+ // GetWifiTDLSStatus might respond synchronously, e.g. in tests.
+ return did_respond() ? AlreadyResponded() : RespondLater();
+#else
+ return RespondNow(Error("Not supported"));
+#endif
+}
+
+#if defined(OS_CHROMEOS)
+void NetworkingCastPrivateGetWifiTDLSStatusFunction::Success(
+ const std::string& result) {
+ Respond(ArgumentList(
+ cast_api::GetWifiTDLSStatus::Results::Create(ParseTDLSStatus(result))));
+}
+
+void NetworkingCastPrivateGetWifiTDLSStatusFunction::Failure(
+ const std::string& error,
+ std::unique_ptr<base::DictionaryValue> error_data) {
+ Respond(Error(error));
+}
+#endif
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h b/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
new file mode 100644
index 00000000000..749e858804d
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
@@ -0,0 +1,131 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_NETWORKING_CAST_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_NETWORKING_CAST_PRIVATE_API_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "extensions/browser/extension_function.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace extensions {
+
+class NetworkingCastPrivateVerifyDestinationFunction
+ : public UIThreadExtensionFunction {
+ public:
+ NetworkingCastPrivateVerifyDestinationFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networking.castPrivate.verifyDestination",
+ NETWORKINGCASTPRIVATE_VERIFYDESTINATION);
+
+ protected:
+ ~NetworkingCastPrivateVerifyDestinationFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+
+ void Success(bool result);
+ void Failure(const std::string& error);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateVerifyDestinationFunction);
+};
+
+class NetworkingCastPrivateVerifyAndEncryptCredentialsFunction
+ : public UIThreadExtensionFunction {
+ public:
+ NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() {}
+ DECLARE_EXTENSION_FUNCTION(
+ "networking.castPrivate.verifyAndEncryptCredentials",
+ NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTCREDENTIALS);
+
+ protected:
+ ~NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+
+ void Success(const std::string& result);
+ void Failure(const std::string& error);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(
+ NetworkingCastPrivateVerifyAndEncryptCredentialsFunction);
+};
+
+class NetworkingCastPrivateVerifyAndEncryptDataFunction
+ : public UIThreadExtensionFunction {
+ public:
+ NetworkingCastPrivateVerifyAndEncryptDataFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networking.castPrivate.verifyAndEncryptData",
+ NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTDATA);
+
+ protected:
+ ~NetworkingCastPrivateVerifyAndEncryptDataFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+
+ void Success(const std::string& result);
+ void Failure(const std::string& error);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateVerifyAndEncryptDataFunction);
+};
+
+class NetworkingCastPrivateSetWifiTDLSEnabledStateFunction
+ : public UIThreadExtensionFunction {
+ public:
+ NetworkingCastPrivateSetWifiTDLSEnabledStateFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networking.castPrivate.setWifiTDLSEnabledState",
+ NETWORKINGCASTPRIVATE_SETWIFITDLSENABLEDSTATE);
+
+ protected:
+ ~NetworkingCastPrivateSetWifiTDLSEnabledStateFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+
+#if defined(OS_CHROMEOS)
+ void Success(const std::string& result);
+ void Failure(const std::string& error,
+ std::unique_ptr<base::DictionaryValue> error_data);
+#endif
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(
+ NetworkingCastPrivateSetWifiTDLSEnabledStateFunction);
+};
+
+class NetworkingCastPrivateGetWifiTDLSStatusFunction
+ : public UIThreadExtensionFunction {
+ public:
+ NetworkingCastPrivateGetWifiTDLSStatusFunction() {}
+ DECLARE_EXTENSION_FUNCTION("networking.castPrivate.getWifiTDLSStatus",
+ NETWORKINGCASTPRIVATE_GETWIFITDLSSTATUS);
+
+ protected:
+ ~NetworkingCastPrivateGetWifiTDLSStatusFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+
+#if defined(OS_CHROMEOS)
+ void Success(const std::string& result);
+ void Failure(const std::string& error,
+ std::unique_ptr<base::DictionaryValue> error_data);
+#endif
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateGetWifiTDLSStatusFunction);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_NETWORKING_CAST_PRIVATE_API_H_
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc b/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
new file mode 100644
index 00000000000..7eed80d9c61
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
@@ -0,0 +1,158 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "extensions/browser/api/networking_private/networking_cast_private_delegate.h"
+#include "extensions/common/switches.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill_device_client.h"
+#include "chromeos/dbus/shill_service_client.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#endif
+
+namespace extensions {
+
+namespace {
+
+class TestNetworkingCastPrivateDelegate
+ : public ChromeNetworkingCastPrivateDelegate {
+ public:
+ TestNetworkingCastPrivateDelegate() {}
+ ~TestNetworkingCastPrivateDelegate() override {}
+
+ void VerifyDestination(std::unique_ptr<Credentials> credentials,
+ const VerifiedCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
+ success_callback.Run(true);
+ }
+
+ void VerifyAndEncryptCredentials(
+ const std::string& guid,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
+ success_callback.Run("encrypted_credentials");
+ }
+
+ void VerifyAndEncryptData(const std::string& data,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
+ success_callback.Run("encrypted_data");
+ }
+
+ private:
+ void AssertCredentials(const Credentials& credentials) {
+ ASSERT_EQ("certificate", credentials.certificate());
+ ASSERT_EQ("ica1,ica2,ica3",
+ base::JoinString(credentials.intermediate_certificates(), ","));
+ ASSERT_EQ("cHVibGljX2tleQ==", credentials.public_key());
+ ASSERT_EQ("00:01:02:03:04:05", credentials.device_bssid());
+ ASSERT_EQ("c2lnbmVkX2RhdGE=", credentials.signed_data());
+ ASSERT_EQ(
+ "Device 0123,device_serial,00:01:02:03:04:05,cHVibGljX2tleQ==,nonce",
+ credentials.unsigned_data());
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TestNetworkingCastPrivateDelegate);
+};
+
+} // namespace
+
+class NetworkingCastPrivateApiTest : public ExtensionApiTest {
+ public:
+ NetworkingCastPrivateApiTest() = default;
+ ~NetworkingCastPrivateApiTest() override = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ExtensionApiTest::SetUpCommandLine(command_line);
+ // Whitelist the extension ID of the test extension.
+ command_line->AppendSwitchASCII(
+ extensions::switches::kWhitelistedExtensionID,
+ "epcifkihnkjgphfkloaaleeakhpmgdmn");
+ }
+
+ void SetUp() override {
+ networking_cast_private_delegate_factory_ = base::Bind(
+ &NetworkingCastPrivateApiTest::CreateNetworkingCastPrivateDelegate,
+ base::Unretained(this));
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
+ &networking_cast_private_delegate_factory_);
+
+ ExtensionApiTest::SetUp();
+ }
+
+ void SetUpOnMainThread() override {
+ ExtensionApiTest::SetUpOnMainThread();
+
+#if defined(OS_CHROMEOS)
+ chromeos::DBusThreadManager* dbus_manager =
+ chromeos::DBusThreadManager::Get();
+ chromeos::ShillDeviceClient::TestInterface* device_test =
+ dbus_manager->GetShillDeviceClient()->GetTestInterface();
+ device_test->ClearDevices();
+ device_test->AddDevice("/device/stub_wifi_device1", shill::kTypeWifi,
+ "stub_wifi_device");
+ device_test->SetTDLSState(shill::kTDLSConnectedState);
+
+ chromeos::ShillServiceClient::TestInterface* service_test =
+ dbus_manager->GetShillServiceClient()->GetTestInterface();
+ service_test->ClearServices();
+ service_test->AddService("stub_wifi", "stub_wifi_guid", "wifi",
+ shill::kTypeWifi, shill::kStateOnline,
+ true /* add_to_visible */);
+#endif // defined(OS_CHROMEOS)
+ }
+
+ void TearDown() override {
+ ExtensionApiTest::TearDown();
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(nullptr);
+ }
+
+ bool TdlsSupported() {
+#if defined(OS_CHROMEOS)
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ private:
+ std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
+ CreateNetworkingCastPrivateDelegate() {
+ return base::MakeUnique<TestNetworkingCastPrivateDelegate>();
+ }
+
+ ChromeNetworkingCastPrivateDelegate::FactoryCallback
+ networking_cast_private_delegate_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateApiTest);
+};
+
+IN_PROC_BROWSER_TEST_F(NetworkingCastPrivateApiTest, Basic) {
+ const std::string arg =
+ base::StringPrintf("{\"tdlsSupported\": %d}", TdlsSupported());
+ EXPECT_TRUE(RunPlatformAppTestWithArg("networking_cast_private", arg.c_str()))
+ << message_;
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc b/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
index 7c3bcfdbd36..7c9675385d1 100644
--- a/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
@@ -99,7 +99,7 @@ class NetworkingConfigTest
shill::kTypeWifi, shill::kStateOnline,
true /* add_to_visible */);
service_test->SetServiceProperty(kWifi1ServicePath, shill::kWifiBSsid,
- base::StringValue("01:02:ab:7f:90:00"));
+ base::Value("01:02:ab:7f:90:00"));
service_test->SetServiceProperty(
kWifi1ServicePath, shill::kSignalStrengthProperty, base::Value(40));
profile_test->AddService(ShillProfileClient::GetSharedProfilePath(),
diff --git a/chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc b/chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc
deleted file mode 100644
index 1fc8b48d1b7..00000000000
--- a/chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/networking_private/crypto_verify_impl.h"
-
-#include <stdint.h>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
-#include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h"
-#include "content/public/browser/browser_thread.h"
-#include "extensions/browser/api/networking_private/networking_private_api.h"
-#include "extensions/browser/api/networking_private/networking_private_service_client.h"
-#include "extensions/common/api/networking_private.h"
-
-namespace extensions {
-
-namespace {
-
-const char kCryptoVerifySequenceTokenName[] = "CryptoVerify";
-
-// Called from a blocking pool task runner. Returns true and sets |verified| if
-// able to decode the credentials, otherwise sets |verified| to false and
-// returns false.
-bool DecodeAndVerifyCredentials(
- const CryptoVerifyImpl::Credentials& credentials,
- bool* verified) {
- std::string decoded_signed_data;
- if (!base::Base64Decode(credentials.signed_data, &decoded_signed_data)) {
- LOG(ERROR) << "Failed to decode signed data";
- *verified = false;
- return false;
- }
- *verified = networking_private_crypto::VerifyCredentials(
- credentials.certificate, credentials.intermediate_certificates,
- decoded_signed_data, credentials.unsigned_data, credentials.device_bssid);
- return true;
-}
-
-void VerifyDestinationCompleted(
- const CryptoVerifyImpl::BoolCallback& success_callback,
- const CryptoVerifyImpl::FailureCallback& failure_callback,
- bool* verified,
- bool success) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!success)
- failure_callback.Run(networking_private::kErrorEncryptionError);
- else
- success_callback.Run(*verified);
-}
-
-// Called from a blocking pool task runner. Returns |data| encoded using
-// |credentials| on success, or an empty string on failure.
-std::string DoVerifyAndEncryptData(
- const CryptoVerifyImpl::Credentials& credentials,
- const std::string& data) {
- bool verified;
- if (!DecodeAndVerifyCredentials(credentials, &verified) || !verified)
- return std::string();
-
- std::string decoded_public_key;
- if (!base::Base64Decode(credentials.public_key, &decoded_public_key)) {
- LOG(ERROR) << "Failed to decode public key";
- return std::string();
- }
-
- std::vector<uint8_t> public_key_data(decoded_public_key.begin(),
- decoded_public_key.end());
- std::vector<uint8_t> ciphertext;
- if (!networking_private_crypto::EncryptByteString(public_key_data, data,
- &ciphertext)) {
- LOG(ERROR) << "Failed to encrypt data";
- return std::string();
- }
-
- std::string base64_encoded_ciphertext;
- base::Base64Encode(
- base::StringPiece(reinterpret_cast<const char*>(ciphertext.data()),
- ciphertext.size()),
- &base64_encoded_ciphertext);
- return base64_encoded_ciphertext;
-}
-
-void VerifyAndEncryptDataCompleted(
- const CryptoVerifyImpl::StringCallback& success_callback,
- const CryptoVerifyImpl::FailureCallback& failure_callback,
- const std::string& encrypted_data) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (encrypted_data.empty())
- failure_callback.Run(networking_private::kErrorEncryptionError);
- else
- success_callback.Run(encrypted_data);
-}
-
-// Called when NetworkingPrivateCredentialsGetter completes (from an arbitrary
-// thread). Posts the result to the UI thread.
-void CredentialsGetterCompleted(
- const CryptoVerifyImpl::StringCallback& success_callback,
- const CryptoVerifyImpl::FailureCallback& failure_callback,
- const std::string& key_data,
- const std::string& error) {
- if (!error.empty()) {
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(failure_callback, error));
- } else {
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(success_callback, key_data));
- }
-}
-
-// Called from a blocking pool task runner. Returns true if
-// NetworkingPrivateCredentialsGetter is successfully started (which will
-// invoke the appropriate callback when completed), or false if unable
-// to start the getter (credentials or public key decode failed).
-bool DoVerifyAndEncryptCredentials(
- const std::string& guid,
- const CryptoVerifyImpl::Credentials& credentials,
- const CryptoVerifyImpl::StringCallback& success_callback,
- const CryptoVerifyImpl::FailureCallback& failure_callback) {
- bool verified;
- if (!DecodeAndVerifyCredentials(credentials, &verified) || !verified)
- return false;
-
- std::string decoded_public_key;
- if (!base::Base64Decode(credentials.public_key, &decoded_public_key)) {
- LOG(ERROR) << "Failed to decode public key";
- return false;
- }
-
- // Start getting credentials. CredentialsGetterCompleted will be called on
- // completion. On Windows it will be called from a different thread after
- // |credentials_getter| is deleted.
- std::unique_ptr<NetworkingPrivateCredentialsGetter> credentials_getter(
- NetworkingPrivateCredentialsGetter::Create());
- credentials_getter->Start(guid, decoded_public_key,
- base::Bind(&CredentialsGetterCompleted,
- success_callback, failure_callback));
- return true;
-}
-
-void VerifyAndEncryptCredentialsCompleted(
- const CryptoVerifyImpl::FailureCallback& failure_callback,
- bool succeeded) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- // If VerifyAndEncryptCredentials succeeded, then the appropriate callback
- // will be triggered from CredentialsGetterCompleted.
- if (succeeded)
- return;
- failure_callback.Run(networking_private::kErrorEncryptionError);
-}
-
-} // namespace
-
-CryptoVerifyImpl::Credentials::Credentials(
- const VerificationProperties& properties) {
- certificate = properties.certificate;
- if (properties.intermediate_certificates.get())
- intermediate_certificates = *properties.intermediate_certificates;
- signed_data = properties.signed_data;
-
- std::vector<std::string> data_parts;
- data_parts.push_back(properties.device_ssid);
- data_parts.push_back(properties.device_serial);
- data_parts.push_back(properties.device_bssid);
- data_parts.push_back(properties.public_key);
- data_parts.push_back(properties.nonce);
- unsigned_data = base::JoinString(data_parts, ",");
-
- device_bssid = properties.device_bssid;
- public_key = properties.public_key;
-}
-
-CryptoVerifyImpl::Credentials::Credentials(const Credentials& other) = default;
-
-CryptoVerifyImpl::Credentials::~Credentials() {
-}
-
-CryptoVerifyImpl::CryptoVerifyImpl() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::SequencedWorkerPool::SequenceToken sequence_token =
- content::BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
- kCryptoVerifySequenceTokenName);
- blocking_pool_task_runner_ =
- content::BrowserThread::GetBlockingPool()
- ->GetSequencedTaskRunnerWithShutdownBehavior(
- sequence_token, base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
-}
-
-CryptoVerifyImpl::~CryptoVerifyImpl() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-}
-
-void CryptoVerifyImpl::VerifyDestination(
- const VerificationProperties& verification_properties,
- const BoolCallback& success_callback,
- const FailureCallback& failure_callback) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- Credentials credentials(verification_properties);
- bool* verified = new bool;
- base::PostTaskAndReplyWithResult(
- blocking_pool_task_runner_.get(), FROM_HERE,
- base::Bind(&DecodeAndVerifyCredentials, credentials, verified),
- base::Bind(&VerifyDestinationCompleted, success_callback,
- failure_callback, base::Owned(verified)));
-}
-
-void CryptoVerifyImpl::VerifyAndEncryptCredentials(
- const std::string& guid,
- const VerificationProperties& verification_properties,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- Credentials credentials(verification_properties);
- base::PostTaskAndReplyWithResult(
- blocking_pool_task_runner_.get(), FROM_HERE,
- base::Bind(&DoVerifyAndEncryptCredentials, guid, credentials,
- success_callback, failure_callback),
- base::Bind(&VerifyAndEncryptCredentialsCompleted, failure_callback));
-}
-
-void CryptoVerifyImpl::VerifyAndEncryptData(
- const VerificationProperties& verification_properties,
- const std::string& data,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- Credentials credentials(verification_properties);
- base::PostTaskAndReplyWithResult(
- blocking_pool_task_runner_.get(), FROM_HERE,
- base::Bind(&DoVerifyAndEncryptData, credentials, data),
- base::Bind(&VerifyAndEncryptDataCompleted, success_callback,
- failure_callback));
-}
-
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h b/chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h
deleted file mode 100644
index fe8ed7dff41..00000000000
--- a/chromium/chrome/browser/extensions/api/networking_private/crypto_verify_impl.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_CRYPTO_VERIFY_IMPL_H_
-#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_CRYPTO_VERIFY_IMPL_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "extensions/browser/api/networking_private/networking_private_delegate.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace extensions {
-
-// Implementation of NetworkingPrivateDelegate::VerifyDelegate using
-// networking_private_crypto.
-class CryptoVerifyImpl : public NetworkingPrivateDelegate::VerifyDelegate {
- public:
- CryptoVerifyImpl();
- ~CryptoVerifyImpl() override;
-
- struct Credentials {
- // VerificationProperties are not copyable so define a struct that can be
- // passed to tasks on the worker thread.
- explicit Credentials(const VerificationProperties& properties);
- Credentials(const Credentials& other);
- ~Credentials();
-
- std::string certificate;
- std::vector<std::string> intermediate_certificates;
- std::string signed_data;
- std::string unsigned_data;
- std::string device_bssid;
- std::string public_key;
- };
-
- // NetworkingPrivateDelegate::VerifyDelegate
- void VerifyDestination(const VerificationProperties& verification_properties,
- const BoolCallback& success_callback,
- const FailureCallback& failure_callback) override;
- void VerifyAndEncryptCredentials(
- const std::string& guid,
- const VerificationProperties& verification_properties,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) override;
- void VerifyAndEncryptData(
- const VerificationProperties& verification_properties,
- const std::string& data,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) override;
-
- private:
- // Task runner for blocking tasks.
- scoped_refptr<base::SequencedTaskRunner> blocking_pool_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(CryptoVerifyImpl);
-};
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_CRYPTO_VERIFY_IMPL_H_
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
index d8d0b782e43..9bbcd167a11 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
@@ -9,11 +9,14 @@
#include <utility>
#include <vector>
+#include "base/bind.h"
+#include "base/callback.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/onc/onc_constants.h"
@@ -38,12 +41,12 @@ const char kFailure[] = "Failure";
const char kSuccess[] = "Success";
const char kGuid[] = "SOME_GUID";
-class TestDelegate : public NetworkingPrivateDelegate {
+class TestNetworkingPrivateDelegate : public NetworkingPrivateDelegate {
public:
- explicit TestDelegate(std::unique_ptr<VerifyDelegate> verify_delegate)
- : NetworkingPrivateDelegate(std::move(verify_delegate)), fail_(false) {}
+ explicit TestNetworkingPrivateDelegate(bool test_failure)
+ : fail_(test_failure) {}
- ~TestDelegate() override {}
+ ~TestNetworkingPrivateDelegate() override {}
// Asynchronous methods
void GetProperties(const std::string& guid,
@@ -66,6 +69,7 @@ class TestDelegate : public NetworkingPrivateDelegate {
void SetProperties(const std::string& guid,
std::unique_ptr<base::DictionaryValue> properties,
+ bool allow_set_shared_config,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) override {
VoidResult(success_callback, failure_callback);
@@ -79,6 +83,7 @@ class TestDelegate : public NetworkingPrivateDelegate {
}
void ForgetNetwork(const std::string& guid,
+ bool allow_forget_shared_network,
const VoidCallback& success_callback,
const FailureCallback& failure_callback) override {
VoidResult(success_callback, failure_callback);
@@ -254,60 +259,83 @@ class TestDelegate : public NetworkingPrivateDelegate {
std::map<std::string, bool> disabled_;
std::vector<bool> scan_requested_;
- DISALLOW_COPY_AND_ASSIGN(TestDelegate);
+ DISALLOW_COPY_AND_ASSIGN(TestNetworkingPrivateDelegate);
};
-class TestVerifyDelegate : public NetworkingPrivateDelegate::VerifyDelegate {
+class TestNetworkingCastPrivateDelegate
+ : public ChromeNetworkingCastPrivateDelegate {
public:
- TestVerifyDelegate() : owner_(NULL) {}
+ explicit TestNetworkingCastPrivateDelegate(bool test_failure)
+ : fail_(test_failure) {}
- ~TestVerifyDelegate() override {}
+ ~TestNetworkingCastPrivateDelegate() override {}
- void VerifyDestination(
- const VerificationProperties& verification_properties,
- const BoolCallback& success_callback,
- const FailureCallback& failure_callback) override {
- owner_->BoolResult(success_callback, failure_callback);
+ void VerifyDestination(std::unique_ptr<Credentials> credentials,
+ const VerifiedCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ if (fail_) {
+ failure_callback.Run(kFailure);
+ } else {
+ success_callback.Run(true);
+ }
}
+
void VerifyAndEncryptCredentials(
const std::string& guid,
- const VerificationProperties& verification_properties,
- const StringCallback& success_callback,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
const FailureCallback& failure_callback) override {
- owner_->StringResult(success_callback, failure_callback);
+ if (fail_) {
+ failure_callback.Run(kFailure);
+ } else {
+ success_callback.Run("encrypted_credentials");
+ }
}
- void VerifyAndEncryptData(
- const VerificationProperties& verification_properties,
- const std::string& data,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) override {
- owner_->StringResult(success_callback, failure_callback);
+ void VerifyAndEncryptData(const std::string& data,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ if (fail_) {
+ failure_callback.Run(kFailure);
+ } else {
+ success_callback.Run("encrypted_data");
+ }
}
- void set_owner(TestDelegate* owner) { owner_ = owner; }
-
private:
- TestDelegate* owner_;
+ bool fail_;
- DISALLOW_COPY_AND_ASSIGN(TestVerifyDelegate);
+ DISALLOW_COPY_AND_ASSIGN(TestNetworkingCastPrivateDelegate);
};
class NetworkingPrivateApiTest : public ExtensionApiTest {
public:
- NetworkingPrivateApiTest() {
- if (!s_test_delegate_) {
- TestVerifyDelegate* verify_delegate = new TestVerifyDelegate;
- std::unique_ptr<NetworkingPrivateDelegate::VerifyDelegate>
- verify_delegate_ptr(verify_delegate);
- s_test_delegate_ = new TestDelegate(std::move(verify_delegate_ptr));
- verify_delegate->set_owner(s_test_delegate_);
- }
- }
+ using TestNetworkingPrivateDelegateFactory =
+ base::Callback<std::unique_ptr<KeyedService>()>;
static std::unique_ptr<KeyedService> GetNetworkingPrivateDelegate(
content::BrowserContext* profile) {
- CHECK(s_test_delegate_);
- return base::WrapUnique(s_test_delegate_);
+ CHECK(s_networking_private_delegate_factory_ptr);
+ return s_networking_private_delegate_factory_ptr->Run();
+ }
+
+ NetworkingPrivateApiTest() = default;
+ ~NetworkingPrivateApiTest() override = default;
+
+ void SetUp() override {
+ networking_cast_delegate_factory_ = base::Bind(
+ &NetworkingPrivateApiTest::CreateTestNetworkingCastPrivateDelegate,
+ base::Unretained(this), test_failure_);
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
+ &networking_cast_delegate_factory_);
+
+ networking_private_delegate_factory_ = base::Bind(
+ &NetworkingPrivateApiTest::CreateTestNetworkingPrivateDelegate,
+ base::Unretained(this), test_failure_);
+ s_networking_private_delegate_factory_ptr =
+ &networking_private_delegate_factory_;
+
+ ExtensionApiTest::SetUp();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -322,19 +350,27 @@ class NetworkingPrivateApiTest : public ExtensionApiTest {
ExtensionApiTest::SetUpOnMainThread();
NetworkingPrivateDelegateFactory::GetInstance()->SetTestingFactory(
profile(), &NetworkingPrivateApiTest::GetNetworkingPrivateDelegate);
- content::RunAllPendingInMessageLoop();
+ }
+
+ void TearDown() override {
+ ExtensionApiTest::TearDown();
+
+ s_networking_private_delegate_factory_ptr = nullptr;
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(nullptr);
+
+ networking_private_delegate_ = nullptr;
}
bool GetEnabled(const std::string& type) {
- return s_test_delegate_->GetEnabled(type);
+ return networking_private_delegate_->GetEnabled(type);
}
bool GetDisabled(const std::string& type) {
- return s_test_delegate_->GetDisabled(type);
+ return networking_private_delegate_->GetDisabled(type);
}
size_t GetScanRequested() {
- return s_test_delegate_->GetScanRequested();
+ return networking_private_delegate_->GetScanRequested();
}
protected:
@@ -344,15 +380,44 @@ class NetworkingPrivateApiTest : public ExtensionApiTest {
kFlagEnableFileAccess | kFlagLoadAsComponent);
}
- // Static pointer to the TestDelegate so that it can be accessed in
- // GetNetworkingPrivateDelegate() passed to SetTestingFactory().
- static TestDelegate* s_test_delegate_;
+ private:
+ std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
+ CreateTestNetworkingCastPrivateDelegate(bool test_failure) {
+ return base::MakeUnique<TestNetworkingCastPrivateDelegate>(test_failure);
+ }
+
+ std::unique_ptr<KeyedService> CreateTestNetworkingPrivateDelegate(
+ bool test_failure) {
+ CHECK(!networking_private_delegate_);
+ auto delegate =
+ base::MakeUnique<TestNetworkingPrivateDelegate>(test_failure);
+ networking_private_delegate_ = delegate.get();
+ return delegate;
+ }
+
+ protected:
+ bool test_failure_ = false;
+
+ private:
+ // Pointer to a networking private delegate created by the test factory
+ // callback.
+ TestNetworkingPrivateDelegate* networking_private_delegate_ = nullptr;
+
+ TestNetworkingPrivateDelegateFactory networking_private_delegate_factory_;
+ // Static pointer to |test_delegate_factory_|, so it can be used from
+ // |CreateNetwokringPrivateDelegate|.
+ static TestNetworkingPrivateDelegateFactory*
+ s_networking_private_delegate_factory_ptr;
+
+ ChromeNetworkingCastPrivateDelegate::FactoryCallback
+ networking_cast_delegate_factory_;
DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateApiTest);
};
-// static
-TestDelegate* NetworkingPrivateApiTest::s_test_delegate_ = NULL;
+NetworkingPrivateApiTest::TestNetworkingPrivateDelegateFactory*
+ NetworkingPrivateApiTest::s_networking_private_delegate_factory_ptr =
+ nullptr;
} // namespace
@@ -474,7 +539,9 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateApiTest, GetGlobalPolicy) {
class NetworkingPrivateApiTestFail : public NetworkingPrivateApiTest {
public:
- NetworkingPrivateApiTestFail() { s_test_delegate_->set_fail(true); }
+ NetworkingPrivateApiTestFail() { test_failure_ = true; }
+
+ ~NetworkingPrivateApiTestFail() override = default;
protected:
DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateApiTestFail);
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index ba49075bfdb..00c1c9e251b 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_ui_delegate_chromeos.h"
#include "chrome/browser/extensions/extension_apitest.h"
@@ -73,6 +74,7 @@ using chromeos::ShillManagerClient;
using chromeos::ShillProfileClient;
using chromeos::ShillServiceClient;
+using extensions::ChromeNetworkingCastPrivateDelegate;
using extensions::NetworkingPrivateDelegate;
using extensions::NetworkingPrivateDelegateFactory;
using extensions::NetworkingPrivateChromeOS;
@@ -91,30 +93,51 @@ const char kCellular1ServicePath[] = "stub_cellular1";
// Stub Verify* methods implementation to satisfy expectations of
// networking_private_apitest.
-class CryptoVerifyStub : public NetworkingPrivateDelegate::VerifyDelegate {
- private:
+class TestNetworkingCastPrivateDelegate
+ : public ChromeNetworkingCastPrivateDelegate {
+ public:
+ TestNetworkingCastPrivateDelegate() = default;
+ ~TestNetworkingCastPrivateDelegate() override = default;
+
// VerifyDelegate
- void VerifyDestination(const VerificationProperties& verification_properties,
- const BoolCallback& success_callback,
+ void VerifyDestination(std::unique_ptr<Credentials> credentials,
+ const VerifiedCallback& success_callback,
const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
success_callback.Run(true);
}
void VerifyAndEncryptCredentials(
const std::string& guid,
- const VerificationProperties& verification_properties,
- const StringCallback& success_callback,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
success_callback.Run("encrypted_credentials");
}
- void VerifyAndEncryptData(
- const VerificationProperties& verification_properties,
- const std::string& data,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) override {
+ void VerifyAndEncryptData(const std::string& data,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
success_callback.Run("encrypted_data");
}
+
+ private:
+ void AssertCredentials(const Credentials& credentials) {
+ ASSERT_EQ("certificate", credentials.certificate());
+ ASSERT_EQ("ica1,ica2,ica3",
+ base::JoinString(credentials.intermediate_certificates(), ","));
+ ASSERT_EQ("cHVibGljX2tleQ==", credentials.public_key());
+ ASSERT_EQ("00:01:02:03:04:05", credentials.device_bssid());
+ ASSERT_EQ("c2lnbmVkX2RhdGE=", credentials.signed_data());
+ ASSERT_EQ(
+ "Device 0123,device_serial,00:01:02:03:04:05,cHVibGljX2tleQ==,nonce",
+ credentials.unsigned_data());
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TestNetworkingCastPrivateDelegate);
};
class UIDelegateStub : public NetworkingPrivateDelegate::UIDelegate {
@@ -231,16 +254,31 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
"stub_cellular_device1");
device_test_->SetDeviceProperty(kCellularDevicePath,
shill::kCarrierProperty,
- base::StringValue("Cellular1_Carrier"));
+ base::Value("Cellular1_Carrier"));
base::DictionaryValue home_provider;
home_provider.SetString("name", "Cellular1_Provider");
home_provider.SetString("code", "000000");
home_provider.SetString("country", "us");
device_test_->SetDeviceProperty(
kCellularDevicePath, shill::kHomeProviderProperty, home_provider);
- device_test_->SetDeviceProperty(
- kCellularDevicePath, shill::kTechnologyFamilyProperty,
- base::StringValue(shill::kNetworkTechnologyGsm));
+ device_test_->SetDeviceProperty(kCellularDevicePath,
+ shill::kTechnologyFamilyProperty,
+ base::Value(shill::kNetworkTechnologyGsm));
+ device_test_->SetDeviceProperty(kCellularDevicePath, shill::kMeidProperty,
+ base::Value("test_meid"));
+ device_test_->SetDeviceProperty(kCellularDevicePath, shill::kImeiProperty,
+ base::Value("test_imei"));
+ device_test_->SetDeviceProperty(kCellularDevicePath, shill::kIccidProperty,
+ base::Value("test_iccid"));
+ device_test_->SetDeviceProperty(kCellularDevicePath, shill::kEsnProperty,
+ base::Value("test_esn"));
+ device_test_->SetDeviceProperty(kCellularDevicePath, shill::kMdnProperty,
+ base::Value("test_mdn"));
+ device_test_->SetDeviceProperty(kCellularDevicePath, shill::kMinProperty,
+ base::Value("test_min"));
+ device_test_->SetDeviceProperty(kCellularDevicePath,
+ shill::kModelIDProperty,
+ base::Value("test_model_id"));
device_test_->SetSimLocked(kCellularDevicePath, false);
// Add the Cellular Service.
@@ -250,13 +288,13 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
kCellular1ServicePath, shill::kAutoConnectProperty, base::Value(true));
service_test_->SetServiceProperty(
kCellular1ServicePath, shill::kNetworkTechnologyProperty,
- base::StringValue(shill::kNetworkTechnologyGsm));
+ base::Value(shill::kNetworkTechnologyGsm));
service_test_->SetServiceProperty(
kCellular1ServicePath, shill::kActivationStateProperty,
- base::StringValue(shill::kActivationStateNotActivated));
- service_test_->SetServiceProperty(
- kCellular1ServicePath, shill::kRoamingStateProperty,
- base::StringValue(shill::kRoamingStateHome));
+ base::Value(shill::kActivationStateNotActivated));
+ service_test_->SetServiceProperty(kCellular1ServicePath,
+ shill::kRoamingStateProperty,
+ base::Value(shill::kRoamingStateHome));
profile_test_->AddService(kUser1ProfilePath, kCellular1ServicePath);
content::RunAllPendingInMessageLoop();
@@ -272,13 +310,22 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
static std::unique_ptr<KeyedService> CreateNetworkingPrivateServiceClient(
content::BrowserContext* context) {
- std::unique_ptr<CryptoVerifyStub> crypto_verify(new CryptoVerifyStub);
std::unique_ptr<NetworkingPrivateDelegate> result(
- new NetworkingPrivateChromeOS(context, std::move(crypto_verify)));
+ new NetworkingPrivateChromeOS(context));
std::unique_ptr<NetworkingPrivateDelegate::UIDelegate> ui_delegate(
new UIDelegateStub);
result->set_ui_delegate(std::move(ui_delegate));
- return std::move(result);
+ return result;
+ }
+
+ void SetUp() override {
+ networking_cast_delegate_factory_ = base::Bind(
+ &NetworkingPrivateChromeOSApiTest::CreateNetworkingCastPrivateDelegate,
+ base::Unretained(this));
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
+ &networking_cast_delegate_factory_);
+
+ ExtensionApiTest::SetUp();
}
void SetUpOnMainThread() override {
@@ -331,14 +378,14 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
device_test_->SetDeviceProperty(kWifiDevicePath, shill::kIPConfigsProperty,
wifi_ip_configs);
device_test_->SetDeviceProperty(kWifiDevicePath, shill::kAddressProperty,
- base::StringValue("001122aabbcc"));
+ base::Value("001122aabbcc"));
// Add Services
AddService("stub_ethernet", "eth0", shill::kTypeEthernet,
shill::kStateOnline);
service_test_->SetServiceProperty(
"stub_ethernet", shill::kProfileProperty,
- base::StringValue(ShillProfileClient::GetSharedProfilePath()));
+ base::Value(ShillProfileClient::GetSharedProfilePath()));
profile_test_->AddService(ShillProfileClient::GetSharedProfilePath(),
"stub_ethernet");
@@ -346,19 +393,18 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
shill::kStateOnline);
service_test_->SetServiceProperty(kWifi1ServicePath,
shill::kSecurityClassProperty,
- base::StringValue(shill::kSecurityWep));
- service_test_->SetServiceProperty(kWifi1ServicePath,
- shill::kWifiBSsid,
- base::StringValue("00:01:02:03:04:05"));
+ base::Value(shill::kSecurityWep));
+ service_test_->SetServiceProperty(kWifi1ServicePath, shill::kWifiBSsid,
+ base::Value("00:01:02:03:04:05"));
service_test_->SetServiceProperty(
kWifi1ServicePath, shill::kSignalStrengthProperty, base::Value(40));
service_test_->SetServiceProperty(kWifi1ServicePath,
shill::kProfileProperty,
- base::StringValue(kUser1ProfilePath));
+ base::Value(kUser1ProfilePath));
service_test_->SetServiceProperty(
kWifi1ServicePath, shill::kConnectableProperty, base::Value(true));
service_test_->SetServiceProperty(kWifi1ServicePath, shill::kDeviceProperty,
- base::StringValue(kWifiDevicePath));
+ base::Value(kWifiDevicePath));
base::DictionaryValue static_ipconfig;
static_ipconfig.SetStringWithoutPathExpansion(shill::kAddressProperty,
"1.2.3.4");
@@ -376,7 +422,7 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
shill::kStateIdle);
service_test_->SetServiceProperty(kWifi2ServicePath,
shill::kSecurityClassProperty,
- base::StringValue(shill::kSecurityPsk));
+ base::Value(shill::kSecurityPsk));
service_test_->SetServiceProperty(
kWifi2ServicePath, shill::kSignalStrengthProperty, base::Value(80));
service_test_->SetServiceProperty(
@@ -386,7 +432,7 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
service_test_->SetServiceProperty(
"stub_wimax", shill::kSignalStrengthProperty, base::Value(40));
service_test_->SetServiceProperty("stub_wimax", shill::kProfileProperty,
- base::StringValue(kUser1ProfilePath));
+ base::Value(kUser1ProfilePath));
service_test_->SetServiceProperty("stub_wimax", shill::kConnectableProperty,
base::Value(true));
profile_test_->AddService(kUser1ProfilePath, "stub_wimax");
@@ -400,27 +446,37 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
base::Value(5000));
service_test_->SetServiceProperty(kWifi2ServicePath,
shill::kProfileProperty,
- base::StringValue(kUser1ProfilePath));
+ base::Value(kUser1ProfilePath));
profile_test_->AddService(kUser1ProfilePath, kWifi2ServicePath);
AddService("stub_vpn1", "vpn1", shill::kTypeVPN, shill::kStateOnline);
- service_test_->SetServiceProperty(
- "stub_vpn1", shill::kProviderTypeProperty,
- base::StringValue(shill::kProviderOpenVpn));
+ service_test_->SetServiceProperty("stub_vpn1", shill::kProviderTypeProperty,
+ base::Value(shill::kProviderOpenVpn));
profile_test_->AddService(kUser1ProfilePath, "stub_vpn1");
AddService("stub_vpn2", "vpn2", shill::kTypeVPN, shill::kStateOffline);
service_test_->SetServiceProperty(
"stub_vpn2", shill::kProviderTypeProperty,
- base::StringValue(shill::kProviderThirdPartyVpn));
+ base::Value(shill::kProviderThirdPartyVpn));
service_test_->SetServiceProperty(
"stub_vpn2", shill::kProviderHostProperty,
- base::StringValue("third_party_provider_extension_id"));
+ base::Value("third_party_provider_extension_id"));
profile_test_->AddService(kUser1ProfilePath, "stub_vpn2");
content::RunAllPendingInMessageLoop();
}
+ void TearDown() override {
+ ExtensionApiTest::TearDown();
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(nullptr);
+ }
+
+ private:
+ std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
+ CreateNetworkingCastPrivateDelegate() {
+ return base::MakeUnique<TestNetworkingCastPrivateDelegate>();
+ }
+
protected:
NetworkPortalDetectorTestImpl* detector() { return detector_; }
@@ -431,6 +487,12 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest {
ShillDeviceClient::TestInterface* device_test_;
policy::MockConfigurationPolicyProvider provider_;
std::string userhash_;
+
+ private:
+ ChromeNetworkingCastPrivateDelegate::FactoryCallback
+ networking_cast_delegate_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateChromeOSApiTest);
};
// Place each subtest into a separate browser test so that the stub networking
@@ -454,9 +516,8 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartActivate) {
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartActivateSprint) {
SetupCellular();
// Set the carrier to Sprint.
- device_test_->SetDeviceProperty(kCellularDevicePath,
- shill::kCarrierProperty,
- base::StringValue(shill::kCarrierSprint));
+ device_test_->SetDeviceProperty(kCellularDevicePath, shill::kCarrierProperty,
+ base::Value(shill::kCarrierSprint));
EXPECT_TRUE(RunNetworkingSubtest("startActivateSprint")) << message_;
EXPECT_EQ(0, UIDelegateStub::s_show_account_details_called_);
}
@@ -553,10 +614,72 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, CreateNetwork) {
EXPECT_TRUE(RunNetworkingSubtest("createNetwork")) << message_;
}
+IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
+ CreateNetworkForPolicyControlledNetwork) {
+ const std::string user_policy_blob =
+ R"({
+ "NetworkConfigurations": [{
+ "GUID": "stub_wifi2",
+ "Type": "WiFi",
+ "Name": "My WiFi Network",
+ "WiFi": {
+ "HexSSID": "77696669325F50534B",
+ "Passphrase": "passphrase",
+ "Recommended": [ "AutoConnect", "Passphrase" ],
+ "Security": "WPA-PSK"
+ }
+ }],
+ "Certificates": [],
+ "Type": "UnencryptedConfiguration"
+ })";
+
+ policy::PolicyMap policy;
+ policy.Set(policy::key::kOpenNetworkConfiguration,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+ policy::POLICY_SOURCE_CLOUD,
+ base::WrapUnique(new base::Value(user_policy_blob)), nullptr);
+ provider_.UpdateChromePolicy(policy);
+
+ content::RunAllPendingInMessageLoop();
+
+ EXPECT_TRUE(RunNetworkingSubtest("createNetworkForPolicyControlledNetwork"));
+}
+
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, ForgetNetwork) {
EXPECT_TRUE(RunNetworkingSubtest("forgetNetwork")) << message_;
}
+IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
+ ForgetPolicyControlledNetwork) {
+ const std::string user_policy_blob =
+ R"({
+ "NetworkConfigurations": [{
+ "GUID": "stub_wifi2",
+ "Type": "WiFi",
+ "Name": "My WiFi Network",
+ "WiFi": {
+ "HexSSID": "77696669325F50534B",
+ "Passphrase": "passphrase",
+ "Recommended": [ "AutoConnect", "Passphrase" ],
+ "Security": "WPA-PSK"
+ }
+ }],
+ "Certificates": [],
+ "Type": "UnencryptedConfiguration"
+ })";
+
+ policy::PolicyMap policy;
+ policy.Set(policy::key::kOpenNetworkConfiguration,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+ policy::POLICY_SOURCE_CLOUD,
+ base::WrapUnique(new base::Value(user_policy_blob)), nullptr);
+ provider_.UpdateChromePolicy(policy);
+
+ content::RunAllPendingInMessageLoop();
+
+ EXPECT_TRUE(RunNetworkingSubtest("forgetPolicyControlledNetwork"));
+}
+
// TODO(stevenjb): Find a better way to set this up on Chrome OS.
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetManagedProperties) {
const std::string uidata_blob =
@@ -566,7 +689,7 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetManagedProperties) {
" }"
"}";
service_test_->SetServiceProperty(kWifi2ServicePath, shill::kUIDataProperty,
- base::StringValue(uidata_blob));
+ base::Value(uidata_blob));
service_test_->SetServiceProperty(
kWifi2ServicePath, shill::kAutoConnectProperty, base::Value(false));
@@ -592,10 +715,10 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetManagedProperties) {
"}";
policy::PolicyMap policy;
- policy.Set(
- policy::key::kOpenNetworkConfiguration, policy::POLICY_LEVEL_MANDATORY,
- policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
- base::WrapUnique(new base::StringValue(user_policy_blob)), nullptr);
+ policy.Set(policy::key::kOpenNetworkConfiguration,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+ policy::POLICY_SOURCE_CLOUD,
+ base::WrapUnique(new base::Value(user_policy_blob)), nullptr);
provider_.UpdateChromePolicy(policy);
content::RunAllPendingInMessageLoop();
@@ -732,6 +855,7 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetGlobalPolicy) {
// using API methods and event does not cause access exceptions (due to
// missing permissions).
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, Alias) {
+ SetupCellular();
EXPECT_TRUE(RunPlatformAppTest("networking_private/alias")) << message_;
}
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
index e7abad92c15..a50e5718866 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
@@ -9,7 +9,9 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "components/user_manager/user.h"
@@ -33,6 +35,7 @@
using testing::Return;
using testing::_;
+using extensions::ChromeNetworkingCastPrivateDelegate;
using extensions::NetworkingPrivateDelegate;
using extensions::NetworkingPrivateDelegateFactory;
using extensions::NetworkingPrivateEventRouter;
@@ -43,29 +46,50 @@ namespace {
// Stub Verify* methods implementation to satisfy expectations of
// networking_private_apitest.
-class CryptoVerifyStub : public NetworkingPrivateDelegate::VerifyDelegate {
- void VerifyDestination(
- const VerificationProperties& verification_properties,
- const BoolCallback& success_callback,
- const FailureCallback& failure_callback) override {
+class TestNetworkingCastPrivateDelegate
+ : public ChromeNetworkingCastPrivateDelegate {
+ public:
+ TestNetworkingCastPrivateDelegate() = default;
+ ~TestNetworkingCastPrivateDelegate() override = default;
+
+ void VerifyDestination(std::unique_ptr<Credentials> credentials,
+ const VerifiedCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
success_callback.Run(true);
}
void VerifyAndEncryptCredentials(
const std::string& guid,
- const VerificationProperties& verification_properties,
- const StringCallback& success_callback,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
success_callback.Run("encrypted_credentials");
}
- void VerifyAndEncryptData(
- const VerificationProperties& verification_properties,
- const std::string& data,
- const StringCallback& success_callback,
- const FailureCallback& failure_callback) override {
+ void VerifyAndEncryptData(const std::string& data,
+ std::unique_ptr<Credentials> credentials,
+ const DataCallback& success_callback,
+ const FailureCallback& failure_callback) override {
+ AssertCredentials(*credentials);
success_callback.Run("encrypted_data");
}
+
+ private:
+ void AssertCredentials(const Credentials& credentials) {
+ ASSERT_EQ("certificate", credentials.certificate());
+ ASSERT_EQ("ica1,ica2,ica3",
+ base::JoinString(credentials.intermediate_certificates(), ","));
+ ASSERT_EQ("cHVibGljX2tleQ==", credentials.public_key());
+ ASSERT_EQ("00:01:02:03:04:05", credentials.device_bssid());
+ ASSERT_EQ("c2lnbmVkX2RhdGE=", credentials.signed_data());
+ ASSERT_EQ(
+ "Device 0123,device_serial,00:01:02:03:04:05,cHVibGljX2tleQ==,nonce",
+ credentials.unsigned_data());
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TestNetworkingCastPrivateDelegate);
};
class NetworkingPrivateServiceClientApiTest : public ExtensionApiTest {
@@ -90,9 +114,18 @@ class NetworkingPrivateServiceClientApiTest : public ExtensionApiTest {
content::BrowserContext* context) {
std::unique_ptr<wifi::FakeWiFiService> wifi_service(
new wifi::FakeWiFiService());
- std::unique_ptr<CryptoVerifyStub> crypto_verify(new CryptoVerifyStub);
- return std::unique_ptr<KeyedService>(new NetworkingPrivateServiceClient(
- std::move(wifi_service), std::move(crypto_verify)));
+ return std::unique_ptr<KeyedService>(
+ new NetworkingPrivateServiceClient(std::move(wifi_service)));
+ }
+
+ void SetUp() override {
+ networking_cast_delegate_factory_ =
+ base::Bind(&NetworkingPrivateServiceClientApiTest::
+ CreateNetworkingCastPrivateDelegate,
+ base::Unretained(this));
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
+ &networking_cast_delegate_factory_);
+ ExtensionApiTest::SetUp();
}
void SetUpOnMainThread() override {
@@ -107,7 +140,20 @@ class NetworkingPrivateServiceClientApiTest : public ExtensionApiTest {
ExtensionApiTest::TearDownOnMainThread();
}
- protected:
+ void TearDown() override {
+ ExtensionApiTest::TearDown();
+ ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(nullptr);
+ }
+
+ private:
+ std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
+ CreateNetworkingCastPrivateDelegate() {
+ return base::MakeUnique<TestNetworkingCastPrivateDelegate>();
+ }
+
+ ChromeNetworkingCastPrivateDelegate::FactoryCallback
+ networking_cast_delegate_factory_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateServiceClientApiTest);
};
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc
deleted file mode 100644
index 036b5d29b5a..00000000000
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h"
-
-#include "base/memory/ptr_util.h"
-#include "build/build_config.h"
-#include "chrome/browser/extensions/api/networking_private/crypto_verify_impl.h"
-
-namespace extensions {
-
-NetworkingPrivateVerifyDelegateFactoryImpl::
- NetworkingPrivateVerifyDelegateFactoryImpl() {
-}
-
-NetworkingPrivateVerifyDelegateFactoryImpl::
- ~NetworkingPrivateVerifyDelegateFactoryImpl() {
-}
-
-std::unique_ptr<NetworkingPrivateDelegate::VerifyDelegate>
-NetworkingPrivateVerifyDelegateFactoryImpl::CreateDelegate() {
-#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_MACOSX)
- return base::MakeUnique<CryptoVerifyImpl>();
-#else
- return nullptr;
-#endif
-}
-
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h b/chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h
deleted file mode 100644
index 78029bf5f89..00000000000
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_VERIFY_DELEGATE_FACTORY_IMPL_H_
-#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_VERIFY_DELEGATE_FACTORY_IMPL_H_
-
-#include "base/macros.h"
-#include "extensions/browser/api/networking_private/networking_private_delegate_factory.h"
-
-namespace extensions {
-
-class NetworkingPrivateVerifyDelegateFactoryImpl
- : public NetworkingPrivateDelegateFactory::VerifyDelegateFactory {
- public:
- NetworkingPrivateVerifyDelegateFactoryImpl();
- ~NetworkingPrivateVerifyDelegateFactoryImpl() override;
-
- std::unique_ptr<NetworkingPrivateDelegate::VerifyDelegate> CreateDelegate()
- override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateVerifyDelegateFactoryImpl);
-};
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_PRIVATE_NETWORKING_PRIVATE_VERIFY_DELEGATE_FACTORY_IMPL_H_
diff --git a/chromium/chrome/browser/extensions/api/notifications/OWNERS b/chromium/chrome/browser/extensions/api/notifications/OWNERS
index 6f1cc7b2a2c..14240545981 100644
--- a/chromium/chrome/browser/extensions/api/notifications/OWNERS
+++ b/chromium/chrome/browser/extensions/api/notifications/OWNERS
@@ -1 +1,4 @@
dewittj@chromium.org
+
+# TEAM: extensions-dev@chromium.org
+# COMPONENT: Platform>Extensions
diff --git a/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc
new file mode 100644
index 00000000000..cfbdfc490ee
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc
@@ -0,0 +1,95 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/notifications/extension_notification_display_helper.h"
+
+#include <algorithm>
+
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_display_service.h"
+#include "chrome/browser/notifications/notification_display_service_factory.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+ExtensionNotificationDisplayHelper::ExtensionNotificationDisplayHelper(
+ Profile* profile)
+ : profile_(profile) {}
+
+ExtensionNotificationDisplayHelper::~ExtensionNotificationDisplayHelper() {}
+
+void ExtensionNotificationDisplayHelper::Display(
+ const Notification& notification) {
+ // Remove the previous version of this notification if the |notification| is
+ // updating another notification.
+ EraseDataForNotificationId(notification.delegate_id());
+
+ notifications_.push_back(base::MakeUnique<Notification>(notification));
+
+ GetDisplayService()->Display(NotificationCommon::EXTENSION,
+ notification.delegate_id(), notification);
+}
+
+Notification* ExtensionNotificationDisplayHelper::GetByNotificationId(
+ const std::string& notification_id) {
+ for (const auto& notification : notifications_) {
+ if (notification->delegate_id() == notification_id)
+ return notification.get();
+ }
+
+ return nullptr;
+}
+
+std::set<std::string>
+ExtensionNotificationDisplayHelper::GetNotificationIdsForExtension(
+ const GURL& extension_origin) const {
+ std::set<std::string> notification_ids;
+ for (const auto& notification : notifications_) {
+ if (notification->origin_url() == extension_origin)
+ notification_ids.insert(notification->delegate_id());
+ }
+
+ return notification_ids;
+}
+
+bool ExtensionNotificationDisplayHelper::EraseDataForNotificationId(
+ const std::string& notification_id) {
+ auto iter = std::find_if(
+ notifications_.begin(), notifications_.end(),
+ [notification_id](const std::unique_ptr<Notification>& notification) {
+ return notification->delegate_id() == notification_id;
+ });
+
+ if (iter == notifications_.end())
+ return false;
+
+ notifications_.erase(iter);
+ return true;
+}
+
+bool ExtensionNotificationDisplayHelper::Close(
+ const std::string& notification_id) {
+ if (!EraseDataForNotificationId(notification_id))
+ return false;
+
+ GetDisplayService()->Close(NotificationCommon::EXTENSION, notification_id);
+ return true;
+}
+
+void ExtensionNotificationDisplayHelper::Shutdown() {
+ // Do not call GetDisplayService()->Close() here. The Shutdown method is
+ // called upon profile destruction and closing a notification requires a
+ // profile, as it may dispatch an event to the extension.
+
+ notifications_.clear();
+}
+
+NotificationDisplayService*
+ExtensionNotificationDisplayHelper::GetDisplayService() {
+ return NotificationDisplayServiceFactory::GetForProfile(profile_);
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.h b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.h
new file mode 100644
index 00000000000..1ebf8fb9271
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper.h
@@ -0,0 +1,72 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_DISPLAY_HELPER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_DISPLAY_HELPER_H_
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+class GURL;
+class Notification;
+class NotificationDisplayService;
+class Profile;
+
+namespace extensions {
+
+// Helper class for displaying notifications through the notification display
+// service. The NDS supports notifications that can outlive the browser process,
+// and therefore does not retain as much information as is necessary to support
+// the extensions API. (Notably the ability to partly update notifications.)
+class ExtensionNotificationDisplayHelper : public KeyedService {
+ public:
+ explicit ExtensionNotificationDisplayHelper(Profile* profile);
+ ~ExtensionNotificationDisplayHelper() override;
+
+ // Displays the |notification| using the notification display service.
+ void Display(const Notification& notification);
+
+ // Returns the notification identified by |notification_id| if it is currently
+ // visible. May return a nullptr.
+ Notification* GetByNotificationId(const std::string& notification_id);
+
+ // Returns a set with the IDs of all notifications that are currently being
+ // shown on behalf of the |extension_origin|.
+ std::set<std::string> GetNotificationIdsForExtension(
+ const GURL& extension_origin) const;
+
+ // Removes stored state for the notification identified by |notification_id|.
+ // Returns whether there was local state.
+ bool EraseDataForNotificationId(const std::string& notification_id);
+
+ // Closes the notification identified by |notification_id|. Returns whether a
+ // notification was closed in response to the call.
+ bool Close(const std::string& notification_id);
+
+ // KeyedService overrides:
+ void Shutdown() override;
+
+ private:
+ using NotificationVector = std::vector<std::unique_ptr<Notification>>;
+
+ // Returns the notification display service instance to communicate with.
+ NotificationDisplayService* GetDisplayService();
+
+ // The Profile instance that owns this keyed service.
+ Profile* profile_;
+
+ // Vector of notifications that are being shown for extensions.
+ NotificationVector notifications_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionNotificationDisplayHelper);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_DISPLAY_HELPER_H_
diff --git a/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.cc b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.cc
new file mode 100644
index 00000000000..e537ef7b9ea
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.cc
@@ -0,0 +1,49 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h"
+
+#include "chrome/browser/extensions/api/notifications/extension_notification_display_helper.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace extensions {
+
+// static
+ExtensionNotificationDisplayHelperFactory*
+ExtensionNotificationDisplayHelperFactory::GetInstance() {
+ return base::Singleton<ExtensionNotificationDisplayHelperFactory>::get();
+}
+
+// static
+ExtensionNotificationDisplayHelper*
+ExtensionNotificationDisplayHelperFactory::GetForProfile(Profile* profile) {
+ return static_cast<ExtensionNotificationDisplayHelper*>(
+ GetInstance()->GetServiceForBrowserContext(profile, true /* create */));
+}
+
+ExtensionNotificationDisplayHelperFactory::
+ ExtensionNotificationDisplayHelperFactory()
+ : BrowserContextKeyedServiceFactory(
+ "ExtensionNotificationDisplayHelperFactory",
+ BrowserContextDependencyManager::GetInstance()) {}
+
+ExtensionNotificationDisplayHelperFactory::
+ ~ExtensionNotificationDisplayHelperFactory() {}
+
+KeyedService*
+ExtensionNotificationDisplayHelperFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ Profile* profile = Profile::FromBrowserContext(context);
+ return new ExtensionNotificationDisplayHelper(profile);
+}
+
+content::BrowserContext*
+ExtensionNotificationDisplayHelperFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextOwnInstanceInIncognito(context);
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h
new file mode 100644
index 00000000000..85911583db0
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_DISPLAY_HELPER_FACTORY_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_DISPLAY_HELPER_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class Profile;
+
+namespace extensions {
+
+class ExtensionNotificationDisplayHelper;
+
+class ExtensionNotificationDisplayHelperFactory
+ : public BrowserContextKeyedServiceFactory {
+ public:
+ // Get the singleton instance of the factory.
+ static ExtensionNotificationDisplayHelperFactory* GetInstance();
+
+ // Get the display helper for |profile|, creating one if needed.
+ static ExtensionNotificationDisplayHelper* GetForProfile(Profile* profile);
+
+ protected:
+ // Overridden from BrowserContextKeyedServiceFactory.
+ KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+
+ private:
+ friend struct base::DefaultSingletonTraits<
+ ExtensionNotificationDisplayHelperFactory>;
+
+ ExtensionNotificationDisplayHelperFactory();
+ ~ExtensionNotificationDisplayHelperFactory() override;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionNotificationDisplayHelperFactory);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_DISPLAY_HELPER_FACTORY_H_
diff --git a/chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.cc b/chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.cc
new file mode 100644
index 00000000000..f5578ffd8a5
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.cc
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/notifications/extension_notification_handler.h"
+
+#include "base/logging.h"
+
+ExtensionNotificationHandler::ExtensionNotificationHandler() = default;
+
+ExtensionNotificationHandler::~ExtensionNotificationHandler() = default;
+
+void ExtensionNotificationHandler::OpenSettings(Profile* profile) {
+ // Extension notifications don't display a settings button.
+ NOTREACHED();
+}
diff --git a/chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.h b/chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.h
new file mode 100644
index 00000000000..9d6985ff7e8
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/notifications/extension_notification_handler.h
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_HANDLER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_HANDLER_H_
+
+#include "base/macros.h"
+#include "chrome/browser/notifications/non_persistent_notification_handler.h"
+
+// Handler for notifications shown by extensions. Will be created and owned by
+// the NotificationDisplayService.
+class ExtensionNotificationHandler : public NonPersistentNotificationHandler {
+ public:
+ ExtensionNotificationHandler();
+ ~ExtensionNotificationHandler() override;
+
+ // NotificationHandler implementation.
+ void OpenSettings(Profile* profile) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ExtensionNotificationHandler);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_NOTIFICATIONS_EXTENSION_NOTIFICATION_HANDLER_H_
diff --git a/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc b/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
index cd435f5d0c6..577aaf7c764 100644
--- a/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -19,9 +19,9 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/api/notifications/extension_notification_display_helper.h"
+#include "chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h"
#include "chrome/browser/notifications/notification.h"
-#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/notifier_state_tracker.h"
#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
#include "chrome/browser/profiles/profile.h"
@@ -212,10 +212,14 @@ class NotificationsApiDelegate : public NotificationDelegate {
const std::string& id)
: api_function_(api_function),
event_router_(EventRouter::Get(profile)),
+ display_helper_(
+ ExtensionNotificationDisplayHelperFactory::GetForProfile(profile)),
extension_id_(extension_id),
id_(id),
scoped_id_(CreateScopedIdentifier(extension_id, id)) {
DCHECK(api_function_);
+ DCHECK(display_helper_);
+
shutdown_notifier_subscription_ =
ShutdownNotifierFactory::GetInstance()->Get(profile)->Subscribe(
base::Bind(&NotificationsApiDelegate::Shutdown,
@@ -230,6 +234,9 @@ class NotificationsApiDelegate : public NotificationDelegate {
args->AppendBoolean(by_user);
SendEvent(events::NOTIFICATIONS_ON_CLOSED,
notifications::OnClosed::kEventName, gesture, std::move(args));
+
+ DCHECK(display_helper_);
+ display_helper_->EraseDataForNotificationId(scoped_id_);
}
void Click() override {
@@ -302,8 +309,9 @@ class NotificationsApiDelegate : public NotificationDelegate {
}
void Shutdown() {
- event_router_ = nullptr;
shutdown_notifier_subscription_.reset();
+ event_router_ = nullptr;
+ display_helper_ = nullptr;
}
std::unique_ptr<base::ListValue> CreateBaseEventArgs() {
@@ -318,6 +326,7 @@ class NotificationsApiDelegate : public NotificationDelegate {
// profile-keyed service shutdown events and reset to nullptr at that time,
// so make sure to check for a valid pointer before use.
EventRouter* event_router_;
+ ExtensionNotificationDisplayHelper* display_helper_;
const std::string extension_id_;
const std::string id_;
@@ -496,7 +505,7 @@ bool NotificationsApiFunction::CreateNotification(
notification.set_never_timeout(options->require_interaction &&
*options->require_interaction);
- g_browser_process->notification_ui_manager()->Add(notification, GetProfile());
+ GetDisplayHelper()->Display(notification);
return true;
}
@@ -630,8 +639,10 @@ bool NotificationsApiFunction::UpdateNotification(
if (options->is_clickable.get())
notification->set_clickable(*options->is_clickable);
- g_browser_process->notification_ui_manager()->Update(*notification,
- GetProfile());
+ // It's safe to follow the regular path for adding a new notification as it's
+ // already been verified that there is a notification that can be updated.
+ GetDisplayHelper()->Display(*notification);
+
return true;
}
@@ -652,6 +663,11 @@ bool NotificationsApiFunction::CanRunWhileDisabled() const {
return false;
}
+ExtensionNotificationDisplayHelper* NotificationsApiFunction::GetDisplayHelper()
+ const {
+ return ExtensionNotificationDisplayHelperFactory::GetForProfile(GetProfile());
+}
+
bool NotificationsApiFunction::RunAsync() {
if (IsNotificationsApiAvailable() && IsNotificationsApiEnabled()) {
return RunNotificationsApi();
@@ -704,7 +720,7 @@ bool NotificationsCreateFunction::RunNotificationsApi() {
notification_id = base::RandBytesAsString(16);
}
- SetResult(base::MakeUnique<base::StringValue>(notification_id));
+ SetResult(base::MakeUnique<base::Value>(notification_id));
// TODO(dewittj): Add more human-readable error strings if this fails.
if (!CreateNotification(notification_id, &params_->options))
@@ -728,9 +744,9 @@ bool NotificationsUpdateFunction::RunNotificationsApi() {
// We are in update. If the ID doesn't exist, succeed but call the callback
// with "false".
const Notification* matched_notification =
- g_browser_process->notification_ui_manager()->FindById(
- CreateScopedIdentifier(extension_->id(), params_->notification_id),
- NotificationUIManager::GetProfileID(GetProfile()));
+ GetDisplayHelper()->GetByNotificationId(
+ CreateScopedIdentifier(extension_->id(), params_->notification_id));
+
if (!matched_notification) {
SetResult(base::MakeUnique<base::Value>(false));
SendResponse(true);
@@ -766,9 +782,8 @@ bool NotificationsClearFunction::RunNotificationsApi() {
params_ = api::notifications::Clear::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params_.get());
- bool cancel_result = g_browser_process->notification_ui_manager()->CancelById(
- CreateScopedIdentifier(extension_->id(), params_->notification_id),
- NotificationUIManager::GetProfileID(GetProfile()));
+ bool cancel_result = GetDisplayHelper()->Close(
+ CreateScopedIdentifier(extension_->id(), params_->notification_id));
SetResult(base::MakeUnique<base::Value>(cancel_result));
SendResponse(true);
@@ -781,11 +796,8 @@ NotificationsGetAllFunction::NotificationsGetAllFunction() {}
NotificationsGetAllFunction::~NotificationsGetAllFunction() {}
bool NotificationsGetAllFunction::RunNotificationsApi() {
- NotificationUIManager* notification_ui_manager =
- g_browser_process->notification_ui_manager();
std::set<std::string> notification_ids =
- notification_ui_manager->GetAllIdsByProfileAndSourceOrigin(
- NotificationUIManager::GetProfileID(GetProfile()), extension_->url());
+ GetDisplayHelper()->GetNotificationIdsForExtension(extension_->url());
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
@@ -817,8 +829,8 @@ bool NotificationsGetPermissionLevelFunction::RunNotificationsApi() {
? api::notifications::PERMISSION_LEVEL_GRANTED
: api::notifications::PERMISSION_LEVEL_DENIED;
- SetResult(base::MakeUnique<base::StringValue>(
- api::notifications::ToString(result)));
+ SetResult(
+ base::MakeUnique<base::Value>(api::notifications::ToString(result)));
SendResponse(true);
return true;
diff --git a/chromium/chrome/browser/extensions/api/notifications/notifications_api.h b/chromium/chrome/browser/extensions/api/notifications/notifications_api.h
index d7bb4b712c7..1a21c118965 100644
--- a/chromium/chrome/browser/extensions/api/notifications/notifications_api.h
+++ b/chromium/chrome/browser/extensions/api/notifications/notifications_api.h
@@ -20,6 +20,8 @@ namespace extensions {
extern const base::Feature kAllowFullscreenAppNotificationsFeature;
+class ExtensionNotificationDisplayHelper;
+
class NotificationsApiFunction : public ChromeAsyncExtensionFunction {
public:
// Whether the current extension and channel allow the API. Public for
@@ -40,6 +42,10 @@ class NotificationsApiFunction : public ChromeAsyncExtensionFunction {
bool AreExtensionNotificationsAllowed() const;
+ // Returns the display helper that should be used for interacting with the
+ // common notification system.
+ ExtensionNotificationDisplayHelper* GetDisplayHelper() const;
+
// Returns true if the API function is still allowed to run even when the
// notifications for a notifier have been disabled.
virtual bool CanRunWhileDisabled() const;
diff --git a/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc
index 1ebdf8afc36..761c413acf8 100644
--- a/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -8,12 +8,17 @@
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/apps/app_browsertest_util.h"
-#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/api/notifications/extension_notification_display_helper.h"
+#include "chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h"
#include "chrome/browser/extensions/api/notifications/notifications_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/notifications/notification.h"
-#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/notifications/notification_common.h"
+#include "chrome/browser/notifications/notification_display_service_factory.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/notifier_state_tracker_factory.h"
+#include "chrome/browser/notifications/stub_notification_display_service.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/extensions/app_launch_params.h"
#include "chrome/browser/ui/extensions/application_launch.h"
@@ -30,8 +35,6 @@
#include "extensions/common/test_util.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/notification_list.h"
#include "ui/message_center/notifier_settings.h"
#if defined(OS_MACOSX)
@@ -42,6 +45,8 @@
using extensions::AppWindow;
using extensions::AppWindowRegistry;
using extensions::Extension;
+using extensions::ExtensionNotificationDisplayHelper;
+using extensions::ExtensionNotificationDisplayHelperFactory;
using extensions::ResultCatcher;
namespace utils = extension_function_test_utils;
@@ -155,14 +160,46 @@ class NotificationsApiTest : public ExtensionApiTest {
return NULL;
}
+ ExtensionNotificationDisplayHelper* GetDisplayHelper() {
+ return ExtensionNotificationDisplayHelperFactory::GetForProfile(profile());
+ }
+
+ StubNotificationDisplayService* GetDisplayService() {
+ return reinterpret_cast<StubNotificationDisplayService*>(
+ NotificationDisplayServiceFactory::GetForProfile(profile()));
+ }
+
+ NotifierStateTracker* GetNotifierStateTracker() {
+ return NotifierStateTrackerFactory::GetForProfile(profile());
+ }
+
protected:
+ void SetUpOnMainThread() override {
+ ExtensionApiTest::SetUpOnMainThread();
+
+ DCHECK(profile());
+ NotificationDisplayServiceFactory::GetInstance()->SetTestingFactory(
+ profile(), &StubNotificationDisplayService::FactoryForTests);
+ }
+
+ // Returns the notification that's being displayed for |extension|, or nullptr
+ // when the notification count is not equal to one. It's not safe to rely on
+ // the Notification pointer after closing the notification, but a copy can be
+ // made to continue to be able to access the underlying information.
+ Notification* GetNotificationForExtension(
+ const extensions::Extension* extension) {
+ DCHECK(extension);
+
+ std::set<std::string> notifications =
+ GetDisplayHelper()->GetNotificationIdsForExtension(extension->url());
+ if (notifications.size() != 1)
+ return nullptr;
+
+ return GetDisplayHelper()->GetByNotificationId(*notifications.begin());
+ }
+
std::string GetNotificationIdFromDelegateId(const std::string& delegate_id) {
- return g_browser_process->notification_ui_manager()
- ->FindById(
- delegate_id,
- NotificationUIManager::GetProfileID(
- g_browser_process->profile_manager()->GetLastUsedProfile()))
- ->id();
+ return GetDisplayHelper()->GetByNotificationId(delegate_id)->id();
}
void LaunchPlatformApp(const Extension* extension) {
@@ -216,8 +253,8 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestByUser) {
ResultCatcher catcher;
const std::string notification_id =
GetNotificationIdFromDelegateId(extension->id() + "-FOO");
- g_browser_process->message_center()->RemoveNotification(notification_id,
- false);
+ GetDisplayService()->RemoveNotification(
+ NotificationCommon::EXTENSION, notification_id, false /* by_user */);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
@@ -225,21 +262,21 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestByUser) {
ResultCatcher catcher;
const std::string notification_id =
GetNotificationIdFromDelegateId(extension->id() + "-BAR");
- g_browser_process->message_center()->RemoveNotification(notification_id,
- true);
+ GetDisplayService()->RemoveNotification(
+ NotificationCommon::EXTENSION, notification_id, true /* by_user */);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
{
ResultCatcher catcher;
- g_browser_process->message_center()->RemoveAllNotifications(
- false /* by_user */, message_center::MessageCenter::RemoveType::ALL);
+ GetDisplayService()->RemoveAllNotifications(NotificationCommon::EXTENSION,
+ false /* by_user */);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
{
ResultCatcher catcher;
- g_browser_process->message_center()->RemoveAllNotifications(
- true /* by_user */, message_center::MessageCenter::RemoveType::ALL);
+ GetDisplayService()->RemoveAllNotifications(NotificationCommon::EXTENSION,
+ true /* by_user */);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
}
@@ -254,11 +291,8 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestPartialUpdate) {
int kNewPriority = 2;
const char kButtonTitle[] = "NewButton";
- const message_center::NotificationList::Notifications& notifications =
- g_browser_process->message_center()->GetVisibleNotifications();
- ASSERT_EQ(1u, notifications.size());
- message_center::Notification* notification = *(notifications.begin());
- ASSERT_EQ(extension->url(), notification->origin_url());
+ Notification* notification = GetNotificationForExtension(extension);
+ ASSERT_TRUE(notification);
LOG(INFO) << "Notification ID: " << notification->id();
@@ -303,9 +337,7 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestGetPermissionLevel) {
message_center::NotifierId notifier_id(
message_center::NotifierId::APPLICATION,
empty_extension->id());
- message_center::Notifier notifier(notifier_id, base::string16(), true);
- g_browser_process->message_center()->GetNotifierSettingsProvider()->
- SetNotifierEnabled(notifier, false);
+ GetNotifierStateTracker()->SetNotifierEnabled(notifier_id, false);
std::unique_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
notification_function.get(), "[]", browser(), utils::NONE));
@@ -329,9 +361,7 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestOnPermissionLevelChanged) {
message_center::NotifierId notifier_id(
message_center::NotifierId::APPLICATION,
extension->id());
- message_center::Notifier notifier(notifier_id, base::string16(), true);
- g_browser_process->message_center()->GetNotifierSettingsProvider()->
- SetNotifierEnabled(notifier, false);
+ GetNotifierStateTracker()->SetNotifierEnabled(notifier_id, false);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
@@ -343,9 +373,7 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestOnPermissionLevelChanged) {
message_center::NotifierId notifier_id(
message_center::NotifierId::APPLICATION,
extension->id());
- message_center::Notifier notifier(notifier_id, base::string16(), false);
- g_browser_process->message_center()->GetNotifierSettingsProvider()->
- SetNotifierEnabled(notifier, true);
+ GetNotifierStateTracker()->SetNotifierEnabled(notifier_id, true);
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
@@ -356,11 +384,8 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestUserGesture) {
LoadExtensionAndWait("notifications/api/user_gesture");
ASSERT_TRUE(extension) << message_;
- const message_center::NotificationList::Notifications& notifications =
- g_browser_process->message_center()->GetVisibleNotifications();
- ASSERT_EQ(1u, notifications.size());
- message_center::Notification* notification = *(notifications.begin());
- ASSERT_EQ(extension->url(), notification->origin_url());
+ Notification* notification = GetNotificationForExtension(extension);
+ ASSERT_TRUE(notification);
{
UserGestureCatcher catcher;
@@ -368,11 +393,13 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestUserGesture) {
EXPECT_TRUE(catcher.GetNextResult());
notification->Click();
EXPECT_TRUE(catcher.GetNextResult());
- notification->Close(true);
+ notification->Close(true /* by_user */);
EXPECT_TRUE(catcher.GetNextResult());
- notification->Close(false);
- EXPECT_FALSE(catcher.GetNextResult());
+
+ // Note that |notification| no longer points to valid memory.
}
+
+ ASSERT_FALSE(GetNotificationForExtension(extension));
}
IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestRequireInteraction) {
@@ -380,11 +407,8 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestRequireInteraction) {
LoadExtensionAndWait("notifications/api/require_interaction");
ASSERT_TRUE(extension) << message_;
- const message_center::NotificationList::Notifications& notifications =
- g_browser_process->message_center()->GetVisibleNotifications();
- ASSERT_EQ(1u, notifications.size());
- message_center::Notification* notification = *(notifications.begin());
- ASSERT_EQ(extension->url(), notification->origin_url());
+ Notification* notification = GetNotificationForExtension(extension);
+ ASSERT_TRUE(notification);
EXPECT_TRUE(notification->never_timeout());
}
@@ -401,10 +425,9 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestShouldDisplayNormal) {
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
GetFirstAppWindow(extension->id())->GetNativeWindow()));
- const message_center::NotificationList::Notifications& notifications =
- g_browser_process->message_center()->GetVisibleNotifications();
- ASSERT_EQ(1u, notifications.size());
- message_center::Notification* notification = *(notifications.begin());
+ Notification* notification = GetNotificationForExtension(extension);
+ ASSERT_TRUE(notification);
+
// If the app hasn't created a fullscreen window, then its notifications
// shouldn't be displayed when a window is fullscreen.
ASSERT_FALSE(notification->delegate()->ShouldDisplayOverFullscreen());
@@ -430,10 +453,9 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestShouldDisplayFullscreen) {
ASSERT_TRUE(GetFirstAppWindow(extension->id())->GetBaseWindow()->IsActive())
<< "Not Active";
- const message_center::NotificationList::Notifications& notifications =
- g_browser_process->message_center()->GetVisibleNotifications();
- ASSERT_EQ(1u, notifications.size());
- message_center::Notification* notification = *(notifications.begin());
+ Notification* notification = GetNotificationForExtension(extension);
+ ASSERT_TRUE(notification);
+
// If the app has created a fullscreen window, then its notifications should
// be displayed when a window is fullscreen.
ASSERT_TRUE(notification->delegate()->ShouldDisplayOverFullscreen());
@@ -459,10 +481,9 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestShouldDisplayFullscreenOff) {
ASSERT_TRUE(GetFirstAppWindow(extension->id())->GetBaseWindow()->IsActive())
<< "Not Active";
- const message_center::NotificationList::Notifications& notifications =
- g_browser_process->message_center()->GetVisibleNotifications();
- ASSERT_EQ(1u, notifications.size());
- message_center::Notification* notification = *(notifications.begin());
+ Notification* notification = GetNotificationForExtension(extension);
+ ASSERT_TRUE(notification);
+
// When the experiment flag is off, then ShouldDisplayOverFullscreen should
// return false.
ASSERT_FALSE(notification->delegate()->ShouldDisplayOverFullscreen());
@@ -493,10 +514,9 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestShouldDisplayMultiFullscreen) {
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
GetFirstAppWindow(extension2->id())->GetNativeWindow()));
- const message_center::NotificationList::Notifications& notifications =
- g_browser_process->message_center()->GetVisibleNotifications();
- ASSERT_EQ(1u, notifications.size());
- message_center::Notification* notification = *(notifications.begin());
+ Notification* notification = GetNotificationForExtension(extension1);
+ ASSERT_TRUE(notification);
+
// The first app window is superseded by the second window, so its
// notification shouldn't be displayed.
ASSERT_FALSE(notification->delegate()->ShouldDisplayOverFullscreen());
@@ -526,7 +546,10 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest,
ASSERT_TRUE(GetFirstAppWindow(extension->id())->GetBaseWindow()->IsActive())
<< "Not Active";
- const message_center::NotificationList::PopupNotifications notifications =
- g_browser_process->message_center()->GetPopupNotifications();
- ASSERT_EQ(1u, notifications.size());
+ Notification* notification = GetNotificationForExtension(extension);
+ ASSERT_TRUE(notification);
+
+ // The extension's window is being shown and focused, so its expected that
+ // the notification displays on top of it.
+ ASSERT_TRUE(notification->delegate()->ShouldDisplayOverFullscreen());
}
diff --git a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.cc b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.cc
index b98495012a7..91a4bca7515 100644
--- a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.cc
+++ b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.cc
@@ -12,6 +12,7 @@
#include "base/memory/ptr_util.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
@@ -74,10 +75,11 @@ bool SetOmniboxDefaultSuggestion(
std::unique_ptr<base::DictionaryValue> dict = suggestion.ToValue();
// Add the content field so that the dictionary can be used to populate an
// omnibox::SuggestResult.
- dict->SetWithoutPathExpansion(kSuggestionContent, new base::StringValue(""));
- prefs->UpdateExtensionPref(extension_id,
- kOmniboxDefaultSuggestion,
- dict.release());
+ dict->SetWithoutPathExpansion(
+ kSuggestionContent,
+ base::MakeUnique<base::Value>(base::Value::Type::STRING));
+ prefs->UpdateExtensionPref(extension_id, kOmniboxDefaultSuggestion,
+ std::move(dict));
return true;
}
@@ -112,8 +114,8 @@ bool ExtensionOmniboxEventRouter::OnInputChanged(
return false;
std::unique_ptr<base::ListValue> args(new base::ListValue());
- args->Set(0, new base::StringValue(input));
- args->Set(1, new base::Value(suggest_id));
+ args->Set(0, base::MakeUnique<base::Value>(input));
+ args->Set(1, base::MakeUnique<base::Value>(suggest_id));
std::unique_ptr<Event> event = base::MakeUnique<Event>(
events::OMNIBOX_ON_INPUT_CHANGED, omnibox::OnInputChanged::kEventName,
@@ -140,13 +142,13 @@ void ExtensionOmniboxEventRouter::OnInputEntered(
active_tab_permission_granter()->GrantIfRequested(extension);
std::unique_ptr<base::ListValue> args(new base::ListValue());
- args->Set(0, new base::StringValue(input));
+ args->Set(0, base::MakeUnique<base::Value>(input));
if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB)
- args->Set(1, new base::StringValue(kForegroundTabDisposition));
+ args->Set(1, base::MakeUnique<base::Value>(kForegroundTabDisposition));
else if (disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB)
- args->Set(1, new base::StringValue(kBackgroundTabDisposition));
+ args->Set(1, base::MakeUnique<base::Value>(kBackgroundTabDisposition));
else
- args->Set(1, new base::StringValue(kCurrentTabDisposition));
+ args->Set(1, base::MakeUnique<base::Value>(kCurrentTabDisposition));
std::unique_ptr<Event> event = base::MakeUnique<Event>(
events::OMNIBOX_ON_INPUT_ENTERED, omnibox::OnInputEntered::kEventName,
@@ -194,8 +196,9 @@ void OmniboxAPI::Shutdown() {
OmniboxAPI::~OmniboxAPI() {
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<OmniboxAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<OmniboxAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<OmniboxAPI>* OmniboxAPI::GetFactoryInstance() {
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 9fcaabfbfc9..6f389d7b6ef 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
@@ -33,9 +33,8 @@ ExtensionFunction::ResponseAction
PasswordsPrivateDelegate* delegate =
PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
true /* create */);
- delegate->RemoveSavedPassword(
- parameters->login_pair.origin_url,
- parameters->login_pair.username);
+ delegate->RemoveSavedPassword(parameters->login_pair.urls.origin,
+ parameters->login_pair.username);
return RespondNow(NoArguments());
}
@@ -80,7 +79,7 @@ ExtensionFunction::ResponseAction
PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
true /* create */);
- delegate->RequestShowPassword(parameters->login_pair.origin_url,
+ delegate->RequestShowPassword(parameters->login_pair.urls.origin,
parameters->login_pair.username,
GetSenderWebContents());
@@ -145,9 +144,10 @@ void PasswordsPrivateGetPasswordExceptionListFunction::GetList() {
}
void PasswordsPrivateGetPasswordExceptionListFunction::GotList(
- const PasswordsPrivateDelegate::ExceptionPairs& list) {
+ const PasswordsPrivateDelegate::ExceptionEntries& entries) {
Respond(ArgumentList(
- api::passwords_private::GetPasswordExceptionList::Results::Create(list)));
+ api::passwords_private::GetPasswordExceptionList::Results::Create(
+ entries)));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
index 6296e8bbe2b..dab11b9644d 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
@@ -100,7 +100,7 @@ class PasswordsPrivateGetPasswordExceptionListFunction
private:
void GetList();
- void GotList(const PasswordsPrivateDelegate::ExceptionPairs& pairs);
+ void GotList(const PasswordsPrivateDelegate::ExceptionEntries& entries);
DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateGetPasswordExceptionListFunction);
};
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 6ab38ffe123..b00abdba45b 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
@@ -33,25 +33,20 @@ static const char kPlaintextPassword[] = "plaintext";
api::passwords_private::PasswordUiEntry CreateEntry(size_t num) {
api::passwords_private::PasswordUiEntry entry;
- std::stringstream ss;
- ss << "http://test" << num << ".com";
- entry.login_pair.origin_url = ss.str();
- ss << "/login";
- entry.link_url = ss.str();
- ss.clear();
- ss << "testName" << num;
- entry.login_pair.username = ss.str();
+ entry.login_pair.urls.shown = "test" + std::to_string(num) + ".com";
+ entry.login_pair.urls.origin =
+ "http://" + entry.login_pair.urls.shown + "/login";
+ entry.login_pair.urls.link = entry.login_pair.urls.origin;
+ entry.login_pair.username = "testName" + std::to_string(num);
entry.num_characters_in_password = kNumCharactersInPassword;
return entry;
}
-api::passwords_private::ExceptionPair CreateException(size_t num) {
- api::passwords_private::ExceptionPair exception;
- std::stringstream ss;
- ss << "http://exception" << num << ".com";
- exception.exception_url = ss.str();
- ss << "/login";
- exception.link_url = ss.str();
+api::passwords_private::ExceptionEntry CreateException(size_t num) {
+ api::passwords_private::ExceptionEntry exception;
+ exception.urls.shown = "exception" + std::to_string(num) + ".com";
+ exception.urls.origin = "http://" + exception.urls.shown + "/login";
+ exception.urls.link = exception.urls.origin;
return exception;
}
@@ -89,12 +84,12 @@ class TestDelegate : public PasswordsPrivateDelegate {
}
void GetPasswordExceptionsList(
- const ExceptionPairsCallback& callback) override {
+ const ExceptionEntriesCallback& callback) override {
callback.Run(current_exceptions_);
}
- void RemoveSavedPassword(
- const std::string& origin_url, const std::string& username) override {
+ void RemoveSavedPassword(const std::string& origin,
+ const std::string& username) override {
if (current_entries_.empty())
return;
@@ -114,7 +109,7 @@ class TestDelegate : public PasswordsPrivateDelegate {
SendPasswordExceptionsList();
}
- void RequestShowPassword(const std::string& origin_url,
+ void RequestShowPassword(const std::string& origin,
const std::string& username,
content::WebContents* web_contents) override {
// Return a mocked password value.
@@ -122,8 +117,7 @@ class TestDelegate : public PasswordsPrivateDelegate {
PasswordsPrivateEventRouter* router =
PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
if (router) {
- router->OnPlaintextPasswordFetched(origin_url, username,
- plaintext_password);
+ router->OnPlaintextPasswordFetched(origin, username, plaintext_password);
}
}
@@ -134,7 +128,7 @@ class TestDelegate : public PasswordsPrivateDelegate {
// observers are added, this delegate can send the current lists without
// having to request them from |password_manager_presenter_| again.
std::vector<api::passwords_private::PasswordUiEntry> current_entries_;
- std::vector<api::passwords_private::ExceptionPair> current_exceptions_;
+ std::vector<api::passwords_private::ExceptionEntry> current_exceptions_;
Profile* profile_;
};
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 0cb1e04da72..15cfac7d522 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
@@ -44,10 +44,11 @@ class PasswordsPrivateDelegate : public KeyedService {
virtual void SendPasswordExceptionsList() = 0;
// Gets the password exceptions list.
- using ExceptionPairs = std::vector<api::passwords_private::ExceptionPair>;
- using ExceptionPairsCallback = base::Callback<void(const ExceptionPairs&)>;
+ using ExceptionEntries = std::vector<api::passwords_private::ExceptionEntry>;
+ using ExceptionEntriesCallback =
+ base::Callback<void(const ExceptionEntries&)>;
virtual void GetPasswordExceptionsList(
- const ExceptionPairsCallback& callback) = 0;
+ const ExceptionEntriesCallback& callback) = 0;
// Removes the saved password entry corresponding to |origin_url| and
// |username|.
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 ee744580d82..e942112a110 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
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
@@ -13,20 +14,66 @@
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/password_manager/core/browser/affiliation_utils.h"
+#include "components/password_manager/core/browser/password_ui_utils.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
-std::string LoginPairToMapKey(
- const std::string& origin_url, const std::string& username) {
+const char kAndroidAppScheme[] = "android://";
+const char kPlayStoreAppPrefix[] =
+ "https://play.google.com/store/apps/details?id=";
+
+std::string LoginPairToMapKey(const std::string& origin_url,
+ const std::string& username) {
// Concatenate origin URL and username to form a unique key.
return origin_url + ',' + username;
}
+// Conveniece struct that mirrors the UrlCollection dictionary in
+// passwords_private.idl.
+struct URLs {
+ std::string origin;
+ std::string shown;
+ std::string link;
+};
+
+// Obtains origin and link URL from the passed in form. In case the origin
+// corresponds to the identifier of an Android app, it tries to create a human
+// readable version of the origin URL.
+URLs CreateURLFromForm(const autofill::PasswordForm& form) {
+ bool is_android_uri = false;
+ GURL link_url;
+ bool origin_is_clickable = false;
+ std::string shown_url = password_manager::GetShownOriginAndLinkUrl(
+ form, &is_android_uri, &link_url, &origin_is_clickable);
+ std::string link_str = link_url.spec();
+
+ if (is_android_uri) {
+ if (!origin_is_clickable) {
+ // e.g. android://com.example.r => r.example.com.
+ shown_url = password_manager::StripAndroidAndReverse(shown_url);
+ // Turn human unfriendly string into a clickable link to the PlayStore.
+ base::ReplaceFirstSubstringAfterOffset(&link_str, 0, kAndroidAppScheme,
+ kPlayStoreAppPrefix);
+ }
+
+ // Currently we use "direction=rtl" in CSS to elide long origins from the
+ // left. This does not play nice with appending strings that end in
+ // punctuation symbols, which is why the bidirectional override tag is
+ // necessary.
+ // TODO(crbug.com/679434): Clean this up.
+ shown_url += "\u202D" + // equivalent to <bdo dir = "ltr">
+ l10n_util::GetStringUTF8(IDS_PASSWORDS_ANDROID_URI_SUFFIX) +
+ "\u202C"; // equivalent to </bdo>
+ }
+
+ return {form.signon_realm, shown_url, link_str};
}
+} // namespace
+
namespace extensions {
PasswordsPrivateDelegateImpl::PasswordsPrivateDelegateImpl(Profile* profile)
@@ -65,7 +112,7 @@ void PasswordsPrivateDelegateImpl::SendPasswordExceptionsList() {
}
void PasswordsPrivateDelegateImpl::GetPasswordExceptionsList(
- const ExceptionPairsCallback& callback) {
+ const ExceptionEntriesCallback& callback) {
if (current_exceptions_initialized_)
callback.Run(current_exceptions_);
else
@@ -166,22 +213,22 @@ void PasswordsPrivateDelegateImpl::SetPasswordList(
const std::vector<std::unique_ptr<autofill::PasswordForm>>& password_list) {
// Rebuild |login_pair_to_index_map_| so that it reflects the contents of the
// new list.
+ // Also, create a list of PasswordUiEntry objects to send to observers.
login_pair_to_index_map_.clear();
+ current_entries_.clear();
+
for (size_t i = 0; i < password_list.size(); i++) {
- std::string key = LoginPairToMapKey(
- password_manager::GetHumanReadableOrigin(*password_list[i]),
- base::UTF16ToUTF8(password_list[i]->username_value));
+ const auto& form = password_list[i];
+ URLs urls = CreateURLFromForm(*form);
+ std::string key =
+ LoginPairToMapKey(urls.origin, base::UTF16ToUTF8(form->username_value));
login_pair_to_index_map_[key] = i;
- }
- // Now, create a list of PasswordUiEntry objects to send to observers.
- current_entries_.clear();
- for (const auto& form : password_list) {
api::passwords_private::PasswordUiEntry entry;
- entry.login_pair.origin_url =
- password_manager::GetHumanReadableOrigin(*form);
+ entry.login_pair.urls.origin = std::move(urls.origin);
+ entry.login_pair.urls.shown = std::move(urls.shown);
+ entry.login_pair.urls.link = std::move(urls.link);
entry.login_pair.username = base::UTF16ToUTF8(form->username_value);
- entry.link_url = form->origin.spec();
entry.num_characters_in_password = form->password_value.length();
if (!form->federation_origin.unique()) {
@@ -211,20 +258,20 @@ void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
password_exception_list) {
// Rebuild |exception_url_to_index_map_| so that it reflects the contents of
// the new list.
+ // Also, create a list of exceptions to send to observers.
exception_url_to_index_map_.clear();
- for (size_t i = 0; i < password_exception_list.size(); i++) {
- std::string key = password_manager::GetHumanReadableOrigin(
- *password_exception_list[i]);
- exception_url_to_index_map_[key] = i;
- }
-
- // Now, create a list of exceptions to send to observers.
current_exceptions_.clear();
- for (const auto& form : password_exception_list) {
- api::passwords_private::ExceptionPair pair;
- pair.exception_url = password_manager::GetHumanReadableOrigin(*form);
- pair.link_url = form->origin.spec();
- current_exceptions_.push_back(std::move(pair));
+
+ for (size_t i = 0; i < password_exception_list.size(); i++) {
+ const auto& form = password_exception_list[i];
+ URLs urls = CreateURLFromForm(*form);
+ exception_url_to_index_map_[urls.origin] = i;
+
+ api::passwords_private::ExceptionEntry current_exception_entry;
+ current_exception_entry.urls.origin = std::move(urls.origin);
+ current_exception_entry.urls.shown = std::move(urls.shown);
+ current_exception_entry.urls.link = std::move(urls.link);
+ current_exceptions_.push_back(std::move(current_exception_entry));
}
SendPasswordExceptionsList();
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 830e8ba9a98..842eb52a8be 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
@@ -43,7 +43,7 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
void GetSavedPasswordsList(const UiEntriesCallback& callback) override;
void SendPasswordExceptionsList() override;
void GetPasswordExceptionsList(
- const ExceptionPairsCallback& callback) override;
+ const ExceptionEntriesCallback& callback) override;
void RemoveSavedPassword(
const std::string& origin_url, const std::string& username) override;
void RemovePasswordException(const std::string& exception_url) override;
@@ -98,7 +98,7 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
// observers are added, this delegate can send the current lists without
// having to request them from |password_manager_presenter_| again.
UiEntries current_entries_;
- ExceptionPairs current_exceptions_;
+ ExceptionEntries current_exceptions_;
// Whether SetPasswordList and SetPasswordExceptionList have been called, and
// whether this class has been initialized, meaning both have been called.
@@ -112,7 +112,7 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
// callbacks are invoked.
std::vector<base::Closure> pre_initialization_callbacks_;
std::vector<UiEntriesCallback> get_saved_passwords_list_callbacks_;
- std::vector<ExceptionPairsCallback> get_password_exception_list_callbacks_;
+ std::vector<ExceptionEntriesCallback> get_password_exception_list_callbacks_;
// The WebContents used when invoking this API. Used to fetch the
// NativeWindow for the window where the API was 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 87e1a39c2ca..c8dba57cd2e 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
@@ -63,7 +63,7 @@ TEST(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {
}
TEST(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
- CallbackTracker<PasswordsPrivateDelegate::ExceptionPairs> tracker;
+ CallbackTracker<PasswordsPrivateDelegate::ExceptionEntries> tracker;
content::TestBrowserThreadBundle thread_bundle;
TestingProfile profile;
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
index 11ab3e01a77..380e99ac88b 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "content/public/browser/browser_context.h"
+#include "url/gurl.h"
namespace extensions {
@@ -49,7 +50,7 @@ void PasswordsPrivateEventRouter::SendSavedPasswordListToListeners() {
}
void PasswordsPrivateEventRouter::OnPasswordExceptionsListChanged(
- const std::vector<api::passwords_private::ExceptionPair>& exceptions) {
+ const std::vector<api::passwords_private::ExceptionEntry>& exceptions) {
cached_password_exception_parameters_ =
api::passwords_private::OnPasswordExceptionsListChanged::Create(
exceptions);
@@ -73,7 +74,8 @@ void PasswordsPrivateEventRouter::OnPlaintextPasswordFetched(
const std::string& username,
const std::string& plaintext_password) {
api::passwords_private::PlaintextPasswordEventParameters params;
- params.login_pair.origin_url = origin_url;
+ // TODO(crbug.com/715866): use origins and URLs more consistently.
+ params.login_pair.urls.origin = GURL(origin_url).GetOrigin().spec();
params.login_pair.username = username;
params.plaintext_password = plaintext_password;
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
index c1846732255..5ea04d7a8da 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
@@ -33,7 +33,7 @@ class PasswordsPrivateEventRouter : public KeyedService {
// Notifies listeners of updated exceptions.
// |exceptions| The new list of password exceptions.
void OnPasswordExceptionsListChanged(
- const std::vector<api::passwords_private::ExceptionPair>& exceptions);
+ const std::vector<api::passwords_private::ExceptionEntry>& exceptions);
// Notifies listeners after fetching a plain-text password.
// |origin_url| The origin which the password is saved for.
diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
index 170a37fabf0..b99b3efc0c3 100644
--- a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
@@ -7,8 +7,10 @@
#include <stddef.h>
#include <memory>
+#include <utility>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chrome/common/extensions/api/permissions.h"
#include "extensions/common/permissions/permission_set.h"
@@ -58,14 +60,13 @@ TEST(ExtensionPermissionsAPIHelpers, Pack) {
std::string expected_apis[] = {"tabs", "fileBrowserHandler",
"fileBrowserHandlerInternal"};
for (size_t i = 0; i < arraysize(expected_apis); ++i) {
- std::unique_ptr<base::Value> value(new base::StringValue(expected_apis[i]));
+ std::unique_ptr<base::Value> value(new base::Value(expected_apis[i]));
EXPECT_NE(api_list->end(), api_list->Find(*value));
}
std::string expected_origins[] = { "http://a.com/*", "http://b.com/*" };
for (size_t i = 0; i < arraysize(expected_origins); ++i) {
- std::unique_ptr<base::Value> value(
- new base::StringValue(expected_origins[i]));
+ std::unique_ptr<base::Value> value(new base::Value(expected_origins[i]));
EXPECT_NE(origin_list->end(), origin_list->Find(*value));
}
@@ -96,7 +97,7 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack) {
// Origins shouldn't have to be present.
{
Permissions permissions_object;
- value->Set("permissions", apis->DeepCopy());
+ value->Set("permissions", apis->CreateDeepCopy());
EXPECT_TRUE(Permissions::Populate(*value, &permissions_object));
permissions = UnpackPermissionSet(permissions_object, true, &error);
EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kTab));
@@ -108,7 +109,7 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack) {
{
Permissions permissions_object;
value->Clear();
- value->Set("origins", origins->DeepCopy());
+ value->Set("origins", origins->CreateDeepCopy());
EXPECT_TRUE(Permissions::Populate(*value, &permissions_object));
permissions = UnpackPermissionSet(permissions_object, true, &error);
EXPECT_TRUE(permissions.get());
@@ -120,9 +121,9 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack) {
{
Permissions permissions_object;
value->Clear();
- std::unique_ptr<base::ListValue> invalid_apis(apis->DeepCopy());
+ std::unique_ptr<base::ListValue> invalid_apis = apis->CreateDeepCopy();
invalid_apis->AppendInteger(3);
- value->Set("permissions", invalid_apis->DeepCopy());
+ value->Set("permissions", std::move(invalid_apis));
EXPECT_FALSE(Permissions::Populate(*value, &permissions_object));
}
@@ -130,9 +131,10 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack) {
{
Permissions permissions_object;
value->Clear();
- std::unique_ptr<base::ListValue> invalid_origins(origins->DeepCopy());
+ std::unique_ptr<base::ListValue> invalid_origins =
+ origins->CreateDeepCopy();
invalid_origins->AppendInteger(3);
- value->Set("origins", invalid_origins->DeepCopy());
+ value->Set("origins", std::move(invalid_origins));
EXPECT_FALSE(Permissions::Populate(*value, &permissions_object));
}
@@ -140,14 +142,14 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack) {
{
Permissions permissions_object;
value->Clear();
- value->Set("origins", new base::Value(2));
+ value->Set("origins", base::MakeUnique<base::Value>(2));
EXPECT_FALSE(Permissions::Populate(*value, &permissions_object));
}
{
Permissions permissions_object;
value->Clear();
- value->Set("permissions", new base::Value(2));
+ value->Set("permissions", base::MakeUnique<base::Value>(2));
EXPECT_FALSE(Permissions::Populate(*value, &permissions_object));
}
@@ -155,8 +157,8 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack) {
{
Permissions permissions_object;
value->Clear();
- value->Set("origins", origins->DeepCopy());
- value->Set("random", new base::Value(3));
+ value->Set("origins", origins->CreateDeepCopy());
+ value->Set("random", base::MakeUnique<base::Value>(3));
EXPECT_TRUE(Permissions::Populate(*value, &permissions_object));
permissions = UnpackPermissionSet(permissions_object, true, &error);
EXPECT_TRUE(permissions.get());
@@ -168,9 +170,9 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack) {
{
Permissions permissions_object;
value->Clear();
- std::unique_ptr<base::ListValue> invalid_apis(apis->DeepCopy());
+ std::unique_ptr<base::ListValue> invalid_apis = apis->CreateDeepCopy();
invalid_apis->AppendString("unknown_permission");
- value->Set("permissions", invalid_apis->DeepCopy());
+ value->Set("permissions", std::move(invalid_apis));
EXPECT_TRUE(Permissions::Populate(*value, &permissions_object));
permissions = UnpackPermissionSet(permissions_object, true, &error);
EXPECT_FALSE(permissions.get());
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 cd818aef348..cada03f3bce 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
@@ -65,7 +65,7 @@ void BuildWebCryptoRSAAlgorithmDictionary(const PublicKeyInfo& key_info,
const unsigned char defaultPublicExponent[] = {0x01, 0x00, 0x01};
algorithm->SetWithoutPathExpansion(
"publicExponent",
- base::BinaryValue::CreateWithCopiedBuffer(
+ base::Value::CreateWithCopiedBuffer(
reinterpret_cast<const char*>(defaultPublicExponent),
arraysize(defaultPublicExponent)));
}
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 2a8a5a44605..341df18ff3a 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
@@ -5,6 +5,7 @@
#include <cryptohi.h>
#include <memory>
+#include <utility>
#include "base/json/json_writer.h"
#include "base/macros.h"
@@ -197,7 +198,7 @@ class PlatformKeysTest : public ExtensionApiTest {
cert1_key_permission->SetBooleanWithoutPathExpansion(
"allowCorporateKeyUsage", true);
key_permissions_policy.SetWithoutPathExpansion(
- extension_->id(), cert1_key_permission.release());
+ extension_->id(), std::move(cert1_key_permission));
}
std::string key_permissions_policy_str;
diff --git a/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting.cc b/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting.cc
index a612d302aaf..db511d051b8 100644
--- a/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting.cc
+++ b/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting.cc
@@ -39,7 +39,7 @@ ExtensionFunction::ResponseAction GetDirectSettingFunction::Run() {
const base::Value* value = preference->GetValue();
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
- result->Set(preference_api_constants::kValue, value->DeepCopy());
+ result->Set(preference_api_constants::kValue, value->CreateDeepCopy());
return RespondNow(OneArgument(std::move(result)));
}
diff --git a/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc b/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc
index 36e86c67ade..5bf1d8f7a02 100644
--- a/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc
+++ b/chromium/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc
@@ -76,12 +76,12 @@ class PreferenceWhitelist {
DISALLOW_COPY_AND_ASSIGN(PreferenceWhitelist);
};
-base::LazyInstance<PreferenceWhitelist> preference_whitelist =
+base::LazyInstance<PreferenceWhitelist>::DestructorAtExit preference_whitelist =
LAZY_INSTANCE_INITIALIZER;
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<ChromeDirectSettingAPI> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<ChromeDirectSettingAPI>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
ChromeDirectSettingAPI::ChromeDirectSettingAPI(content::BrowserContext* context)
: profile_(Profile::FromBrowserContext(context)) {
@@ -137,7 +137,7 @@ void ChromeDirectSettingAPI::OnPrefChanged(
const base::Value* value = preference->GetValue();
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
- result->Set(preference_api_constants::kValue, value->DeepCopy());
+ result->Set(preference_api_constants::kValue, value->CreateDeepCopy());
base::ListValue args;
args.Append(std::move(result));
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_api.cc b/chromium/chrome/browser/extensions/api/preference/preference_api.cc
index 5e7b59182ca..cf3b12df99d 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_api.cc
@@ -171,62 +171,68 @@ PrefMappingEntry kPrefMapping[] = {
class IdentityPrefTransformer : public PrefTransformerInterface {
public:
- base::Value* ExtensionToBrowserPref(const base::Value* extension_pref,
- std::string* error,
- bool* bad_message) override {
- return extension_pref->DeepCopy();
+ std::unique_ptr<base::Value> ExtensionToBrowserPref(
+ const base::Value* extension_pref,
+ std::string* error,
+ bool* bad_message) override {
+ return extension_pref->CreateDeepCopy();
}
- base::Value* BrowserToExtensionPref(
+ std::unique_ptr<base::Value> BrowserToExtensionPref(
const base::Value* browser_pref) override {
- return browser_pref->DeepCopy();
+ return browser_pref->CreateDeepCopy();
}
};
class InvertBooleanTransformer : public PrefTransformerInterface {
public:
- base::Value* ExtensionToBrowserPref(const base::Value* extension_pref,
- std::string* error,
- bool* bad_message) override {
+ std::unique_ptr<base::Value> ExtensionToBrowserPref(
+ const base::Value* extension_pref,
+ std::string* error,
+ bool* bad_message) override {
return InvertBooleanValue(extension_pref);
}
- base::Value* BrowserToExtensionPref(
+ std::unique_ptr<base::Value> BrowserToExtensionPref(
const base::Value* browser_pref) override {
return InvertBooleanValue(browser_pref);
}
private:
- static base::Value* InvertBooleanValue(const base::Value* value) {
+ static std::unique_ptr<base::Value> InvertBooleanValue(
+ const base::Value* value) {
bool bool_value = false;
bool result = value->GetAsBoolean(&bool_value);
DCHECK(result);
- return new base::Value(!bool_value);
+ return base::MakeUnique<base::Value>(!bool_value);
}
};
class NetworkPredictionTransformer : public PrefTransformerInterface {
public:
- base::Value* ExtensionToBrowserPref(const base::Value* extension_pref,
- std::string* error,
- bool* bad_message) override {
+ std::unique_ptr<base::Value> ExtensionToBrowserPref(
+ const base::Value* extension_pref,
+ std::string* error,
+ bool* bad_message) override {
bool bool_value = false;
const bool pref_found = extension_pref->GetAsBoolean(&bool_value);
DCHECK(pref_found) << "Preference not found.";
if (bool_value) {
- return new base::Value(chrome_browser_net::NETWORK_PREDICTION_DEFAULT);
+ return base::MakeUnique<base::Value>(
+ chrome_browser_net::NETWORK_PREDICTION_DEFAULT);
} else {
- return new base::Value(chrome_browser_net::NETWORK_PREDICTION_NEVER);
+ return base::MakeUnique<base::Value>(
+ chrome_browser_net::NETWORK_PREDICTION_NEVER);
}
}
- base::Value* BrowserToExtensionPref(
+ std::unique_ptr<base::Value> BrowserToExtensionPref(
const base::Value* browser_pref) override {
int int_value = chrome_browser_net::NETWORK_PREDICTION_DEFAULT;
const bool pref_found = browser_pref->GetAsInteger(&int_value);
DCHECK(pref_found) << "Preference not found.";
- return new base::Value(int_value !=
- chrome_browser_net::NETWORK_PREDICTION_NEVER);
+ return base::MakeUnique<base::Value>(
+ int_value != chrome_browser_net::NETWORK_PREDICTION_NEVER);
}
};
@@ -381,11 +387,11 @@ void PreferenceEventRouter::OnPrefChanged(PrefService* pref_service,
base::ListValue args;
const PrefService::Preference* pref =
- pref_service->FindPreference(browser_pref.c_str());
+ pref_service->FindPreference(browser_pref);
CHECK(pref);
PrefTransformerInterface* transformer =
PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
- base::Value* transformed_value =
+ std::unique_ptr<base::Value> transformed_value =
transformer->BrowserToExtensionPref(pref->GetValue());
if (!transformed_value) {
LOG(ERROR) << ErrorUtils::FormatErrorMessage(kConversionErrorMessage,
@@ -394,7 +400,7 @@ void PreferenceEventRouter::OnPrefChanged(PrefService* pref_service,
}
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->Set(keys::kValue, transformed_value);
+ dict->Set(keys::kValue, std::move(transformed_value));
if (incognito) {
ExtensionPrefs* ep = ExtensionPrefs::Get(profile_);
dict->SetBoolean(keys::kIncognitoSpecific,
@@ -425,7 +431,7 @@ void PreferenceAPIBase::SetExtensionControlledPref(
base::Value* value) {
#ifndef NDEBUG
const PrefService::Preference* pref =
- extension_prefs()->pref_service()->FindPreference(pref_key.c_str());
+ extension_prefs()->pref_service()->FindPreference(pref_key);
DCHECK(pref) << "Extension controlled preference key " << pref_key
<< " not registered.";
DCHECK_EQ(pref->GetType(), value->GetType())
@@ -443,7 +449,7 @@ void PreferenceAPIBase::SetExtensionControlledPref(
base::DictionaryValue* preference = update.Get();
if (!preference)
preference = update.Create();
- preference->SetWithoutPathExpansion(pref_key, value->DeepCopy());
+ preference->SetWithoutPathExpansion(pref_key, value->CreateDeepCopy());
}
extension_pref_value_map()->SetExtensionPref(
extension_id, pref_key, scope, value);
@@ -453,7 +459,7 @@ void PreferenceAPIBase::RemoveExtensionControlledPref(
const std::string& extension_id,
const std::string& pref_key,
ExtensionPrefsScope scope) {
- DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str()))
+ DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key))
<< "Extension controlled preference key " << pref_key
<< " not registered.";
@@ -474,7 +480,7 @@ bool PreferenceAPIBase::CanExtensionControlPref(
const std::string& extension_id,
const std::string& pref_key,
bool incognito) {
- DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str()))
+ DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key))
<< "Extension controlled preference key " << pref_key
<< " not registered.";
@@ -486,7 +492,7 @@ bool PreferenceAPIBase::DoesExtensionControlPref(
const std::string& extension_id,
const std::string& pref_key,
bool* from_incognito) {
- DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str()))
+ DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key))
<< "Extension controlled preference key " << pref_key
<< " not registered.";
@@ -517,8 +523,9 @@ void PreferenceAPI::Shutdown() {
content_settings_store()->RemoveObserver(this);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<PreferenceAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<PreferenceAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<PreferenceAPI>*
@@ -616,8 +623,7 @@ ExtensionFunction::ResponseAction GetPreferenceFunction::Run() {
Profile* profile = Profile::FromBrowserContext(browser_context());
PrefService* prefs =
incognito ? profile->GetOffTheRecordPrefs() : profile->GetPrefs();
- const PrefService::Preference* pref =
- prefs->FindPreference(browser_pref.c_str());
+ const PrefService::Preference* pref = prefs->FindPreference(browser_pref);
CHECK(pref);
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue);
@@ -630,7 +636,7 @@ ExtensionFunction::ResponseAction GetPreferenceFunction::Run() {
// Retrieve pref value.
PrefTransformerInterface* transformer =
PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
- base::Value* transformed_value =
+ std::unique_ptr<base::Value> transformed_value =
transformer->BrowserToExtensionPref(pref->GetValue());
if (!transformed_value) {
// TODO(devlin): Can this happen? When? Should it be an error, or a bad
@@ -640,7 +646,7 @@ ExtensionFunction::ResponseAction GetPreferenceFunction::Run() {
pref->name());
return RespondNow(Error(kUnknownErrorDoNotUse));
}
- result->Set(keys::kValue, transformed_value);
+ result->Set(keys::kValue, std::move(transformed_value));
// Retrieve incognito status.
if (incognito) {
@@ -705,7 +711,7 @@ ExtensionFunction::ResponseAction SetPreferenceFunction::Run() {
ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
const PrefService::Preference* pref =
- prefs->pref_service()->FindPreference(browser_pref.c_str());
+ prefs->pref_service()->FindPreference(browser_pref);
CHECK(pref);
// Validate new value.
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_api.h b/chromium/chrome/browser/extensions/api/preference/preference_api.h
index 47d68b4a576..ff72eba7b27 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_api.h
+++ b/chromium/chrome/browser/extensions/api/preference/preference_api.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_PREFERENCE_PREFERENCE_API_H__
#define CHROME_BROWSER_EXTENSIONS_API_PREFERENCE_PREFERENCE_API_H__
+#include <memory>
#include <string>
#include "base/macros.h"
@@ -151,7 +152,7 @@ class PrefTransformerInterface {
// |error| and returns NULL otherwise. |bad_message| is passed to simulate
// the behavior of EXTENSION_FUNCTION_VALIDATE. It is never NULL.
// The ownership of the returned value is passed to the caller.
- virtual base::Value* ExtensionToBrowserPref(
+ virtual std::unique_ptr<base::Value> ExtensionToBrowserPref(
const base::Value* extension_pref,
std::string* error,
bool* bad_message) = 0;
@@ -160,7 +161,7 @@ class PrefTransformerInterface {
// into a representation that is used by the extension.
// Returns the extension representation in case of success or NULL otherwise.
// The ownership of the returned value is passed to the caller.
- virtual base::Value* BrowserToExtensionPref(
+ virtual std::unique_ptr<base::Value> BrowserToExtensionPref(
const base::Value* browser_pref) = 0;
};
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc b/chromium/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc
index a4a893391d4..2c5209a9bb0 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc
@@ -192,9 +192,8 @@ void ExtensionControlledPrefsTest::EnsureExtensionUninstalled(
class ControlledPrefsInstallOneExtension
: public ExtensionControlledPrefsTest {
void Initialize() override {
- InstallExtensionControlledPref(extension1(),
- kPref1,
- new base::StringValue("val1"));
+ InstallExtensionControlledPref(extension1(), kPref1,
+ new base::Value("val1"));
}
void Verify() override {
std::string actual = prefs()->pref_service()->GetString(kPref1);
@@ -209,10 +208,10 @@ class ControlledPrefsInstallIncognitoPersistent
: public ExtensionControlledPrefsTest {
public:
void Initialize() override {
- InstallExtensionControlledPref(
- extension1(), kPref1, new base::StringValue("val1"));
- InstallExtensionControlledPrefIncognito(
- extension1(), kPref1, new base::StringValue("val2"));
+ InstallExtensionControlledPref(extension1(), kPref1,
+ new base::Value("val1"));
+ InstallExtensionControlledPrefIncognito(extension1(), kPref1,
+ new base::Value("val2"));
std::unique_ptr<PrefService> incog_prefs(
prefs_.CreateIncognitoPrefService());
std::string actual = incog_prefs->GetString(kPref1);
@@ -240,10 +239,10 @@ class ControlledPrefsInstallIncognitoSessionOnly
ControlledPrefsInstallIncognitoSessionOnly() : iteration_(0) {}
void Initialize() override {
- InstallExtensionControlledPref(
- extension1(), kPref1, new base::StringValue("val1"));
- InstallExtensionControlledPrefIncognitoSessionOnly(
- extension1(), kPref1, new base::StringValue("val2"));
+ InstallExtensionControlledPref(extension1(), kPref1,
+ new base::Value("val1"));
+ InstallExtensionControlledPrefIncognitoSessionOnly(extension1(), kPref1,
+ new base::Value("val2"));
std::unique_ptr<PrefService> incog_prefs(
prefs_.CreateIncognitoPrefService());
std::string actual = incog_prefs->GetString(kPref1);
@@ -273,10 +272,10 @@ TEST_F(ControlledPrefsInstallIncognitoSessionOnly,
class ControlledPrefsUninstallExtension : public ExtensionControlledPrefsTest {
void Initialize() override {
- InstallExtensionControlledPref(
- extension1(), kPref1, new base::StringValue("val1"));
- InstallExtensionControlledPref(
- extension1(), kPref2, new base::StringValue("val2"));
+ InstallExtensionControlledPref(extension1(), kPref1,
+ new base::Value("val1"));
+ InstallExtensionControlledPref(extension1(), kPref2,
+ new base::Value("val2"));
scoped_refptr<ContentSettingsStore> store = content_settings_store();
ContentSettingsPattern pattern =
ContentSettingsPattern::FromString("http://[*.]example.com");
@@ -325,7 +324,7 @@ class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest {
EXPECT_CALL(observer, OnPreferenceChanged(_));
EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
InstallExtensionControlledPref(extension1(), kPref1,
- new base::StringValue("https://www.chromium.org"));
+ new base::Value("https://www.chromium.org"));
Mock::VerifyAndClearExpectations(&observer);
Mock::VerifyAndClearExpectations(&incognito_observer);
@@ -333,7 +332,7 @@ class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest {
EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)).Times(0);
InstallExtensionControlledPref(extension1(), kPref1,
- new base::StringValue("https://www.chromium.org"));
+ new base::Value("https://www.chromium.org"));
Mock::VerifyAndClearExpectations(&observer);
Mock::VerifyAndClearExpectations(&incognito_observer);
@@ -341,22 +340,22 @@ class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest {
EXPECT_CALL(observer, OnPreferenceChanged(_));
EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
InstallExtensionControlledPref(extension1(), kPref1,
- new base::StringValue("chrome://newtab"));
+ new base::Value("chrome://newtab"));
Mock::VerifyAndClearExpectations(&observer);
Mock::VerifyAndClearExpectations(&incognito_observer);
// Change only incognito persistent value.
EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
- InstallExtensionControlledPrefIncognito(extension1(), kPref1,
- new base::StringValue("chrome://newtab2"));
+ InstallExtensionControlledPrefIncognito(
+ extension1(), kPref1, new base::Value("chrome://newtab2"));
Mock::VerifyAndClearExpectations(&observer);
Mock::VerifyAndClearExpectations(&incognito_observer);
// Change only incognito session-only value.
EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
- InstallExtensionControlledPrefIncognito(extension1(), kPref1,
- new base::StringValue("chrome://newtab3"));
+ InstallExtensionControlledPrefIncognito(
+ extension1(), kPref1, new base::Value("chrome://newtab3"));
Mock::VerifyAndClearExpectations(&observer);
Mock::VerifyAndClearExpectations(&incognito_observer);
@@ -381,8 +380,8 @@ TEST_F(ControlledPrefsNotifyWhenNeeded,
// Tests disabling an extension.
class ControlledPrefsDisableExtension : public ExtensionControlledPrefsTest {
void Initialize() override {
- InstallExtensionControlledPref(
- extension1(), kPref1, new base::StringValue("val1"));
+ InstallExtensionControlledPref(extension1(), kPref1,
+ new base::Value("val1"));
std::string actual = prefs()->pref_service()->GetString(kPref1);
EXPECT_EQ("val1", actual);
prefs()->SetExtensionDisabled(extension1()->id(),
@@ -398,8 +397,8 @@ TEST_F(ControlledPrefsDisableExtension, ControlledPrefsDisableExtension) { }
// Tests disabling and reenabling an extension.
class ControlledPrefsReenableExtension : public ExtensionControlledPrefsTest {
void Initialize() override {
- InstallExtensionControlledPref(
- extension1(), kPref1, new base::StringValue("val1"));
+ InstallExtensionControlledPref(extension1(), kPref1,
+ new base::Value("val1"));
prefs()->SetExtensionDisabled(extension1()->id(),
Extension::DISABLE_USER_ACTION);
prefs()->SetExtensionEnabled(extension1()->id());
@@ -415,10 +414,10 @@ class ControlledPrefsSetExtensionControlledPref
: public ExtensionControlledPrefsTest {
public:
void Initialize() override {
- base::StringValue* v1 = new base::StringValue("https://www.chromium.org");
- base::StringValue* v2 = new base::StringValue("https://www.chromium.org");
- base::StringValue* v1i = new base::StringValue("https://www.chromium.org");
- base::StringValue* v2i = new base::StringValue("https://www.chromium.org");
+ base::Value* v1 = new base::Value("https://www.chromium.org");
+ base::Value* v2 = new base::Value("https://www.chromium.org");
+ base::Value* v1i = new base::Value("https://www.chromium.org");
+ base::Value* v2i = new base::Value("https://www.chromium.org");
// Ownership is taken, value shall not be deleted.
InstallExtensionControlledPref(extension1(), kPref1, v1);
InstallExtensionControlledPrefIncognito(extension1(), kPref1, v1i);
@@ -441,8 +440,8 @@ class ControlledPrefsDisableExtensions : public ExtensionControlledPrefsTest {
: iteration_(0) {}
~ControlledPrefsDisableExtensions() override {}
void Initialize() override {
- InstallExtensionControlledPref(
- extension1(), kPref1, new base::StringValue("val1"));
+ InstallExtensionControlledPref(extension1(), kPref1,
+ new base::Value("val1"));
// This becomes only active in the second verification phase.
prefs_.set_extensions_disabled(true);
}
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_helpers.cc b/chromium/chrome/browser/extensions/api/preference/preference_helpers.cc
index e2b3577cbe5..2361270a861 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_helpers.cc
@@ -15,6 +15,7 @@
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_util.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
#include "extensions/common/permissions/permissions_data.h"
@@ -61,8 +62,7 @@ const char* GetLevelOfControl(
: profile->GetPrefs();
bool from_incognito = false;
bool* from_incognito_ptr = incognito ? &from_incognito : NULL;
- const PrefService::Preference* pref =
- prefs->FindPreference(browser_pref.c_str());
+ const PrefService::Preference* pref = prefs->FindPreference(browser_pref);
CHECK(pref);
if (!pref->IsExtensionModifiable())
diff --git a/chromium/chrome/browser/extensions/api/processes/processes_api.cc b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
index 1a928f56324..910f103b21b 100644
--- a/chromium/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
@@ -37,8 +37,8 @@ const char kInvalidArgument[] = "Invalid argument: *.";
namespace {
-base::LazyInstance<BrowserContextKeyedAPIFactory<ProcessesAPI>>
- g_processes_api_factory = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<BrowserContextKeyedAPIFactory<ProcessesAPI>>::
+ DestructorAtExit g_processes_api_factory = LAZY_INSTANCE_INITIALIZER;
int64_t GetRefreshTypesFlagOnlyEssentialData() {
// This is the only non-optional data in the Process as defined by the API in
@@ -160,7 +160,7 @@ void FillProcessData(
if (task_manager->GetWebCacheStats(id, &cache_stats)) {
out_process->image_cache = CreateCacheData(cache_stats.images);
out_process->script_cache = CreateCacheData(cache_stats.scripts);
- out_process->css_cache = CreateCacheData(cache_stats.cssStyleSheets);
+ out_process->css_cache = CreateCacheData(cache_stats.css_style_sheets);
}
}
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc
index c2ad7f37bb2..4116d9f4f8e 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc
@@ -96,7 +96,7 @@ ProxyPrefTransformer::ProxyPrefTransformer() {
ProxyPrefTransformer::~ProxyPrefTransformer() {
}
-base::Value* ProxyPrefTransformer::ExtensionToBrowserPref(
+std::unique_ptr<base::Value> ProxyPrefTransformer::ExtensionToBrowserPref(
const base::Value* extension_pref,
std::string* error,
bool* bad_message) {
@@ -130,27 +130,28 @@ base::Value* ProxyPrefTransformer::ExtensionToBrowserPref(
config, &proxy_rules_string, error, bad_message) ||
!helpers::GetBypassListFromExtensionPref(
config, &bypass_list, error, bad_message)) {
- return NULL;
+ return nullptr;
}
- return helpers::CreateProxyConfigDict(
- mode_enum, pac_mandatory, pac_url, pac_data, proxy_rules_string,
- bypass_list, error);
+ return helpers::CreateProxyConfigDict(mode_enum, pac_mandatory, pac_url,
+ pac_data, proxy_rules_string,
+ bypass_list, error);
}
-base::Value* ProxyPrefTransformer::BrowserToExtensionPref(
+std::unique_ptr<base::Value> ProxyPrefTransformer::BrowserToExtensionPref(
const base::Value* browser_pref) {
CHECK(browser_pref->IsType(base::Value::Type::DICTIONARY));
// This is a dictionary wrapper that exposes the proxy configuration stored in
// the browser preferences.
ProxyConfigDictionary config(
- static_cast<const base::DictionaryValue*>(browser_pref));
+ static_cast<const base::DictionaryValue*>(browser_pref)
+ ->CreateDeepCopy());
ProxyPrefs::ProxyMode mode;
if (!config.GetMode(&mode)) {
LOG(ERROR) << "Cannot determine proxy mode.";
- return NULL;
+ return nullptr;
}
// Build a new ProxyConfig instance as defined in the extension API.
@@ -172,7 +173,7 @@ base::Value* ProxyPrefTransformer::BrowserToExtensionPref(
// in the extension API.
base::DictionaryValue* pac_dict = helpers::CreatePacScriptDict(config);
if (!pac_dict)
- return NULL;
+ return nullptr;
extension_pref->Set(keys::kProxyConfigPacScript, pac_dict);
break;
}
@@ -181,14 +182,15 @@ base::Value* ProxyPrefTransformer::BrowserToExtensionPref(
base::DictionaryValue* proxy_rules_dict =
helpers::CreateProxyRulesDict(config);
if (!proxy_rules_dict)
- return NULL;
+ return nullptr;
extension_pref->Set(keys::kProxyConfigRules, proxy_rules_dict);
break;
}
case ProxyPrefs::kModeCount:
NOTREACHED();
}
- return extension_pref.release();
+ // TODO(crbug.com/703565): remove std::move() once compiler support improves.
+ return std::move(extension_pref);
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api.h b/chromium/chrome/browser/extensions/api/proxy/proxy_api.h
index f3c3fb5afe3..d10fe758609 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api.h
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api.h
@@ -32,10 +32,12 @@ class ProxyPrefTransformer : public PrefTransformerInterface {
~ProxyPrefTransformer() override;
// Implementation of PrefTransformerInterface.
- base::Value* ExtensionToBrowserPref(const base::Value* extension_pref,
- std::string* error,
- bool* bad_message) override;
- base::Value* BrowserToExtensionPref(const base::Value* browser_pref) override;
+ std::unique_ptr<base::Value> ExtensionToBrowserPref(
+ const base::Value* extension_pref,
+ std::string* error,
+ bool* bad_message) override;
+ std::unique_ptr<base::Value> BrowserToExtensionPref(
+ const base::Value* browser_pref) override;
private:
DISALLOW_COPY_AND_ASSIGN(ProxyPrefTransformer);
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 f22e8b3d513..48b590a2516 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -307,7 +307,7 @@ bool GetBypassListFromExtensionPref(const base::DictionaryValue* proxy_config,
return JoinUrlList(bypass_list, ",", out, error, bad_message);
}
-base::DictionaryValue* CreateProxyConfigDict(
+std::unique_ptr<base::DictionaryValue> CreateProxyConfigDict(
ProxyPrefs::ProxyMode mode_enum,
bool pac_mandatory,
const std::string& pac_url,
@@ -315,7 +315,7 @@ base::DictionaryValue* CreateProxyConfigDict(
const std::string& proxy_rules_string,
const std::string& bypass_list,
std::string* error) {
- base::DictionaryValue* result_proxy_config = NULL;
+ std::unique_ptr<base::DictionaryValue> result_proxy_config;
switch (mode_enum) {
case ProxyPrefs::MODE_DIRECT:
result_proxy_config = ProxyConfigDictionary::CreateDirect();
@@ -330,12 +330,12 @@ base::DictionaryValue* CreateProxyConfigDict(
} else if (!pac_data.empty()) {
if (!CreateDataURLFromPACScript(pac_data, &url)) {
*error = "Internal error, at base64 encoding of 'pacScript.data'.";
- return NULL;
+ return nullptr;
}
} else {
*error = "Proxy mode 'pac_script' requires a 'pacScript' field with "
"either a 'url' field or a 'data' field.";
- return NULL;
+ return nullptr;
}
result_proxy_config =
ProxyConfigDictionary::CreatePacScript(url, pac_mandatory);
@@ -344,7 +344,7 @@ base::DictionaryValue* CreateProxyConfigDict(
case ProxyPrefs::MODE_FIXED_SERVERS: {
if (proxy_rules_string.empty()) {
*error = "Proxy mode 'fixed_servers' requires a 'rules' field.";
- return NULL;
+ return nullptr;
}
result_proxy_config = ProxyConfigDictionary::CreateFixedServers(
proxy_rules_string, bypass_list);
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
index 26b9a9c6efb..f7ee9a2b968 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
@@ -7,6 +7,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_PROXY_PROXY_API_HELPERS_H_
#define CHROME_BROWSER_EXTENSIONS_API_PROXY_PROXY_API_HELPERS_H_
+#include <memory>
#include <string>
#include "components/proxy_config/proxy_prefs.h"
@@ -78,7 +79,7 @@ bool GetBypassListFromExtensionPref(const base::DictionaryValue* proxy_config,
// Creates and returns a ProxyConfig dictionary (as defined in the extension
// API) from the given parameters. Ownership is passed to the caller.
// Depending on the value of |mode_enum|, several of the strings may be empty.
-base::DictionaryValue* CreateProxyConfigDict(
+std::unique_ptr<base::DictionaryValue> CreateProxyConfigDict(
ProxyPrefs::ProxyMode mode_enum,
bool pac_mandatory,
const std::string& pac_url,
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
index 6dcf63a0524..c912ab1ca81 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
@@ -7,7 +7,9 @@
#include "chrome/browser/extensions/api/proxy/proxy_api_helpers.h"
#include <memory>
+#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/proxy/proxy_api_constants.h"
#include "components/proxy_config/proxy_config_dictionary.h"
@@ -29,18 +31,20 @@ const char kSamplePacScriptUrl[] = "http://wpad/wpad.dat";
// Helper function to create a ProxyServer dictionary as defined in the
// extension API.
-base::DictionaryValue* CreateTestProxyServerDict(const std::string& host) {
- base::DictionaryValue* dict = new base::DictionaryValue;
+std::unique_ptr<base::DictionaryValue> CreateTestProxyServerDict(
+ const std::string& host) {
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString(keys::kProxyConfigRuleHost, host);
return dict;
}
// Helper function to create a ProxyServer dictionary as defined in the
// extension API.
-base::DictionaryValue* CreateTestProxyServerDict(const std::string& schema,
- const std::string& host,
- int port) {
- base::DictionaryValue* dict = new base::DictionaryValue;
+std::unique_ptr<base::DictionaryValue> CreateTestProxyServerDict(
+ const std::string& schema,
+ const std::string& host,
+ int port) {
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString(keys::kProxyConfigRuleScheme, schema);
dict->SetString(keys::kProxyConfigRuleHost, host);
dict->SetInteger(keys::kProxyConfigRulePort, port);
@@ -115,9 +119,9 @@ TEST(ExtensionProxyApiHelpers, GetPacUrlFromExtensionPref) {
EXPECT_FALSE(bad_message);
// Set up a pac script.
- base::DictionaryValue* pacScriptDict = new base::DictionaryValue;
+ auto pacScriptDict = base::MakeUnique<base::DictionaryValue>();
pacScriptDict->SetString(keys::kProxyConfigPacScriptUrl, kSamplePacScriptUrl);
- proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict);
+ proxy_config.Set(keys::kProxyConfigPacScript, std::move(pacScriptDict));
ASSERT_TRUE(GetPacUrlFromExtensionPref(&proxy_config, &out, &error,
&bad_message));
@@ -144,9 +148,9 @@ TEST(ExtensionProxyApiHelpers, GetPacDataFromExtensionPref) {
EXPECT_FALSE(bad_message);
// Set up a PAC script.
- base::DictionaryValue* pacScriptDict = new base::DictionaryValue;
+ auto pacScriptDict = base::MakeUnique<base::DictionaryValue>();
pacScriptDict->SetString(keys::kProxyConfigPacScriptData, kSamplePacScript);
- proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict);
+ proxy_config.Set(keys::kProxyConfigPacScript, std::move(pacScriptDict));
ASSERT_TRUE(GetPacDataFromExtensionPref(&proxy_config, &out, &error,
&bad_message));
@@ -173,10 +177,10 @@ TEST(ExtensionProxyApiHelpers, GetProxyRulesStringFromExtensionPref) {
EXPECT_EQ(std::string(), out);
EXPECT_EQ(std::string(), error);
- base::DictionaryValue* proxy_rules = new base::DictionaryValue;
+ auto proxy_rules = base::MakeUnique<base::DictionaryValue>();
proxy_rules->Set(keys::field_name[1], CreateTestProxyServerDict("proxy1"));
proxy_rules->Set(keys::field_name[2], CreateTestProxyServerDict("proxy2"));
- proxy_config.Set(keys::kProxyConfigRules, proxy_rules);
+ proxy_config.Set(keys::kProxyConfigRules, std::move(proxy_rules));
ASSERT_TRUE(
GetProxyRulesStringFromExtensionPref(&proxy_config, &out, &error,
@@ -205,12 +209,12 @@ TEST(ExtensionProxyApiHelpers, GetBypassListFromExtensionPref) {
EXPECT_EQ(std::string(), error);
EXPECT_FALSE(bad_message);
- base::ListValue* bypass_list = new base::ListValue;
+ auto bypass_list = base::MakeUnique<base::ListValue>();
bypass_list->AppendString("host1");
bypass_list->AppendString("host2");
- base::DictionaryValue* proxy_rules = new base::DictionaryValue;
- proxy_rules->Set(keys::kProxyConfigBypassList, bypass_list);
- proxy_config.Set(keys::kProxyConfigRules, proxy_rules);
+ auto proxy_rules = base::MakeUnique<base::DictionaryValue>();
+ proxy_rules->Set(keys::kProxyConfigBypassList, std::move(bypass_list));
+ proxy_config.Set(keys::kProxyConfigRules, std::move(proxy_rules));
ASSERT_TRUE(
GetBypassListFromExtensionPref(&proxy_config, &out, &error,
@@ -222,43 +226,43 @@ TEST(ExtensionProxyApiHelpers, GetBypassListFromExtensionPref) {
TEST(ExtensionProxyApiHelpers, CreateProxyConfigDict) {
std::string error;
- std::unique_ptr<base::DictionaryValue> exp_direct(
- ProxyConfigDictionary::CreateDirect());
+ std::unique_ptr<base::DictionaryValue> exp_direct =
+ ProxyConfigDictionary::CreateDirect();
std::unique_ptr<base::DictionaryValue> out_direct(CreateProxyConfigDict(
ProxyPrefs::MODE_DIRECT, false, std::string(), std::string(),
std::string(), std::string(), &error));
EXPECT_TRUE(base::Value::Equals(exp_direct.get(), out_direct.get()));
- std::unique_ptr<base::DictionaryValue> exp_auto(
- ProxyConfigDictionary::CreateAutoDetect());
+ std::unique_ptr<base::DictionaryValue> exp_auto =
+ ProxyConfigDictionary::CreateAutoDetect();
std::unique_ptr<base::DictionaryValue> out_auto(CreateProxyConfigDict(
ProxyPrefs::MODE_AUTO_DETECT, false, std::string(), std::string(),
std::string(), std::string(), &error));
EXPECT_TRUE(base::Value::Equals(exp_auto.get(), out_auto.get()));
- std::unique_ptr<base::DictionaryValue> exp_pac_url(
- ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
+ std::unique_ptr<base::DictionaryValue> exp_pac_url =
+ ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false);
std::unique_ptr<base::DictionaryValue> out_pac_url(CreateProxyConfigDict(
ProxyPrefs::MODE_PAC_SCRIPT, false, kSamplePacScriptUrl, std::string(),
std::string(), std::string(), &error));
EXPECT_TRUE(base::Value::Equals(exp_pac_url.get(), out_pac_url.get()));
- std::unique_ptr<base::DictionaryValue> exp_pac_data(
- ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
+ std::unique_ptr<base::DictionaryValue> exp_pac_data =
+ ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false);
std::unique_ptr<base::DictionaryValue> out_pac_data(CreateProxyConfigDict(
ProxyPrefs::MODE_PAC_SCRIPT, false, std::string(), kSamplePacScript,
std::string(), std::string(), &error));
EXPECT_TRUE(base::Value::Equals(exp_pac_data.get(), out_pac_data.get()));
- std::unique_ptr<base::DictionaryValue> exp_fixed(
- ProxyConfigDictionary::CreateFixedServers("foo:80", "localhost"));
+ std::unique_ptr<base::DictionaryValue> exp_fixed =
+ ProxyConfigDictionary::CreateFixedServers("foo:80", "localhost");
std::unique_ptr<base::DictionaryValue> out_fixed(CreateProxyConfigDict(
ProxyPrefs::MODE_FIXED_SERVERS, false, std::string(), std::string(),
"foo:80", "localhost", &error));
EXPECT_TRUE(base::Value::Equals(exp_fixed.get(), out_fixed.get()));
- std::unique_ptr<base::DictionaryValue> exp_system(
- ProxyConfigDictionary::CreateSystem());
+ std::unique_ptr<base::DictionaryValue> exp_system =
+ ProxyConfigDictionary::CreateSystem();
std::unique_ptr<base::DictionaryValue> out_system(CreateProxyConfigDict(
ProxyPrefs::MODE_SYSTEM, false, std::string(), std::string(),
std::string(), std::string(), &error));
@@ -312,7 +316,7 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDict) {
ProxyConfigDictionary::CreateFixedServers(
"http=proxy1:80;https=proxy2:80;ftp=proxy3:80;socks=proxy4:80",
"localhost"));
- ProxyConfigDictionary config(browser_pref.get());
+ ProxyConfigDictionary config(std::move(browser_pref));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreateProxyRulesDict(config));
ASSERT_TRUE(extension_pref.get());
@@ -326,9 +330,9 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDict) {
CreateTestProxyServerDict("http", "proxy3", 80));
expected->Set("fallbackProxy",
CreateTestProxyServerDict("socks4", "proxy4", 80));
- base::ListValue* bypass_list = new base::ListValue;
+ auto bypass_list = base::MakeUnique<base::ListValue>();
bypass_list->AppendString("localhost");
- expected->Set(keys::kProxyConfigBypassList, bypass_list);
+ expected->Set(keys::kProxyConfigBypassList, std::move(bypass_list));
EXPECT_TRUE(base::Value::Equals(expected.get(), extension_pref.get()));
}
@@ -340,7 +344,7 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDictMultipleProxies) {
"http=proxy1:80,default://;https=proxy2:80,proxy1:80;ftp=proxy3:80,"
"https://proxy5:443;socks=proxy4:80,proxy1:80",
"localhost"));
- ProxyConfigDictionary config(browser_pref.get());
+ ProxyConfigDictionary config(std::move(browser_pref));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreateProxyRulesDict(config));
ASSERT_TRUE(extension_pref.get());
@@ -354,9 +358,9 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDictMultipleProxies) {
CreateTestProxyServerDict("http", "proxy3", 80));
expected->Set("fallbackProxy",
CreateTestProxyServerDict("socks4", "proxy4", 80));
- base::ListValue* bypass_list = new base::ListValue;
+ auto bypass_list = base::MakeUnique<base::ListValue>();
bypass_list->AppendString("localhost");
- expected->Set(keys::kProxyConfigBypassList, bypass_list);
+ expected->Set(keys::kProxyConfigBypassList, std::move(bypass_list));
EXPECT_TRUE(base::Value::Equals(expected.get(), extension_pref.get()));
}
@@ -365,7 +369,7 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDictMultipleProxies) {
TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
std::unique_ptr<base::DictionaryValue> browser_pref(
ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
- ProxyConfigDictionary config(browser_pref.get());
+ ProxyConfigDictionary config(std::move(browser_pref));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreatePacScriptDict(config));
ASSERT_TRUE(extension_pref.get());
@@ -381,7 +385,7 @@ TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWidthData) {
std::unique_ptr<base::DictionaryValue> browser_pref(
ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
- ProxyConfigDictionary config(browser_pref.get());
+ ProxyConfigDictionary config(std::move(browser_pref));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreatePacScriptDict(config));
ASSERT_TRUE(extension_pref.get());
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc
index 61ebbd4c0b3..7df0ebb87e3 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc
@@ -37,7 +37,8 @@ class ProxySettingsApiTest : public ExtensionApiTest {
EXPECT_TRUE(pref->IsExtensionControlled());
ProxyConfigDictionary dict(
- pref_service->GetDictionary(proxy_config::prefs::kProxy));
+ pref_service->GetDictionary(proxy_config::prefs::kProxy)
+ ->CreateDeepCopy());
ProxyPrefs::ProxyMode mode;
ASSERT_TRUE(dict.GetMode(&mode));
diff --git a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
index 54395bd3674..2070b6a0393 100644
--- a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
@@ -78,7 +78,8 @@ class BackoffPolicy {
// We use a LazyInstance since one of the the policy values references an
// extern symbol, which would cause a static initializer to be generated if we
// just declared the policy struct as a static variable.
-base::LazyInstance<BackoffPolicy> g_backoff_policy = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<BackoffPolicy>::DestructorAtExit g_backoff_policy =
+ LAZY_INSTANCE_INITIALIZER;
BackoffPolicy::BackoffPolicy() {
policy_ = {
diff --git a/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc b/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
index ea965b08b25..dfe4f1b18e4 100644
--- a/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
@@ -146,8 +146,8 @@ void ScreenlockPrivateEventRouter::DispatchEvent(
EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
}
-static base::LazyInstance<
- BrowserContextKeyedAPIFactory<ScreenlockPrivateEventRouter>> g_factory =
+static base::LazyInstance<BrowserContextKeyedAPIFactory<
+ ScreenlockPrivateEventRouter>>::DestructorAtExit g_factory =
LAZY_INSTANCE_INITIALIZER;
// static
diff --git a/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc b/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc
index d16751b288c..48db51d84cf 100644
--- a/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc
@@ -18,7 +18,6 @@
#include "chrome/browser/signin/signin_manager_factory.h"
#include "components/proximity_auth/screenlock_bridge.h"
#include "components/signin/core/browser/signin_manager.h"
-#include "components/signin/core/common/profile_management_switches.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/api/test/test_api.h"
#include "extensions/browser/notification_types.h"
@@ -48,10 +47,6 @@ class ScreenlockPrivateApiTest : public ExtensionApiTest,
command_line->AppendSwitchASCII(
extensions::switches::kWhitelistedExtensionID, kTestExtensionId);
-#if !defined(OS_CHROMEOS)
- // New profile management needs to be on for non-ChromeOS lock.
- ::switches::EnableNewProfileManagementForTesting(command_line);
-#endif
}
void SetUpOnMainThread() override {
diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc b/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
index 8d2cbdadadf..83f3b82888a 100644
--- a/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
+++ b/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
@@ -275,9 +275,6 @@ std::unique_ptr<windows::Window> SessionsGetDevicesFunction::CreateWindowModel(
windows::WindowState state = windows::WINDOW_STATE_NONE;
switch (window.show_state) {
case ui::SHOW_STATE_NORMAL:
-
- // TODO(afakhry): Remove Docked Windows in M58.
- case ui::SHOW_STATE_DOCKED:
state = windows::WINDOW_STATE_NORMAL;
break;
case ui::SHOW_STATE_MINIMIZED:
@@ -339,7 +336,7 @@ api::sessions::Device SessionsGetDevicesFunction::CreateDeviceModel(
static_cast<int>(device_struct.sessions.size()) < max_results;
++it) {
std::unique_ptr<api::sessions::Session> session_model(
- CreateSessionModel(*it->second, session->session_tag));
+ CreateSessionModel(it->second->wrapped_window, session->session_tag));
if (session_model)
device_struct.sessions.push_back(std::move(*session_model));
}
@@ -596,8 +593,9 @@ void SessionsAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<SessionsAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<SessionsAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
BrowserContextKeyedAPIFactory<SessionsAPI>*
SessionsAPI::GetFactoryInstance() {
diff --git a/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc b/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
index 27173838be4..6f607b1a056 100644
--- a/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
+++ b/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
@@ -31,8 +31,8 @@ namespace extensions {
namespace {
-base::LazyInstance<BrowserContextKeyedAPIFactory<SettingsOverridesAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<BrowserContextKeyedAPIFactory<SettingsOverridesAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
const char kManyStartupPagesWarning[] = "* specifies more than 1 startup URL. "
"All but the first will be ignored.";
@@ -159,7 +159,7 @@ void SettingsOverridesAPI::OnExtensionLoaded(
ExtensionPrefs::Get(profile_)->GetInstallParam(extension->id());
if (settings->homepage) {
SetPref(extension->id(), prefs::kHomePage,
- base::MakeUnique<base::StringValue>(SubstituteInstallParam(
+ base::MakeUnique<base::Value>(SubstituteInstallParam(
settings->homepage->spec(), install_parameter)));
SetPref(extension->id(), prefs::kHomePageIsNewTabPage,
base::MakeUnique<base::Value>(false));
diff --git a/chromium/chrome/browser/extensions/api/settings_private/OWNERS b/chromium/chrome/browser/extensions/api/settings_private/OWNERS
index e07a545d3ee..879a522d857 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/settings_private/OWNERS
@@ -1,3 +1,5 @@
michaelpg@chromium.org
stevenjb@chromium.org
dbeam@chromium.org
+
+# COMPONENT: UI>Settings
diff --git a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 60039bdb5b1..7016dfcbdce 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -20,7 +20,7 @@
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "components/safe_browsing_db/safe_browsing_prefs.h"
-#include "components/search_engines/search_engines_pref_names.h"
+#include "components/search_engines/default_search_manager.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/translate/core/browser/translate_prefs.h"
#include "components/translate/core/common/translate_pref_names.h"
@@ -39,6 +39,7 @@
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chromeos/settings/cros_settings_names.h"
+#include "ui/chromeos/events/pref_names.h"
#endif
namespace {
@@ -119,6 +120,10 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_private::PrefType::PREF_TYPE_STRING;
(*s_whitelist)[::prefs::kDefaultCharset] =
settings_private::PrefType::PREF_TYPE_STRING;
+#if defined(OS_MACOSX)
+ (*s_whitelist)[::prefs::kWebkitTabsToLinks] =
+ settings_private::PrefType::PREF_TYPE_BOOLEAN;
+#endif
// On startup.
(*s_whitelist)[::prefs::kRestoreOnStartup] =
@@ -171,8 +176,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
#endif
// Search page.
- (*s_whitelist)[::prefs::kDefaultSearchProviderEnabled] =
- settings_private::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[DefaultSearchManager::kDefaultSearchProviderDataPrefName] =
+ settings_private::PrefType::PREF_TYPE_DICTIONARY;
(*s_whitelist)[::prefs::kGoogleNowLauncherEnabled] =
settings_private::PrefType::PREF_TYPE_BOOLEAN;
@@ -278,6 +283,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_private::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kWakeOnWifiDarkConnect] =
settings_private::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::chromeos::kSignedDataRoamingEnabled] =
+ settings_private::PrefType::PREF_TYPE_BOOLEAN;
// Timezone settings.
(*s_whitelist)[chromeos::kSystemTimezone] =
@@ -341,15 +348,15 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_private::PrefType::PREF_TYPE_BOOLEAN;
// Import data
- (*s_whitelist)[::prefs::kImportAutofillFormData] =
+ (*s_whitelist)[::prefs::kImportDialogAutofillFormData] =
settings_private::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kImportBookmarks] =
+ (*s_whitelist)[::prefs::kImportDialogBookmarks] =
settings_private::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kImportHistory] =
+ (*s_whitelist)[::prefs::kImportDialogHistory] =
settings_private::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kImportSavedPasswords] =
+ (*s_whitelist)[::prefs::kImportDialogSavedPasswords] =
settings_private::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kImportSearchEngine] =
+ (*s_whitelist)[::prefs::kImportDialogSearchEngine] =
settings_private::PrefType::PREF_TYPE_BOOLEAN;
#endif
@@ -371,6 +378,14 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
return *s_whitelist;
}
+settings_private::PrefType PrefsUtil::GetWhitelistedPrefType(
+ const std::string& pref_name) {
+ const TypedPrefMap& keys = GetWhitelistedKeys();
+ const auto& iter = keys.find(pref_name);
+ return iter != keys.end() ? iter->second
+ : settings_private::PrefType::PREF_TYPE_NONE;
+}
+
settings_private::PrefType PrefsUtil::GetType(const std::string& name,
base::Value::Type type) {
switch (type) {
@@ -398,7 +413,10 @@ std::unique_ptr<settings_private::PrefObject> PrefsUtil::GetCrosSettingsPref(
#if defined(OS_CHROMEOS)
const base::Value* value = CrosSettings::Get()->GetPref(name);
- DCHECK(value) << "Pref not found: " << name;
+ if (!value) {
+ LOG(ERROR) << "Cros settings pref not found: " << name;
+ return nullptr;
+ }
pref_object->key = name;
pref_object->type = GetType(name, value->GetType());
pref_object->value.reset(value->DeepCopy());
@@ -409,10 +427,17 @@ std::unique_ptr<settings_private::PrefObject> PrefsUtil::GetCrosSettingsPref(
std::unique_ptr<settings_private::PrefObject> PrefsUtil::GetPref(
const std::string& name) {
+ if (GetWhitelistedPrefType(name) ==
+ settings_private::PrefType::PREF_TYPE_NONE) {
+ return nullptr;
+ }
+
const PrefService::Preference* pref = nullptr;
std::unique_ptr<settings_private::PrefObject> pref_object;
if (IsCrosSetting(name)) {
pref_object = GetCrosSettingsPref(name);
+ if (!pref_object)
+ return nullptr;
} else {
PrefService* pref_service = FindServiceForPref(name);
pref = pref_service->FindPreference(name);
@@ -505,6 +530,11 @@ std::unique_ptr<settings_private::PrefObject> PrefsUtil::GetPref(
PrefsUtil::SetPrefResult PrefsUtil::SetPref(const std::string& pref_name,
const base::Value* value) {
+ if (GetWhitelistedPrefType(pref_name) ==
+ settings_private::PrefType::PREF_TYPE_NONE) {
+ return PREF_NOT_FOUND;
+ }
+
if (IsCrosSetting(pref_name))
return SetCrosSettingsPref(pref_name, value);
@@ -620,15 +650,8 @@ bool PrefsUtil::RemoveFromListCrosSetting(const std::string& pref_name,
}
bool PrefsUtil::IsPrefTypeURL(const std::string& pref_name) {
- settings_private::PrefType pref_type =
- settings_private::PrefType::PREF_TYPE_NONE;
-
- const TypedPrefMap keys = GetWhitelistedKeys();
- const auto& iter = keys.find(pref_name);
- if (iter != keys.end())
- pref_type = iter->second;
-
- return pref_type == settings_private::PrefType::PREF_TYPE_URL;
+ return GetWhitelistedPrefType(pref_name) ==
+ settings_private::PrefType::PREF_TYPE_URL;
}
#if defined(OS_CHROMEOS)
@@ -739,8 +762,10 @@ const Extension* PrefsUtil::GetExtensionControllingPref(
if (pref_object.key == ::prefs::kURLsToRestoreOnStartup)
return GetExtensionOverridingStartupPages(profile_);
- if (pref_object.key == ::prefs::kDefaultSearchProviderEnabled)
+ if (pref_object.key ==
+ DefaultSearchManager::kDefaultSearchProviderDataPrefName) {
return GetExtensionOverridingSearchEngine(profile_);
+ }
if (pref_object.key == proxy_config::prefs::kProxy)
return GetExtensionOverridingProxy(profile_);
diff --git a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.h b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.h
index a2f229e0862..8695af459ca 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.h
+++ b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.h
@@ -42,6 +42,11 @@ class PrefsUtil {
// manipulate.
const TypedPrefMap& GetWhitelistedKeys();
+ // Returns the pref type for |pref_name| or PREF_TYPE_NONE if not in the
+ // whitelist.
+ api::settings_private::PrefType GetWhitelistedPrefType(
+ const std::string& pref_name);
+
// Gets the value of the pref with the given |name|. Returns a pointer to an
// empty PrefObject if no pref is found for |name|.
virtual std::unique_ptr<api::settings_private::PrefObject> GetPref(
diff --git a/chromium/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc b/chromium/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc
index 539f94b58cb..f043941329f 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/settings_private_delegate.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -36,7 +37,7 @@ std::unique_ptr<base::Value> SettingsPrivateDelegate::GetPref(
std::unique_ptr<api::settings_private::PrefObject> pref =
prefs_util_->GetPref(name);
if (!pref)
- return base::Value::CreateNullValue();
+ return base::MakeUnique<base::Value>();
return pref->ToValue();
}
diff --git a/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc b/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc
index f42e2ef98f9..d5d26635977 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
@@ -20,7 +21,7 @@ namespace extensions {
SettingsPrivateEventRouter::SettingsPrivateEventRouter(
content::BrowserContext* context)
- : context_(context), listening_(false) {
+ : context_(context), listening_(false), weak_ptr_factory_(this) {
// Register with the event router so we know when renderers are listening to
// our events. We first check and see if there *is* an event router, because
// some unit tests try to create all context services, but don't initialize
@@ -123,6 +124,15 @@ void SettingsPrivateEventRouter::StartOrStopListeningForPrefsChanges() {
void SettingsPrivateEventRouter::OnPreferenceChanged(
const std::string& pref_name) {
+ // This posts an asynchronous task to ensure that all pref stores are updated,
+ // as |prefs_util_->GetPref()| relies on this information to determine if a
+ // preference is controlled by e.g. extensions.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&SettingsPrivateEventRouter::SendPrefChange,
+ weak_ptr_factory_.GetWeakPtr(), pref_name));
+}
+
+void SettingsPrivateEventRouter::SendPrefChange(const std::string& pref_name) {
EventRouter* event_router = EventRouter::Get(context_);
if (!event_router->HasEventListener(
api::settings_private::OnPrefsChanged::kEventName)) {
diff --git a/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.h b/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.h
index 75fef8f2c45..4c2f1666743 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.h
+++ b/chromium/chrome/browser/extensions/api/settings_private/settings_private_event_router.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/extensions/api/settings_private/prefs_util.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -55,6 +56,9 @@ class SettingsPrivateEventRouter : public KeyedService,
void OnPreferenceChanged(const std::string& pref_name);
+ // Sends a pref change to any listeners (if they exist; no-ops otherwise).
+ void SendPrefChange(const std::string& pref_name);
+
PrefChangeRegistrar* FindRegistrarForPref(const std::string& pref_name);
using SubscriptionMap =
@@ -67,6 +71,8 @@ class SettingsPrivateEventRouter : public KeyedService,
std::unique_ptr<PrefsUtil> prefs_util_;
+ base::WeakPtrFactory<SettingsPrivateEventRouter> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SettingsPrivateEventRouter);
};
diff --git a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.cc b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.cc
index 096316a5caa..93d9ac9118f 100644
--- a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.cc
+++ b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.cc
@@ -41,10 +41,8 @@ const base::DictionaryValue* GetIdMappingDictionary(
std::unique_ptr<base::DictionaryValue> dictionary(
new base::DictionaryValue());
out_value = dictionary.get();
- extension_prefs->UpdateExtensionPref(
- extension_id,
- kPrefStringForIdMapping,
- dictionary.release());
+ extension_prefs->UpdateExtensionPref(extension_id, kPrefStringForIdMapping,
+ std::move(dictionary));
}
return out_value;
@@ -73,9 +71,8 @@ std::vector<std::unique_ptr<DeviceInfo>> GetAllSignedInDevices(
CreateMappingForUnmappedDevices(devices, editable_mapping_dictionary.get());
// Write into |ExtensionPrefs| which will get persisted in disk.
- extension_prefs->UpdateExtensionPref(extension_id,
- kPrefStringForIdMapping,
- editable_mapping_dictionary.release());
+ extension_prefs->UpdateExtensionPref(extension_id, kPrefStringForIdMapping,
+ std::move(editable_mapping_dictionary));
return devices;
}
diff --git a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc
index ab3864f80fd..c8feb049305 100644
--- a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc
+++ b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.cc
@@ -87,8 +87,8 @@ void SignedInDevicesChangeObserver::OnDeviceInfoChange() {
}
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<SignedInDevicesManager> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<SignedInDevicesManager>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<SignedInDevicesManager>*
@@ -114,7 +114,9 @@ SignedInDevicesManager::SignedInDevicesManager(content::BrowserContext* context)
extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
}
-SignedInDevicesManager::~SignedInDevicesManager() {
+SignedInDevicesManager::~SignedInDevicesManager() = default;
+
+void SignedInDevicesManager::Shutdown() {
if (profile_) {
EventRouter* router = EventRouter::Get(profile_);
if (router)
diff --git a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h
index 0c6dad3e6e4..c3e0b9d63f0 100644
--- a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h
+++ b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager.h
@@ -68,6 +68,7 @@ class SignedInDevicesManager : public BrowserContextKeyedAPI,
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<SignedInDevicesManager>*
GetFactoryInstance();
+ void Shutdown() override;
// ExtensionRegistryObserver implementation.
void OnExtensionUnloaded(content::BrowserContext* browser_context,
diff --git a/chromium/chrome/browser/extensions/api/spellcheck/spellcheck_api.cc b/chromium/chrome/browser/extensions/api/spellcheck/spellcheck_api.cc
index 56e4d658614..517086ec32c 100644
--- a/chromium/chrome/browser/extensions/api/spellcheck/spellcheck_api.cc
+++ b/chromium/chrome/browser/extensions/api/spellcheck/spellcheck_api.cc
@@ -46,8 +46,9 @@ SpellcheckAPI::SpellcheckAPI(content::BrowserContext* context)
SpellcheckAPI::~SpellcheckAPI() {
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<SpellcheckAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<SpellcheckAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<SpellcheckAPI>*
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 5fd08264643..02ceaafbb0d 100644
--- a/chromium/chrome/browser/extensions/api/storage/policy_value_store.cc
+++ b/chromium/chrome/browser/extensions/api/storage/policy_value_store.cc
@@ -46,7 +46,7 @@ void PolicyValueStore::SetCurrentPolicy(const policy::PolicyMap& policy) {
it != policy.end(); ++it) {
if (it->second.level == policy::POLICY_LEVEL_MANDATORY) {
current_policy.SetWithoutPathExpansion(
- it->first, it->second.value->DeepCopy());
+ it->first, it->second.value->CreateDeepCopy());
}
}
diff --git a/chromium/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc b/chromium/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc
index ae8fbefa82a..1bd814dd535 100644
--- a/chromium/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc
@@ -143,7 +143,7 @@ TEST_F(PolicyValueStoreTest, DontProvideRecommendedPolicies) {
TEST_F(PolicyValueStoreTest, ReadOnly) {
ValueStore::WriteOptions options = ValueStore::DEFAULTS;
- base::StringValue string_value("value");
+ base::Value string_value("value");
EXPECT_FALSE(store_->Set(options, "key", string_value)->status().ok());
base::DictionaryValue dict;
@@ -159,7 +159,7 @@ TEST_F(PolicyValueStoreTest, ReadOnly) {
TEST_F(PolicyValueStoreTest, NotifyOnChanges) {
// Notify when setting the initial policy.
- const base::StringValue value("111");
+ const base::Value value("111");
{
ValueStoreChangeList changes;
changes.push_back(ValueStoreChange("aaa", nullptr, value.CreateDeepCopy()));
@@ -193,7 +193,7 @@ TEST_F(PolicyValueStoreTest, NotifyOnChanges) {
Mock::VerifyAndClearExpectations(&observer_);
// Notify when policies change.
- const base::StringValue new_value("222");
+ const base::Value new_value("222");
{
ValueStoreChangeList changes;
changes.push_back(ValueStoreChange("bbb", 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 ac1d74b70a9..e0c56008abf 100644
--- a/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc
@@ -329,7 +329,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
// Set "foo" to "bar" via sync.
syncer::SyncChangeList sync_changes;
- base::StringValue bar("bar");
+ base::Value bar("bar");
sync_changes.push_back(settings_sync_util::CreateAdd(
extension_id, "foo", bar, kModelType));
SendChanges(sync_changes);
@@ -374,7 +374,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest,
// Set "foo" to "bar" via sync.
syncer::SyncChangeList sync_changes;
- base::StringValue bar("bar");
+ base::Value bar("bar");
sync_changes.push_back(settings_sync_util::CreateAdd(
extension_id, "foo", bar, kModelType));
SendChanges(sync_changes);
diff --git a/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc b/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
index 1f68049384b..d44e0e2ac78 100644
--- a/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
@@ -15,6 +15,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/storage/settings_sync_util.h"
#include "chrome/browser/extensions/api/storage/sync_value_store_cache.h"
@@ -300,7 +301,7 @@ TEST_F(ExtensionSettingsSyncTest, InSyncDataDoesNotInvokeSync) {
syncer::ModelType model_type = syncer::APP_SETTINGS;
Manifest::Type type = Manifest::TYPE_LEGACY_PACKAGED_APP;
- base::StringValue value1("fooValue");
+ base::Value value1("fooValue");
base::ListValue value2;
value2.AppendString("barValue");
@@ -349,7 +350,7 @@ TEST_F(ExtensionSettingsSyncTest, LocalDataWithNoSyncDataIsPushedToSync) {
syncer::ModelType model_type = syncer::EXTENSION_SETTINGS;
Manifest::Type type = Manifest::TYPE_EXTENSION;
- base::StringValue value1("fooValue");
+ base::Value value1("fooValue");
base::ListValue value2;
value2.AppendString("barValue");
@@ -381,7 +382,7 @@ TEST_F(ExtensionSettingsSyncTest, AnySyncDataOverwritesLocalData) {
syncer::ModelType model_type = syncer::APP_SETTINGS;
Manifest::Type type = Manifest::TYPE_LEGACY_PACKAGED_APP;
- base::StringValue value1("fooValue");
+ base::Value value1("fooValue");
base::ListValue value2;
value2.AppendString("barValue");
@@ -402,8 +403,8 @@ TEST_F(ExtensionSettingsSyncTest, AnySyncDataOverwritesLocalData) {
->MergeDataAndStartSyncing(
model_type, sync_data, std::move(sync_processor_wrapper_),
base::MakeUnique<syncer::SyncErrorFactoryMock>());
- expected1.Set("foo", value1.DeepCopy());
- expected2.Set("bar", value2.DeepCopy());
+ expected1.Set("foo", value1.CreateDeepCopy());
+ expected2.Set("bar", value2.CreateDeepCopy());
ValueStore* storage2 = AddExtensionAndGetStorage("s2", type);
@@ -421,7 +422,7 @@ TEST_F(ExtensionSettingsSyncTest, ProcessSyncChanges) {
syncer::ModelType model_type = syncer::EXTENSION_SETTINGS;
Manifest::Type type = Manifest::TYPE_EXTENSION;
- base::StringValue value1("fooValue");
+ base::Value value1("fooValue");
base::ListValue value2;
value2.AppendString("barValue");
@@ -434,7 +435,7 @@ TEST_F(ExtensionSettingsSyncTest, ProcessSyncChanges) {
ValueStore* storage2 = AddExtensionAndGetStorage("s2", type);
storage1->Set(DEFAULTS, "foo", value1);
- expected1.Set("foo", value1.DeepCopy());
+ expected1.Set("foo", value1.CreateDeepCopy());
syncer::SyncDataList sync_data;
sync_data.push_back(settings_sync_util::CreateData(
@@ -444,7 +445,7 @@ TEST_F(ExtensionSettingsSyncTest, ProcessSyncChanges) {
->MergeDataAndStartSyncing(
model_type, sync_data, std::move(sync_processor_wrapper_),
base::MakeUnique<syncer::SyncErrorFactoryMock>());
- expected2.Set("bar", value2.DeepCopy());
+ expected2.Set("bar", value2.CreateDeepCopy());
// Make sync add some settings.
syncer::SyncChangeList change_list;
@@ -453,8 +454,8 @@ TEST_F(ExtensionSettingsSyncTest, ProcessSyncChanges) {
change_list.push_back(settings_sync_util::CreateAdd(
"s2", "foo", value1, model_type));
GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
- expected1.Set("bar", value2.DeepCopy());
- expected2.Set("foo", value1.DeepCopy());
+ expected1.Set("bar", value2.CreateDeepCopy());
+ expected2.Set("foo", value1.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, expected1, storage1->Get());
EXPECT_PRED_FORMAT2(SettingsEq, expected2, storage2->Get());
@@ -467,8 +468,8 @@ TEST_F(ExtensionSettingsSyncTest, ProcessSyncChanges) {
change_list.push_back(settings_sync_util::CreateUpdate(
"s2", "bar", value1, model_type));
GetSyncableService(model_type)->ProcessSyncChanges(FROM_HERE, change_list);
- expected1.Set("bar", value2.DeepCopy());
- expected2.Set("bar", value1.DeepCopy());
+ expected1.Set("bar", value2.CreateDeepCopy());
+ expected2.Set("bar", value1.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, expected1, storage1->Get());
EXPECT_PRED_FORMAT2(SettingsEq, expected2, storage2->Get());
@@ -494,7 +495,7 @@ TEST_F(ExtensionSettingsSyncTest, PushToSync) {
syncer::ModelType model_type = syncer::APP_SETTINGS;
Manifest::Type type = Manifest::TYPE_LEGACY_PACKAGED_APP;
- base::StringValue value1("fooValue");
+ base::Value value1("fooValue");
base::ListValue value2;
value2.AppendString("barValue");
@@ -621,7 +622,7 @@ TEST_F(ExtensionSettingsSyncTest, PushToSync) {
}
TEST_F(ExtensionSettingsSyncTest, ExtensionAndAppSettingsSyncSeparately) {
- base::StringValue value1("fooValue");
+ base::Value value1("fooValue");
base::ListValue value2;
value2.AppendString("barValue");
@@ -680,8 +681,8 @@ TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
syncer::ModelType model_type = syncer::EXTENSION_SETTINGS;
Manifest::Type type = Manifest::TYPE_EXTENSION;
- base::StringValue fooValue("fooValue");
- base::StringValue barValue("barValue");
+ base::Value fooValue("fooValue");
+ base::Value barValue("barValue");
// There is a bit of a convoluted method to get storage areas that can fail;
// hand out TestingValueStore object then toggle them failing/succeeding
@@ -707,7 +708,7 @@ TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
@@ -726,13 +727,13 @@ TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -751,13 +752,13 @@ TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -773,13 +774,13 @@ TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
- dict.Set("bar", fooValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
+ dict.Set("bar", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("bar", fooValue.DeepCopy());
+ dict.Set("bar", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -798,13 +799,13 @@ TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
- dict.Set("bar", fooValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
+ dict.Set("bar", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("bar", fooValue.DeepCopy());
+ dict.Set("bar", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -852,13 +853,13 @@ TEST_F(ExtensionSettingsSyncTest, FailingStartSyncingDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
- dict.Set("bar", fooValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
+ dict.Set("bar", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("bar", fooValue.DeepCopy());
+ dict.Set("bar", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
}
@@ -869,8 +870,8 @@ TEST_F(ExtensionSettingsSyncTest, FailingProcessChangesDisablesSync) {
syncer::ModelType model_type = syncer::APP_SETTINGS;
Manifest::Type type = Manifest::TYPE_LEGACY_PACKAGED_APP;
- base::StringValue fooValue("fooValue");
- base::StringValue barValue("barValue");
+ base::Value fooValue("fooValue");
+ base::Value barValue("barValue");
ValueStore* good = AddExtensionAndGetStorage("good", type);
ValueStore* bad = AddExtensionAndGetStorage("bad", type);
@@ -892,12 +893,12 @@ TEST_F(ExtensionSettingsSyncTest, FailingProcessChangesDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -915,13 +916,13 @@ TEST_F(ExtensionSettingsSyncTest, FailingProcessChangesDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -946,13 +947,13 @@ TEST_F(ExtensionSettingsSyncTest, FailingProcessChangesDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
}
@@ -961,8 +962,8 @@ TEST_F(ExtensionSettingsSyncTest, FailingGetAllSyncDataDoesntStopSync) {
syncer::ModelType model_type = syncer::EXTENSION_SETTINGS;
Manifest::Type type = Manifest::TYPE_EXTENSION;
- base::StringValue fooValue("fooValue");
- base::StringValue barValue("barValue");
+ base::Value fooValue("fooValue");
+ base::Value barValue("barValue");
ValueStore* good = AddExtensionAndGetStorage("good", type);
ValueStore* bad = AddExtensionAndGetStorage("bad", type);
@@ -1009,8 +1010,8 @@ TEST_F(ExtensionSettingsSyncTest, FailureToReadChangesToPushDisablesSync) {
syncer::ModelType model_type = syncer::APP_SETTINGS;
Manifest::Type type = Manifest::TYPE_LEGACY_PACKAGED_APP;
- base::StringValue fooValue("fooValue");
- base::StringValue barValue("barValue");
+ base::Value fooValue("fooValue");
+ base::Value barValue("barValue");
ValueStore* good = AddExtensionAndGetStorage("good", type);
ValueStore* bad = AddExtensionAndGetStorage("bad", type);
@@ -1054,14 +1055,14 @@ TEST_F(ExtensionSettingsSyncTest, FailureToReadChangesToPushDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("foo", fooValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", fooValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -1102,8 +1103,8 @@ TEST_F(ExtensionSettingsSyncTest, FailureToPushLocalStateDisablesSync) {
syncer::ModelType model_type = syncer::EXTENSION_SETTINGS;
Manifest::Type type = Manifest::TYPE_EXTENSION;
- base::StringValue fooValue("fooValue");
- base::StringValue barValue("barValue");
+ base::Value fooValue("fooValue");
+ base::Value barValue("barValue");
ValueStore* good = AddExtensionAndGetStorage("good", type);
ValueStore* bad = AddExtensionAndGetStorage("bad", type);
@@ -1140,13 +1141,13 @@ TEST_F(ExtensionSettingsSyncTest, FailureToPushLocalStateDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -1184,8 +1185,8 @@ TEST_F(ExtensionSettingsSyncTest, FailureToPushLocalChangeDisablesSync) {
syncer::ModelType model_type = syncer::EXTENSION_SETTINGS;
Manifest::Type type = Manifest::TYPE_EXTENSION;
- base::StringValue fooValue("fooValue");
- base::StringValue barValue("barValue");
+ base::Value fooValue("fooValue");
+ base::Value barValue("barValue");
ValueStore* good = AddExtensionAndGetStorage("good", type);
ValueStore* bad = AddExtensionAndGetStorage("bad", type);
@@ -1227,13 +1228,13 @@ TEST_F(ExtensionSettingsSyncTest, FailureToPushLocalChangeDisablesSync) {
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
- dict.Set("bar", barValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
+ dict.Set("bar", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, good->Get());
}
{
base::DictionaryValue dict;
- dict.Set("foo", barValue.DeepCopy());
+ dict.Set("foo", barValue.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, dict, bad->Get());
}
@@ -1277,7 +1278,7 @@ TEST_F(ExtensionSettingsSyncTest,
for (size_t i = 0; i < 10000; ++i) {
string_10k.append("a");
}
- base::StringValue large_value(string_10k);
+ base::Value large_value(string_10k);
GetSyncableService(model_type)
->MergeDataAndStartSyncing(
@@ -1303,7 +1304,7 @@ TEST_F(ExtensionSettingsSyncTest,
}
{
base::DictionaryValue expected;
- expected.Set("large_value", large_value.DeepCopy());
+ expected.Set("large_value", large_value.CreateDeepCopy());
EXPECT_PRED_FORMAT2(SettingsEq, expected, storage1->Get());
EXPECT_PRED_FORMAT2(SettingsEq, expected, storage2->Get());
}
@@ -1319,7 +1320,7 @@ TEST_F(ExtensionSettingsSyncTest, Dots) {
{
syncer::SyncDataList sync_data_list;
- std::unique_ptr<base::Value> string_value(new base::StringValue("value"));
+ std::unique_ptr<base::Value> string_value(new base::Value("value"));
sync_data_list.push_back(settings_sync_util::CreateData(
"ext", "key.with.dot", *string_value, model_type));
@@ -1336,14 +1337,13 @@ TEST_F(ExtensionSettingsSyncTest, Dots) {
base::DictionaryValue expected_data;
expected_data.SetWithoutPathExpansion(
- "key.with.dot",
- new base::StringValue("value"));
+ "key.with.dot", base::MakeUnique<base::Value>("value"));
EXPECT_TRUE(base::Value::Equals(&expected_data, &data->settings()));
}
// Test dots in keys going to sync.
{
- std::unique_ptr<base::Value> string_value(new base::StringValue("spot"));
+ std::unique_ptr<base::Value> string_value(new base::Value("spot"));
storage->Set(DEFAULTS, "key.with.spot", *string_value);
ASSERT_EQ(1u, sync_processor_->changes().size());
diff --git a/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc
index 21c333a6738..4e204055196 100644
--- a/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -181,8 +181,8 @@ void StreamsPrivateAbortFunction::OnClose() {
Respond(NoArguments());
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<StreamsPrivateAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<StreamsPrivateAPI>*
diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc b/chromium/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
index ba11685f57d..eb46006f4f0 100644
--- a/chromium/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
+++ b/chromium/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
@@ -27,8 +27,8 @@ using sync_file_system::SyncEventObserver;
namespace extensions {
static base::LazyInstance<
- BrowserContextKeyedAPIFactory<ExtensionSyncEventObserver> > g_factory =
- LAZY_INSTANCE_INITIALIZER;
+ BrowserContextKeyedAPIFactory<ExtensionSyncEventObserver>>::DestructorAtExit
+ g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<ExtensionSyncEventObserver>*
@@ -94,8 +94,8 @@ void ExtensionSyncEventObserver::OnFileSynced(
sync_file_system::SyncDirection direction) {
std::unique_ptr<base::ListValue> params(new base::ListValue());
- std::unique_ptr<base::DictionaryValue> entry(
- CreateDictionaryValueForFileSystemEntry(url, file_type));
+ std::unique_ptr<base::DictionaryValue> entry =
+ CreateDictionaryValueForFileSystemEntry(url, file_type);
if (!entry)
return;
params->Append(std::move(entry));
diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
index a7fdbf9e560..a8f2760508d 100644
--- a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
+++ b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
@@ -371,8 +371,8 @@ SyncFileSystemSetConflictResolutionPolicyFunction::Run() {
ExtensionFunction::ResponseAction
SyncFileSystemGetConflictResolutionPolicyFunction::Run() {
- return RespondNow(OneArgument(
- base::MakeUnique<base::StringValue>(api::sync_file_system::ToString(
+ return RespondNow(
+ OneArgument(base::MakeUnique<base::Value>(api::sync_file_system::ToString(
api::sync_file_system::CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN))));
}
diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc
index 6cfbf8a1862..c191b3d18a9 100644
--- a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.cc
@@ -5,6 +5,8 @@
#include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/values.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "storage/common/fileapi/file_system_util.h"
@@ -105,11 +107,11 @@ ConflictResolutionPolicyToExtensionEnum(
return api::sync_file_system::CONFLICT_RESOLUTION_POLICY_NONE;
}
-base::DictionaryValue* CreateDictionaryValueForFileSystemEntry(
+std::unique_ptr<base::DictionaryValue> CreateDictionaryValueForFileSystemEntry(
const storage::FileSystemURL& url,
sync_file_system::SyncFileType file_type) {
if (!url.is_valid() || file_type == sync_file_system::SYNC_FILE_TYPE_UNKNOWN)
- return NULL;
+ return nullptr;
std::string file_path =
base::FilePath(storage::VirtualPath::GetNormalizedFilePath(url.path()))
@@ -122,7 +124,7 @@ base::DictionaryValue* CreateDictionaryValueForFileSystemEntry(
root_url.append("/");
}
- base::DictionaryValue* dict = new base::DictionaryValue;
+ auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString("fileSystemType",
storage::GetFileSystemTypeString(url.mount_type()));
dict->SetString("fileSystemName",
diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h
index 1d0feab2a20..8c4ae9aea64 100644
--- a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h
+++ b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_SYNC_FILE_SYSTEM_SYNC_FILE_SYSTEM_API_HELPERS_H_
#define CHROME_BROWSER_EXTENSIONS_API_SYNC_FILE_SYSTEM_SYNC_FILE_SYSTEM_API_HELPERS_H_
+#include <memory>
+
#include "chrome/browser/sync_file_system/conflict_resolution_policy.h"
#include "chrome/browser/sync_file_system/sync_action.h"
#include "chrome/browser/sync_file_system/sync_direction.h"
@@ -52,7 +54,7 @@ ExtensionEnumToConflictResolutionPolicy(
// in the renderer's customer binding to create a FileEntry object.
// This returns NULL if the given |url| is not valid or |file_type| is
// SYNC_FILE_TYPE_UNKNOWN.
-base::DictionaryValue* CreateDictionaryValueForFileSystemEntry(
+std::unique_ptr<base::DictionaryValue> CreateDictionaryValueForFileSystemEntry(
const storage::FileSystemURL& url,
sync_file_system::SyncFileType file_type);
diff --git a/chromium/chrome/browser/extensions/api/system_indicator/OWNERS b/chromium/chrome/browser/extensions/api/system_indicator/OWNERS
index 6f1cc7b2a2c..8d997bdbb9e 100644
--- a/chromium/chrome/browser/extensions/api/system_indicator/OWNERS
+++ b/chromium/chrome/browser/extensions/api/system_indicator/OWNERS
@@ -1 +1,4 @@
dewittj@chromium.org
+
+# TEAM: apps-dev@chromium.org
+# COMPONENT: Platform>Apps
diff --git a/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc b/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc
index d128aa24734..997e83eee9f 100644
--- a/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc
@@ -79,8 +79,8 @@ SystemPrivateGetIncognitoModeAvailabilityFunction::Run() {
EXTENSION_FUNCTION_VALIDATE(
value >= 0 &&
value < static_cast<int>(arraysize(kIncognitoModeAvailabilityStrings)));
- return RespondNow(OneArgument(base::MakeUnique<base::StringValue>(
- kIncognitoModeAvailabilityStrings[value])));
+ return RespondNow(OneArgument(
+ base::MakeUnique<base::Value>(kIncognitoModeAvailabilityStrings[value])));
}
ExtensionFunction::ResponseAction SystemPrivateGetUpdateStatusFunction::Run() {
@@ -145,8 +145,8 @@ ExtensionFunction::ResponseAction SystemPrivateGetUpdateStatusFunction::Run() {
}
ExtensionFunction::ResponseAction SystemPrivateGetApiKeyFunction::Run() {
- return RespondNow(OneArgument(
- base::MakeUnique<base::StringValue>(google_apis::GetAPIKey())));
+ return RespondNow(
+ OneArgument(base::MakeUnique<base::Value>(google_apis::GetAPIKey())));
}
void DispatchVolumeChangedEvent(double volume, bool is_volume_muted) {
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc
index 3adbdf05b92..f9c546bac4e 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/web_contents_sizer.h"
+#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
@@ -194,15 +195,13 @@ bool OffscreenTab::HandleContextMenu(const content::ContextMenuParams& params) {
return true;
}
-bool OffscreenTab::PreHandleKeyboardEvent(
+content::KeyboardEventProcessingResult OffscreenTab::PreHandleKeyboardEvent(
WebContents* source,
- const content::NativeWebKeyboardEvent& event,
- bool* is_keyboard_shortcut) {
+ const content::NativeWebKeyboardEvent& event) {
DCHECK_EQ(offscreen_tab_web_contents_.get(), source);
// Intercept and silence all keyboard events before they can be sent to the
// renderer.
- *is_keyboard_shortcut = false;
- return true;
+ return content::KeyboardEventProcessingResult::HANDLED;
}
bool OffscreenTab::PreHandleGestureEvent(WebContents* source,
@@ -281,8 +280,8 @@ bool OffscreenTab::IsFullscreenForTabOrPending(
blink::WebDisplayMode OffscreenTab::GetDisplayMode(
const WebContents* contents) const {
DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
- return in_fullscreen_mode() ?
- blink::WebDisplayModeFullscreen : blink::WebDisplayModeBrowser;
+ return in_fullscreen_mode() ? blink::kWebDisplayModeFullscreen
+ : blink::kWebDisplayModeBrowser;
}
void OffscreenTab::RequestMediaAccessPermission(
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h
index a93453014f2..1df9a3467cf 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h
+++ b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h
@@ -131,9 +131,9 @@ class OffscreenTab : protected content::WebContentsDelegate,
const std::string& request_method,
const base::Callback<void(bool)>& callback) final;
bool HandleContextMenu(const content::ContextMenuParams& params) final;
- bool PreHandleKeyboardEvent(content::WebContents* source,
- const content::NativeWebKeyboardEvent& event,
- bool* is_keyboard_shortcut) final;
+ content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
+ content::WebContents* source,
+ const content::NativeWebKeyboardEvent& event) final;
bool PreHandleGestureEvent(content::WebContents* source,
const blink::WebGestureEvent& event) final;
bool CanDragEnter(content::WebContents* source,
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
index 3f3479e3512..c5d057751ae 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
@@ -54,9 +54,8 @@ class TabCaptureApiTest : public ExtensionApiTest {
protected:
void SimulateMouseClickInCurrentTab() {
content::SimulateMouseClick(
- browser()->tab_strip_model()->GetActiveWebContents(),
- 0,
- blink::WebMouseEvent::Button::Left);
+ browser()->tab_strip_model()->GetActiveWebContents(), 0,
+ blink::WebMouseEvent::Button::kLeft);
}
};
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
index a42bf6c32ee..c72f121441e 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
@@ -258,8 +258,8 @@ TabCaptureRegistry* TabCaptureRegistry::Get(content::BrowserContext* context) {
return BrowserContextKeyedAPIFactory<TabCaptureRegistry>::Get(context);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<TabCaptureRegistry> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<TabCaptureRegistry>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<TabCaptureRegistry>*
diff --git a/chromium/chrome/browser/extensions/api/tabs/app_window_controller.cc b/chromium/chrome/browser/extensions/api/tabs/app_window_controller.cc
index 6831e346d51..bc8272b8417 100644
--- a/chromium/chrome/browser/extensions/api/tabs/app_window_controller.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/app_window_controller.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/tabs/app_base_window.h"
@@ -56,9 +57,9 @@ AppWindowController::CreateWindowValueWithTabs(
if (!tab_value)
return result;
- base::ListValue* tab_list = new base::ListValue();
+ auto tab_list = base::MakeUnique<base::ListValue>();
tab_list->Append(std::move(tab_value));
- result->Set(tabs_constants::kTabsKey, tab_list);
+ result->Set(tabs_constants::kTabsKey, std::move(tab_list));
return result;
}
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
index c36bc009006..e4ec50d3ce1 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -17,6 +17,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/pattern.h"
@@ -199,6 +200,11 @@ void AssignOptionalValue(const std::unique_ptr<T>& source,
}
}
+void ReportRequestedWindowState(windows::WindowState state) {
+ UMA_HISTOGRAM_ENUMERATION("TabsApi.RequestedWindowState", state,
+ windows::WINDOW_STATE_LAST + 1);
+}
+
ui::WindowShowState ConvertToWindowShowState(windows::WindowState state) {
switch (state) {
case windows::WINDOW_STATE_NORMAL:
@@ -489,6 +495,10 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() {
std::string extension_id;
if (create_data) {
+ // Report UMA stats to decide when to remove the deprecated "docked" windows
+ // state (crbug.com/703733).
+ ReportRequestedWindowState(create_data->state);
+
// Figure out window type before figuring out bounds so that default
// bounds can be set according to the window type.
switch (create_data->type) {
@@ -648,7 +658,7 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() {
!browser_context()->IsOffTheRecord() && !include_incognito()) {
// Don't expose incognito windows if extension itself works in non-incognito
// profile and CanCrossIncognito isn't allowed.
- result = base::Value::CreateNullValue();
+ result = base::MakeUnique<base::Value>();
} else {
result = controller->CreateWindowValueWithTabs(extension());
}
@@ -669,6 +679,10 @@ ExtensionFunction::ResponseAction WindowsUpdateFunction::Run() {
return RespondNow(Error(error));
}
+ // Report UMA stats to decide when to remove the deprecated "docked" windows
+ // state (crbug.com/703733).
+ ReportRequestedWindowState(params->update_info.state);
+
ui::WindowShowState show_state =
ConvertToWindowShowState(params->update_info.state);
@@ -1679,7 +1693,7 @@ void TabsCaptureVisibleTabFunction::OnCaptureSuccess(const SkBitmap& bitmap) {
return;
}
- SetResult(base::MakeUnique<base::StringValue>(base64_result));
+ SetResult(base::MakeUnique<base::Value>(base64_result));
SendResponse(true);
}
@@ -1789,7 +1803,7 @@ void TabsDetectLanguageFunction::Observe(
}
void TabsDetectLanguageFunction::GotLanguage(const std::string& language) {
- SetResult(base::MakeUnique<base::StringValue>(language.c_str()));
+ SetResult(base::MakeUnique<base::Value>(language));
SendResponse(true);
Release(); // Balanced in Run()
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 6566c7b444b..bc76ad20066 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
@@ -49,18 +49,17 @@ bool WillDispatchTabUpdatedEvent(
std::unique_ptr<api::tabs::Tab> tab_object =
ExtensionTabUtil::CreateTabObject(contents, extension);
- base::DictionaryValue* tab_value = tab_object->ToValue().release();
+ std::unique_ptr<base::DictionaryValue> tab_value = tab_object->ToValue();
- std::unique_ptr<base::DictionaryValue> changed_properties(
- new base::DictionaryValue);
+ auto changed_properties = base::MakeUnique<base::DictionaryValue>();
const base::Value* value = nullptr;
for (const auto& property : changed_property_names) {
if (tab_value->Get(property, &value))
- changed_properties->Set(property, base::WrapUnique(value->DeepCopy()));
+ changed_properties->Set(property, value->CreateDeepCopy());
}
- event->event_args->Set(1, changed_properties.release());
- event->event_args->Set(2, tab_value);
+ event->event_args->Set(1, std::move(changed_properties));
+ event->event_args->Set(2, std::move(tab_value));
return true;
}
@@ -141,8 +140,7 @@ TabsEventRouter::TabsEventRouter(Profile* profile)
tab_manager_scoped_observer_(this) {
DCHECK(!profile->IsOffTheRecord());
- browser_tab_strip_tracker_.Init(
- BrowserTabStripTracker::InitWith::ALL_BROWERS);
+ browser_tab_strip_tracker_.Init();
tab_manager_scoped_observer_.Add(g_browser_process->GetTabManager());
}
@@ -237,9 +235,11 @@ void TabsEventRouter::TabInsertedAt(TabStripModel* tab_strip_model,
std::unique_ptr<base::DictionaryValue> object_args(
new base::DictionaryValue());
- object_args->Set(tabs_constants::kNewWindowIdKey,
- new Value(ExtensionTabUtil::GetWindowIdOfTab(contents)));
- object_args->Set(tabs_constants::kNewPositionKey, new Value(index));
+ object_args->Set(
+ tabs_constants::kNewWindowIdKey,
+ base::MakeUnique<Value>(ExtensionTabUtil::GetWindowIdOfTab(contents)));
+ object_args->Set(tabs_constants::kNewPositionKey,
+ base::MakeUnique<Value>(index));
args->Append(std::move(object_args));
Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
@@ -258,9 +258,11 @@ void TabsEventRouter::TabDetachedAt(WebContents* contents, int index) {
std::unique_ptr<base::DictionaryValue> object_args(
new base::DictionaryValue());
- object_args->Set(tabs_constants::kOldWindowIdKey,
- new Value(ExtensionTabUtil::GetWindowIdOfTab(contents)));
- object_args->Set(tabs_constants::kOldPositionKey, new Value(index));
+ object_args->Set(
+ tabs_constants::kOldWindowIdKey,
+ base::MakeUnique<Value>(ExtensionTabUtil::GetWindowIdOfTab(contents)));
+ object_args->Set(tabs_constants::kOldPositionKey,
+ base::MakeUnique<Value>(index));
args->Append(std::move(object_args));
Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
@@ -301,7 +303,8 @@ void TabsEventRouter::ActiveTabChanged(WebContents* old_contents,
auto object_args = base::MakeUnique<base::DictionaryValue>();
object_args->Set(tabs_constants::kWindowIdKey,
- new Value(ExtensionTabUtil::GetWindowIdOfTab(new_contents)));
+ base::MakeUnique<Value>(
+ ExtensionTabUtil::GetWindowIdOfTab(new_contents)));
args->Append(object_args->CreateDeepCopy());
// The onActivated event replaced onActiveChanged and onSelectionChanged. The
@@ -320,7 +323,7 @@ void TabsEventRouter::ActiveTabChanged(WebContents* old_contents,
// The onActivated event takes one argument: {windowId, tabId}.
auto on_activated_args = base::MakeUnique<base::ListValue>();
- object_args->Set(tabs_constants::kTabIdKey, new Value(tab_id));
+ object_args->Set(tabs_constants::kTabIdKey, base::MakeUnique<Value>(tab_id));
on_activated_args->Append(std::move(object_args));
DispatchEvent(profile, events::TABS_ON_ACTIVATED,
tabs::OnActivated::kEventName, std::move(on_activated_args),
@@ -348,7 +351,8 @@ void TabsEventRouter::TabSelectionChanged(
select_info->Set(
tabs_constants::kWindowIdKey,
- new Value(ExtensionTabUtil::GetWindowIdOfTabStripModel(tab_strip_model)));
+ base::MakeUnique<Value>(
+ ExtensionTabUtil::GetWindowIdOfTabStripModel(tab_strip_model)));
select_info->Set(tabs_constants::kTabIdsKey, all_tabs.release());
args->Append(std::move(select_info));
@@ -372,10 +376,13 @@ void TabsEventRouter::TabMoved(WebContents* contents,
std::unique_ptr<base::DictionaryValue> object_args(
new base::DictionaryValue());
- object_args->Set(tabs_constants::kWindowIdKey,
- new Value(ExtensionTabUtil::GetWindowIdOfTab(contents)));
- object_args->Set(tabs_constants::kFromIndexKey, new Value(from_index));
- object_args->Set(tabs_constants::kToIndexKey, new Value(to_index));
+ object_args->Set(
+ tabs_constants::kWindowIdKey,
+ base::MakeUnique<Value>(ExtensionTabUtil::GetWindowIdOfTab(contents)));
+ object_args->Set(tabs_constants::kFromIndexKey,
+ base::MakeUnique<Value>(from_index));
+ object_args->Set(tabs_constants::kToIndexKey,
+ base::MakeUnique<Value>(to_index));
args->Append(std::move(object_args));
Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc
index c519fd0c73f..17bc023eabb 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -1242,7 +1242,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, NoTabsAppWindow) {
CloseAppWindow(app_window);
}
-IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, FilteredEvents) {
+// Crashes on Mac/Win only. http://crbug.com/708996
+#if defined(OS_MACOSX)
+#define MAYBE_FilteredEvents DISABLED_FilteredEvents
+#else
+#define MAYBE_FilteredEvents FilteredEvents
+#endif
+
+IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, MAYBE_FilteredEvents) {
extensions::ResultCatcher catcher;
ExtensionTestMessageListener listener("ready", true);
ASSERT_TRUE(
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_windows_api.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_windows_api.cc
index a0efbbfb11a..da01aea1134 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_windows_api.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_windows_api.cc
@@ -68,8 +68,9 @@ void TabsWindowsAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<TabsWindowsAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<TabsWindowsAPI>>::DestructorAtExit g_factory =
+ LAZY_INSTANCE_INITIALIZER;
BrowserContextKeyedAPIFactory<TabsWindowsAPI>*
TabsWindowsAPI::GetFactoryInstance() {
diff --git a/chromium/chrome/browser/extensions/api/virtual_keyboard_private/OWNERS b/chromium/chrome/browser/extensions/api/virtual_keyboard_private/OWNERS
index b925139c866..5af418aa5b6 100644
--- a/chromium/chrome/browser/extensions/api/virtual_keyboard_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/virtual_keyboard_private/OWNERS
@@ -1,3 +1,4 @@
bshe@chromium.org
kevers@chromium.org
+# COMPONENT: UI>Input>VirtualKeyboard
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 7025316c6d4..7633b2ef114 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
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/strings/string16.h"
#include "chrome/browser/chromeos/login/lock/screen_locker.h"
@@ -20,7 +21,6 @@
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/common/url_constants.h"
#include "components/user_manager/user_manager.h"
-#include "content/public/browser/user_metrics.h"
#include "extensions/common/api/virtual_keyboard_private.h"
#include "media/audio/audio_system.h"
#include "ui/aura/window_tree_host.h"
@@ -125,7 +125,7 @@ void ChromeVirtualKeyboardDelegate::SetHotrodKeyboard(bool enable) {
// keyboard gets the correct state of the hotrod keyboard through
// chrome.virtualKeyboardPrivate.getKeyboardConfig.
if (keyboard::IsKeyboardEnabled())
- ash::Shell::GetInstance()->CreateKeyboard();
+ ash::Shell::Get()->CreateKeyboard();
}
void ChromeVirtualKeyboardDelegate::SetKeyboardRestricted(bool restricted) {
@@ -136,7 +136,7 @@ void ChromeVirtualKeyboardDelegate::SetKeyboardRestricted(bool restricted) {
// Force virtual keyboard reload.
if (keyboard::IsKeyboardEnabled())
- ash::Shell::GetInstance()->CreateKeyboard();
+ ash::Shell::Get()->CreateKeyboard();
}
bool ChromeVirtualKeyboardDelegate::LockKeyboard(bool state) {
@@ -163,7 +163,7 @@ bool ChromeVirtualKeyboardDelegate::SendKeyEvent(const std::string& type,
bool ChromeVirtualKeyboardDelegate::ShowLanguageSettings() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- content::RecordAction(base::UserMetricsAction("OpenLanguageOptionsDialog"));
+ base::RecordAction(base::UserMetricsAction("OpenLanguageOptionsDialog"));
chrome::ShowSettingsSubPageForProfile(ProfileManager::GetActiveUserProfile(),
chrome::kLanguageOptionsSubPage);
return true;
@@ -189,11 +189,10 @@ bool ChromeVirtualKeyboardDelegate::SetRequestedKeyboardState(int state_enum) {
bool is_enabled = keyboard::IsKeyboardEnabled();
if (was_enabled == is_enabled)
return true;
- if (is_enabled) {
- ash::Shell::GetInstance()->CreateKeyboard();
- } else {
- ash::Shell::GetInstance()->DeactivateKeyboard();
- }
+ if (is_enabled)
+ ash::Shell::Get()->CreateKeyboard();
+ else
+ ash::Shell::Get()->DeactivateKeyboard();
return true;
}
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 2616a7568fd..2cc3ea482ff 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
@@ -7,12 +7,12 @@
#include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/web_navigation/web_navigation_api_constants.h"
#include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/tab_contents/retargeting_details.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/extensions/api/web_navigation.h"
@@ -45,7 +45,7 @@ namespace {
typedef std::map<content::WebContents*, WebNavigationTabObserver*>
TabObserverMap;
-static base::LazyInstance<TabObserverMap> g_tab_observer =
+static base::LazyInstance<TabObserverMap>::DestructorAtExit g_tab_observer =
LAZY_INSTANCE_INITIALIZER;
} // namespace
@@ -76,17 +76,13 @@ WebNavigationEventRouter::WebNavigationEventRouter(Profile* profile)
: profile_(profile), browser_tab_strip_tracker_(this, this, nullptr) {
CHECK(registrar_.IsEmpty());
registrar_.Add(this,
- chrome::NOTIFICATION_RETARGETING,
- content::NotificationService::AllSources());
- registrar_.Add(this,
chrome::NOTIFICATION_TAB_ADDED,
content::NotificationService::AllSources());
registrar_.Add(this,
content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
content::NotificationService::AllSources());
- browser_tab_strip_tracker_.Init(
- BrowserTabStripTracker::InitWith::ALL_BROWERS);
+ browser_tab_strip_tracker_.Init();
}
WebNavigationEventRouter::~WebNavigationEventRouter() {
@@ -121,14 +117,6 @@ void WebNavigationEventRouter::Observe(
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
- case chrome::NOTIFICATION_RETARGETING: {
- Profile* profile = content::Source<Profile>(source).ptr();
- if (profile->GetOriginalProfile() == profile_) {
- Retargeting(
- content::Details<const RetargetingDetails>(details).ptr());
- }
- break;
- }
case chrome::NOTIFICATION_TAB_ADDED:
TabAdded(content::Details<content::WebContents>(details).ptr());
@@ -143,40 +131,40 @@ void WebNavigationEventRouter::Observe(
}
}
-void WebNavigationEventRouter::Retargeting(const RetargetingDetails* details) {
- if (details->source_render_frame_id == 0)
+void WebNavigationEventRouter::RecordNewWebContents(
+ content::WebContents* source_web_contents,
+ int source_render_process_id,
+ int source_render_frame_id,
+ GURL target_url,
+ content::WebContents* target_web_contents,
+ bool not_yet_in_tabstrip) {
+ if (source_render_frame_id == 0)
return;
WebNavigationTabObserver* tab_observer =
- WebNavigationTabObserver::Get(details->source_web_contents);
+ WebNavigationTabObserver::Get(source_web_contents);
if (!tab_observer) {
// If you hit this DCHECK(), please add reproduction steps to
// http://crbug.com/109464.
- DCHECK(GetViewType(details->source_web_contents) != VIEW_TYPE_TAB_CONTENTS);
+ DCHECK(GetViewType(source_web_contents) != VIEW_TYPE_TAB_CONTENTS);
return;
}
const FrameNavigationState& frame_navigation_state =
tab_observer->frame_navigation_state();
content::RenderFrameHost* frame_host = content::RenderFrameHost::FromID(
- details->source_render_process_id, details->source_render_frame_id);
+ source_render_process_id, source_render_frame_id);
if (!frame_navigation_state.CanSendEvents(frame_host))
return;
// If the WebContents isn't yet inserted into a tab strip, we need to delay
// the extension event until the WebContents is fully initialized.
- if (details->not_yet_in_tabstrip) {
- pending_web_contents_[details->target_web_contents] =
- PendingWebContents(details->source_web_contents,
- frame_host,
- details->target_web_contents,
- details->target_url);
+ if (not_yet_in_tabstrip) {
+ pending_web_contents_[target_web_contents] = PendingWebContents(
+ source_web_contents, frame_host, target_web_contents, target_url);
} else {
helpers::DispatchOnCreatedNavigationTarget(
- details->source_web_contents,
- details->target_web_contents->GetBrowserContext(),
- frame_host,
- details->target_web_contents,
- details->target_url);
+ source_web_contents, target_web_contents->GetBrowserContext(),
+ frame_host, target_web_contents, target_url);
}
}
@@ -266,7 +254,7 @@ void WebNavigationTabObserver::RenderFrameHostChanged(
void WebNavigationTabObserver::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
- if (navigation_handle->IsSamePage() ||
+ if (navigation_handle->IsSameDocument() ||
!FrameNavigationState::IsValidUrl(navigation_handle->GetURL())) {
return;
}
@@ -384,7 +372,8 @@ void WebNavigationTabObserver::DidOpenRequestedURL(
const content::Referrer& referrer,
WindowOpenDisposition disposition,
ui::PageTransition transition,
- bool started_from_context_menu) {
+ bool started_from_context_menu,
+ bool renderer_initiated) {
if (!navigation_state_.CanSendEvents(source_render_frame_host))
return;
@@ -398,11 +387,16 @@ void WebNavigationTabObserver::DidOpenRequestedURL(
disposition != WindowOpenDisposition::OFF_THE_RECORD)
return;
- helpers::DispatchOnCreatedNavigationTarget(web_contents(),
- new_contents->GetBrowserContext(),
- source_render_frame_host,
- new_contents,
- url);
+ WebNavigationAPI* api = WebNavigationAPI::GetFactoryInstance()->Get(
+ web_contents()->GetBrowserContext());
+ WebNavigationEventRouter* router = api->web_navigation_event_router_.get();
+ if (!router)
+ return;
+
+ router->RecordNewWebContents(web_contents(),
+ source_render_frame_host->GetProcess()->GetID(),
+ source_render_frame_host->GetRoutingID(), url,
+ new_contents, renderer_initiated);
}
void WebNavigationTabObserver::WebContentsDestroyed() {
@@ -428,7 +422,7 @@ void WebNavigationTabObserver::HandleCommit(
navigation_state_.StartTrackingDocumentLoad(
navigation_handle->GetRenderFrameHost(), navigation_handle->GetURL(),
- navigation_handle->IsSamePage(),
+ navigation_handle->IsSameDocument(),
false); // is_error_page
events::HistogramValue histogram_value = events::UNKNOWN;
@@ -436,7 +430,7 @@ void WebNavigationTabObserver::HandleCommit(
if (is_reference_fragment_navigation) {
histogram_value = events::WEB_NAVIGATION_ON_REFERENCE_FRAGMENT_UPDATED;
event_name = web_navigation::OnReferenceFragmentUpdated::kEventName;
- } else if (navigation_handle->IsSamePage()) {
+ } else if (navigation_handle->IsSameDocument()) {
histogram_value = events::WEB_NAVIGATION_ON_HISTORY_STATE_UPDATED;
event_name = web_navigation::OnHistoryStateUpdated::kEventName;
} else {
@@ -451,7 +445,7 @@ void WebNavigationTabObserver::HandleError(
if (navigation_handle->HasCommitted()) {
navigation_state_.StartTrackingDocumentLoad(
navigation_handle->GetRenderFrameHost(), navigation_handle->GetURL(),
- navigation_handle->IsSamePage(),
+ navigation_handle->IsSameDocument(),
true); // is_error_page
}
@@ -483,7 +477,7 @@ ExtensionFunction::ResponseAction WebNavigationGetFrameFunction::Run() {
include_incognito(), nullptr, nullptr,
&web_contents, nullptr) ||
!web_contents) {
- return RespondNow(OneArgument(base::Value::CreateNullValue()));
+ return RespondNow(OneArgument(base::MakeUnique<base::Value>()));
}
WebNavigationTabObserver* observer =
@@ -497,11 +491,11 @@ ExtensionFunction::ResponseAction WebNavigationGetFrameFunction::Run() {
ExtensionApiFrameIdMap::Get()->GetRenderFrameHostById(web_contents,
frame_id);
if (!frame_navigation_state.IsValidFrame(render_frame_host))
- return RespondNow(OneArgument(base::Value::CreateNullValue()));
+ return RespondNow(OneArgument(base::MakeUnique<base::Value>()));
GURL frame_url = frame_navigation_state.GetUrl(render_frame_host);
if (!frame_navigation_state.IsValidUrl(frame_url))
- return RespondNow(OneArgument(base::Value::CreateNullValue()));
+ return RespondNow(OneArgument(base::MakeUnique<base::Value>()));
GetFrame::Results::Details frame_details;
frame_details.url = frame_url.spec();
@@ -523,7 +517,7 @@ ExtensionFunction::ResponseAction WebNavigationGetAllFramesFunction::Run() {
include_incognito(), nullptr, nullptr,
&web_contents, nullptr) ||
!web_contents) {
- return RespondNow(OneArgument(base::Value::CreateNullValue()));
+ return RespondNow(OneArgument(base::MakeUnique<base::Value>()));
}
WebNavigationTabObserver* observer =
@@ -579,8 +573,8 @@ void WebNavigationAPI::Shutdown() {
EventRouter::Get(browser_context_)->UnregisterObserver(this);
}
-static base::LazyInstance<BrowserContextKeyedAPIFactory<WebNavigationAPI> >
- g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<BrowserContextKeyedAPIFactory<WebNavigationAPI>>::
+ DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<WebNavigationAPI>*
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
index e467d996d21..35b22af8ce6 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
@@ -27,8 +27,6 @@
#include "extensions/browser/event_router.h"
#include "url/gurl.h"
-struct RetargetingDetails;
-
namespace extensions {
// Tab contents observer that forwards navigation events to the event router.
@@ -69,7 +67,8 @@ class WebNavigationTabObserver
const content::Referrer& referrer,
WindowOpenDisposition disposition,
ui::PageTransition transition,
- bool started_from_context_menu) override;
+ bool started_from_context_menu,
+ bool renderer_initiated) override;
void WebContentsDestroyed() override;
// This method dispatches the already created onBeforeNavigate event.
@@ -119,6 +118,17 @@ class WebNavigationEventRouter : public TabStripModelObserver,
explicit WebNavigationEventRouter(Profile* profile);
~WebNavigationEventRouter() override;
+ // Router level handler for the creation of WebContents. Stores information
+ // about the newly created WebContents. This information is later used when
+ // the WebContents for the tab is added to the tabstrip and we receive the
+ // TAB_ADDED notification.
+ void RecordNewWebContents(content::WebContents* source_web_contents,
+ int source_render_process_id,
+ int source_render_frame_id,
+ GURL target_url,
+ content::WebContents* target_web_contents,
+ bool not_yet_in_tabstrip);
+
private:
// Used to cache the information about newly created WebContents objects.
struct PendingWebContents{
@@ -149,11 +159,6 @@ class WebNavigationEventRouter : public TabStripModelObserver,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
- // Handler for the NOTIFICATION_RETARGETING event. The method takes the
- // details of such an event and stores them for the later
- // NOTIFICATION_TAB_ADDED event.
- void Retargeting(const RetargetingDetails* details);
-
// Handler for the NOTIFICATION_TAB_ADDED event. The method takes the details
// of such an event and creates a JSON formated extension event from it.
void TabAdded(content::WebContents* tab);
@@ -209,6 +214,7 @@ class WebNavigationAPI : public BrowserContextKeyedAPI,
private:
friend class BrowserContextKeyedAPIFactory<WebNavigationAPI>;
+ friend class WebNavigationTabObserver;
content::BrowserContext* browser_context_;
@@ -216,6 +222,7 @@ class WebNavigationAPI : public BrowserContextKeyedAPI,
static const char* service_name() {
return "WebNavigationAPI";
}
+ static const bool kServiceRedirectedInIncognito = true;
static const bool kServiceIsNULLWhileTesting = true;
// Created lazily upon OnListenerAdded.
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
index ac74ce13664..e80814a4ae6 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -124,7 +125,7 @@ void DispatchOnCommitted(events::HistogramValue histogram_value,
ui::PAGE_TRANSITION_AUTO_TOPLEVEL))
transition_type_string = "start_page";
dict->SetString(keys::kTransitionTypeKey, transition_type_string);
- base::ListValue* qualifiers = new base::ListValue();
+ auto qualifiers = base::MakeUnique<base::ListValue>();
if (transition_type & ui::PAGE_TRANSITION_CLIENT_REDIRECT)
qualifiers->AppendString("client_redirect");
if (transition_type & ui::PAGE_TRANSITION_SERVER_REDIRECT)
@@ -133,7 +134,7 @@ void DispatchOnCommitted(events::HistogramValue histogram_value,
qualifiers->AppendString("forward_back");
if (transition_type & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)
qualifiers->AppendString("from_address_bar");
- dict->Set(keys::kTransitionQualifiersKey, qualifiers);
+ dict->Set(keys::kTransitionQualifiersKey, std::move(qualifiers));
dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
args->Append(std::move(dict));
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index be07e4d4cf5..6e771349495 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -454,6 +454,8 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ServerRedirectSingleProcess) {
}
IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ForwardBack) {
+ if (content::IsBrowserSideNavigationEnabled())
+ return; // TODO(jam): investigate
ASSERT_TRUE(StartEmbeddedTestServer());
ASSERT_TRUE(RunExtensionTest("webnavigation/forwardBack")) << message_;
}
@@ -529,7 +531,7 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_UserAction) {
// This corresponds to "Open link in new tab".
content::ContextMenuParams params;
params.is_editable = false;
- params.media_type = blink::WebContextMenuData::MediaTypeNone;
+ params.media_type = blink::WebContextMenuData::kMediaTypeNone;
params.page_url = url;
params.link_url = extension->GetResourceURL("b.html");
@@ -567,15 +569,14 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, RequestOpenTab) {
ui_test_utils::NavigateToURL(browser(), url);
// There's a link on a.html. Middle-click on it to open it in a new tab.
- blink::WebMouseEvent mouse_event(blink::WebInputEvent::MouseDown,
- blink::WebInputEvent::NoModifiers,
- blink::WebInputEvent::TimeStampForTesting);
- mouse_event.button = blink::WebMouseEvent::Button::Middle;
- mouse_event.x = 7;
- mouse_event.y = 7;
- mouse_event.clickCount = 1;
+ blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ mouse_event.button = blink::WebMouseEvent::Button::kMiddle;
+ mouse_event.SetPositionInWidget(7, 7);
+ mouse_event.click_count = 1;
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
- mouse_event.setType(blink::WebInputEvent::MouseUp);
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
@@ -600,15 +601,14 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, TargetBlank) {
// There's a link with target=_blank on a.html. Click on it to open it in a
// new tab.
- blink::WebMouseEvent mouse_event(blink::WebInputEvent::MouseDown,
- blink::WebInputEvent::NoModifiers,
- blink::WebInputEvent::TimeStampForTesting);
- mouse_event.button = blink::WebMouseEvent::Button::Left;
- mouse_event.x = 7;
- mouse_event.y = 7;
- mouse_event.clickCount = 1;
+ blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ mouse_event.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_event.SetPositionInWidget(7, 7);
+ mouse_event.click_count = 1;
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
- mouse_event.setType(blink::WebInputEvent::MouseUp);
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
@@ -631,15 +631,14 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, TargetBlankIncognito) {
// There's a link with target=_blank on a.html. Click on it to open it in a
// new tab.
- blink::WebMouseEvent mouse_event(blink::WebInputEvent::MouseDown,
- blink::WebInputEvent::NoModifiers,
- blink::WebInputEvent::TimeStampForTesting);
- mouse_event.button = blink::WebMouseEvent::Button::Left;
- mouse_event.x = 7;
- mouse_event.y = 7;
- mouse_event.clickCount = 1;
+ blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ mouse_event.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_event.SetPositionInWidget(7, 7);
+ mouse_event.click_count = 1;
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
- mouse_event.setType(blink::WebInputEvent::MouseUp);
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
@@ -726,7 +725,8 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessAbort) {
ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
}
-IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessFragment) {
+// crbug.com/708139.
+IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, DISABLED_CrossProcessFragment) {
ASSERT_TRUE(StartEmbeddedTestServer());
// See crossProcessFragment/f.html.
@@ -747,7 +747,8 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessFragment) {
<< message_;
}
-IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, CrossProcessHistory) {
+// crbug.com/708139.
+IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, DISABLED_CrossProcessHistory) {
ASSERT_TRUE(StartEmbeddedTestServer());
// See crossProcessHistory/e.html.
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 c74a5711c5c..f40e178c2fa 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
@@ -27,6 +27,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/values.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/extensions/event_router_forwarder.h"
#include "chrome/browser/net/chrome_extensions_network_delegate.h"
@@ -56,6 +57,7 @@
#include "net/dns/mock_host_resolver.h"
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest-message.h"
@@ -65,10 +67,8 @@ namespace helpers = extension_web_request_api_helpers;
namespace keys = extension_web_request_api_constants;
namespace web_request = extensions::api::web_request;
-using base::BinaryValue;
using base::DictionaryValue;
using base::ListValue;
-using base::StringValue;
using base::Time;
using base::TimeDelta;
using base::Value;
@@ -250,8 +250,9 @@ TEST_F(ExtensionWebRequestTest, BlockingEventPrecedenceRedirect) {
GURL redirect_url("about:redirected");
GURL not_chosen_redirect_url("about:not_chosen");
- std::unique_ptr<net::URLRequest> request(context_->CreateRequest(
- GURL("about:blank"), net::DEFAULT_PRIORITY, &delegate_));
+ std::unique_ptr<net::URLRequest> request(
+ context_->CreateRequest(GURL("about:blank"), net::DEFAULT_PRIORITY,
+ &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
{
// onBeforeRequest will be dispatched twice initially. The second response -
// the redirect - should win, since it has a later |install_time|. The
@@ -304,8 +305,9 @@ TEST_F(ExtensionWebRequestTest, BlockingEventPrecedenceRedirect) {
}
// Now test the same thing but the extensions answer in reverse order.
- std::unique_ptr<net::URLRequest> request2(context_->CreateRequest(
- GURL("about:blank"), net::DEFAULT_PRIORITY, &delegate_));
+ std::unique_ptr<net::URLRequest> request2(
+ context_->CreateRequest(GURL("about:blank"), net::DEFAULT_PRIORITY,
+ &delegate_, TRAFFIC_ANNOTATION_FOR_TESTS));
{
ExtensionWebRequestEventRouter::EventResponse* response = NULL;
@@ -382,7 +384,8 @@ TEST_F(ExtensionWebRequestTest, BlockingEventPrecedenceCancel) {
GURL request_url("about:blank");
std::unique_ptr<net::URLRequest> request(
- context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_));
+ context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
// onBeforeRequest will be dispatched twice. The second response -
// the redirect - would win, since it has a later |install_time|, but
@@ -453,7 +456,8 @@ TEST_F(ExtensionWebRequestTest, SimulateChancelWhileBlocked) {
GURL request_url("about:blank");
std::unique_ptr<net::URLRequest> request(
- context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_));
+ context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
ExtensionWebRequestEventRouter::EventResponse* response = NULL;
@@ -521,7 +525,8 @@ void ExtensionWebRequestTest::FireURLRequestWithData(
// The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
GURL request_url("http://www.example.com");
std::unique_ptr<net::URLRequest> request(
- context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_));
+ context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
request->set_method(method);
if (content_type != NULL) {
request->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kContentType,
@@ -605,15 +610,13 @@ TEST_F(ExtensionWebRequestTest, AccessRequestBodyData) {
base::ListValue raw;
extensions::subtle::AppendKeyValuePair(
keys::kRequestBodyRawBytesKey,
- BinaryValue::CreateWithCopiedBuffer(kPlainBlock1, kPlainBlock1Length),
- &raw);
+ Value::CreateWithCopiedBuffer(kPlainBlock1, kPlainBlock1Length), &raw);
extensions::subtle::AppendKeyValuePair(
keys::kRequestBodyRawFileKey,
- base::MakeUnique<base::StringValue>(std::string()), &raw);
+ base::MakeUnique<base::Value>(std::string()), &raw);
extensions::subtle::AppendKeyValuePair(
keys::kRequestBodyRawBytesKey,
- BinaryValue::CreateWithCopiedBuffer(kPlainBlock2, kPlainBlock2Length),
- &raw);
+ Value::CreateWithCopiedBuffer(kPlainBlock2, kPlainBlock2Length), &raw);
// Summary.
const base::Value* const kExpected[] = {
form_data.get(),
@@ -824,8 +827,9 @@ TEST_F(ExtensionWebRequestTest, NoAccessRequestBodyData) {
const GURL request_url("http://www.example.com");
for (size_t i = 0; i < arraysize(kMethods); ++i) {
- std::unique_ptr<net::URLRequest> request(context_->CreateRequest(
- request_url, net::DEFAULT_PRIORITY, &delegate_));
+ std::unique_ptr<net::URLRequest> request(
+ context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
request->set_method(kMethods[i]);
ipc_sender_.PushTask(base::Bind(&base::DoNothing));
request->Start();
@@ -921,7 +925,8 @@ TEST_F(ExtensionWebRequestTest, BlockedRequestsAreRemoved) {
// Send a request. It should block. Wait for the run loop to become idle.
GURL request_url("about:blank");
std::unique_ptr<net::URLRequest> request(
- context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_));
+ context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
// Extension response for OnErrorOccurred: Terminate the message loop.
{
base::RunLoop run_loop;
@@ -1054,7 +1059,8 @@ TEST_P(ExtensionWebRequestHeaderModificationTest, TestModifications) {
GURL request_url("http://doesnotexist/does_not_exist.html");
std::unique_ptr<net::URLRequest> request(
- context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_));
+ context_->CreateRequest(request_url, net::DEFAULT_PRIORITY, &delegate_,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
// Initialize headers available before extensions are notified of the
// onBeforeSendHeaders event.
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 9c020f87a67..542a44c7332 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
@@ -274,15 +274,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestNewTab) {
// There's a link on a.html with target=_blank. Click on it to open it in a
// new tab.
- blink::WebMouseEvent mouse_event(blink::WebInputEvent::MouseDown,
- blink::WebInputEvent::NoModifiers,
- blink::WebInputEvent::TimeStampForTesting);
- mouse_event.button = blink::WebMouseEvent::Button::Left;
- mouse_event.x = 7;
- mouse_event.y = 7;
- mouse_event.clickCount = 1;
+ blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown,
+ blink::WebInputEvent::kNoModifiers,
+ blink::WebInputEvent::kTimeStampForTesting);
+ mouse_event.button = blink::WebMouseEvent::Button::kLeft;
+ mouse_event.SetPositionInWidget(7, 7);
+ mouse_event.click_count = 1;
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
- mouse_event.setType(blink::WebInputEvent::MouseUp);
+ mouse_event.SetType(blink::WebInputEvent::kMouseUp);
tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
index 3682c629d20..af3259ef7a6 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
@@ -19,6 +19,7 @@
#include "extensions/common/permissions/permissions_data.h"
#include "ipc/ipc_message.h"
#include "net/base/request_priority.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -122,7 +123,8 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, TestHideRequestForURL) {
for (size_t i = 0; i < arraysize(sensitive_urls); ++i) {
GURL sensitive_url(sensitive_urls[i]);
std::unique_ptr<net::URLRequest> request(
- context.CreateRequest(sensitive_url, net::DEFAULT_PRIORITY, NULL));
+ context.CreateRequest(sensitive_url, net::DEFAULT_PRIORITY, NULL,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_TRUE(WebRequestPermissions::HideRequest(
extension_info_map_.get(), request.get(), nullptr)) <<
sensitive_urls[i];
@@ -131,7 +133,8 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, TestHideRequestForURL) {
for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) {
GURL non_sensitive_url(non_sensitive_urls[i]);
std::unique_ptr<net::URLRequest> request(
- context.CreateRequest(non_sensitive_url, net::DEFAULT_PRIORITY, NULL));
+ context.CreateRequest(non_sensitive_url, net::DEFAULT_PRIORITY, NULL,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_FALSE(WebRequestPermissions::HideRequest(
extension_info_map_.get(), request.get(), nullptr)) <<
non_sensitive_urls[i];
@@ -142,7 +145,8 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, TestHideRequestForURL) {
// Normally this request is not protected:
GURL non_sensitive_url("http://www.google.com/test.js");
std::unique_ptr<net::URLRequest> non_sensitive_request(
- context.CreateRequest(non_sensitive_url, net::DEFAULT_PRIORITY, NULL));
+ context.CreateRequest(non_sensitive_url, net::DEFAULT_PRIORITY, NULL,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_FALSE(WebRequestPermissions::HideRequest(
extension_info_map_.get(), non_sensitive_request.get(), nullptr));
// If the origin is labeled by the WebStoreAppId, it becomes protected.
@@ -151,7 +155,8 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, TestHideRequestForURL) {
int site_instance_id = 23;
int view_id = 17;
std::unique_ptr<net::URLRequest> sensitive_request(
- context.CreateRequest(non_sensitive_url, net::DEFAULT_PRIORITY, NULL));
+ context.CreateRequest(non_sensitive_url, net::DEFAULT_PRIORITY, NULL,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
ResourceRequestInfo::AllocateForTesting(
sensitive_request.get(), content::RESOURCE_TYPE_SCRIPT, NULL,
process_id, view_id, MSG_ROUTING_NONE,
@@ -168,8 +173,9 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, TestHideRequestForURL) {
TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest,
TestCanExtensionAccessURL_HostPermissions) {
- std::unique_ptr<net::URLRequest> request(context.CreateRequest(
- GURL("http://example.com"), net::DEFAULT_PRIORITY, NULL));
+ std::unique_ptr<net::URLRequest> request(
+ context.CreateRequest(GURL("http://example.com"), net::DEFAULT_PRIORITY,
+ NULL, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(PermissionsData::ACCESS_ALLOWED,
WebRequestPermissions::CanExtensionAccessURL(
@@ -237,8 +243,9 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest,
WebRequestPermissions::REQUIRE_ALL_URLS));
// Make sure that chrome:// URLs cannot be accessed.
- std::unique_ptr<net::URLRequest> chrome_request(context.CreateRequest(
- GURL("chrome://version/"), net::DEFAULT_PRIORITY, nullptr));
+ std::unique_ptr<net::URLRequest> chrome_request(
+ context.CreateRequest(GURL("chrome://version/"), net::DEFAULT_PRIORITY,
+ nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
EXPECT_EQ(PermissionsData::ACCESS_DENIED,
WebRequestPermissions::CanExtensionAccessURL(
diff --git a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
index edc852f6c1a..d6a643be519 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
@@ -4,12 +4,14 @@
#include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h"
+#include <memory>
#include <utility>
#include <vector>
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_tab_util.h"
@@ -36,8 +38,8 @@ namespace wap = api::webrtc_audio_private;
using api::webrtc_audio_private::RequestInfo;
-static base::LazyInstance<
- BrowserContextKeyedAPIFactory<WebrtcAudioPrivateEventService> > g_factory =
+static base::LazyInstance<BrowserContextKeyedAPIFactory<
+ WebrtcAudioPrivateEventService>>::DestructorAtExit g_factory =
LAZY_INSTANCE_INITIALIZER;
WebrtcAudioPrivateEventService::WebrtcAudioPrivateEventService(
@@ -217,6 +219,43 @@ std::string WebrtcAudioPrivateFunction::device_id_salt() const {
return device_id_salt_;
}
+// TODO(hlundin): Stolen from WebrtcLoggingPrivateFunction.
+// Consolidate and improve. http://crbug.com/710371
+content::RenderProcessHost*
+WebrtcAudioPrivateFunction::GetRenderProcessHostFromRequest(
+ const RequestInfo& request,
+ const std::string& security_origin) {
+ // If |guest_process_id| is defined, directly use this id to find the
+ // corresponding RenderProcessHost.
+ if (request.guest_process_id)
+ return content::RenderProcessHost::FromID(*request.guest_process_id);
+
+ // Otherwise, use the |tab_id|. If there's no |tab_id| and no
+ // |guest_process_id|, we can't look up the RenderProcessHost.
+ if (!request.tab_id) {
+ error_ = "No tab ID or guest process ID specified.";
+ return nullptr;
+ }
+
+ int tab_id = *request.tab_id;
+ content::WebContents* contents = nullptr;
+ if (!ExtensionTabUtil::GetTabById(tab_id, GetProfile(), true, nullptr,
+ nullptr, &contents, nullptr)) {
+ error_ = extensions::ErrorUtils::FormatErrorMessage(
+ extensions::tabs_constants::kTabNotFoundError,
+ base::IntToString(tab_id));
+ return nullptr;
+ }
+ GURL expected_origin = contents->GetLastCommittedURL().GetOrigin();
+ if (expected_origin.spec() != security_origin) {
+ error_ = base::StringPrintf(
+ "Invalid security origin. Expected=%s, actual=%s",
+ expected_origin.spec().c_str(), security_origin.c_str());
+ return nullptr;
+ }
+ return contents->GetRenderProcessHost();
+}
+
bool WebrtcAudioPrivateGetSinksFunction::RunAsync() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -504,4 +543,31 @@ void WebrtcAudioPrivateGetAssociatedSinkFunction::OnHMACCalculated(
SendResponse(true);
}
+WebrtcAudioPrivateSetAudioExperimentsFunction::
+ WebrtcAudioPrivateSetAudioExperimentsFunction() {}
+
+WebrtcAudioPrivateSetAudioExperimentsFunction::
+ ~WebrtcAudioPrivateSetAudioExperimentsFunction() {}
+
+bool WebrtcAudioPrivateSetAudioExperimentsFunction::RunAsync() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ std::unique_ptr<wap::SetAudioExperiments::Params> params(
+ wap::SetAudioExperiments::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ if (params->audio_experiments.enable_aec3.get()) {
+ content::RenderProcessHost* host = GetRenderProcessHostFromRequest(
+ params->request, params->security_origin);
+ if (!host) {
+ SendResponse(false);
+ return false;
+ }
+
+ host->SetEchoCanceller3(*params->audio_experiments.enable_aec3);
+ }
+
+ SendResponse(true);
+ return true;
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h
index fda70d7faee..279c20238f6 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h
+++ b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h
@@ -101,6 +101,13 @@ class WebrtcAudioPrivateFunction : public ChromeAsyncExtensionFunction {
// |InitDeviceIDSalt()|.
std::string device_id_salt() const;
+ // Returns the RenderProcessHost associated with the given |request|
+ // authorized by the |security_origin|. Returns null if unauthorized or
+ // the RPH does not exist.
+ content::RenderProcessHost* GetRenderProcessHostFromRequest(
+ const api::webrtc_audio_private::RequestInfo& request,
+ const std::string& security_origin);
+
private:
std::string device_id_salt_;
@@ -227,6 +234,21 @@ class WebrtcAudioPrivateGetAssociatedSinkFunction
media::AudioDeviceDescriptions source_devices_;
};
+class WebrtcAudioPrivateSetAudioExperimentsFunction
+ : public WebrtcAudioPrivateFunction {
+ public:
+ WebrtcAudioPrivateSetAudioExperimentsFunction();
+
+ protected:
+ ~WebrtcAudioPrivateSetAudioExperimentsFunction() override;
+
+ private:
+ DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.setAudioExperiments",
+ WEBRTC_AUDIO_PRIVATE_SET_AUDIO_EXPERIMENTS);
+
+ bool RunAsync() override;
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_WEBRTC_AUDIO_PRIVATE_WEBRTC_AUDIO_PRIVATE_API_H_
diff --git a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
index 924d427d576..0be10ce1e7a 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -369,14 +369,7 @@ IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAssociatedSink) {
}
}
-// Times out frequently on Windows, CrOS: http://crbug.com/517112
-#if defined(OS_WIN) || defined(OS_CHROMEOS)
-#define MAYBE_TriggerEvent DISABLED_TriggerEvent
-#else
-#define MAYBE_TriggerEvent TriggerEvent
-#endif
-
-IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, MAYBE_TriggerEvent) {
+IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, TriggerEvent) {
WebrtcAudioPrivateEventService* service =
WebrtcAudioPrivateEventService::GetFactoryInstance()->Get(profile());
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
index 5d6f56959cf..9acfef5372f 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -56,6 +56,8 @@ std::string HashIdWithOrigin(const std::string& security_origin,
}
} // namespace
+// TODO(hlundin): Consolidate with WebrtcAudioPrivateFunction and improve.
+// http://crbug.com/710371
content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest(
const RequestInfo& request, const std::string& security_origin) {
// If |guest_process_id| is defined, directly use this id to find the
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 9f33b6887a4..bb9113bfd4f 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
@@ -122,8 +122,8 @@ api::webstore_private::Result WebstoreInstallHelperResultToApiResult(
return api::webstore_private::RESULT_NONE;
}
-static base::LazyInstance<PendingApprovals> g_pending_approvals =
- LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<PendingApprovals>::DestructorAtExit
+ g_pending_approvals = LAZY_INSTANCE_INITIALIZER;
// A preference set by the web store to indicate login information for
// purchased apps.
@@ -545,7 +545,7 @@ ExtensionFunction::ResponseAction WebstorePrivateSetStoreLoginFunction::Run() {
WebstorePrivateGetWebGLStatusFunction::WebstorePrivateGetWebGLStatusFunction()
: feature_checker_(content::GpuFeatureChecker::Create(
- gpu::GPU_FEATURE_TYPE_WEBGL,
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL,
base::Bind(&WebstorePrivateGetWebGLStatusFunction::OnFeatureCheck,
base::Unretained(this)))) {}
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 a0a30f852d8..4dd5d71b1f9 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
@@ -31,7 +31,6 @@
#include "extensions/browser/extension_system.h"
#include "extensions/browser/install/extension_install_ui.h"
#include "gpu/config/gpu_feature_type.h"
-#include "gpu/config/gpu_info.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "ui/gl/gl_switches.h"
@@ -40,8 +39,6 @@
#include "chrome/browser/supervised_user/supervised_user_constants.h"
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
-using gpu::GpuFeatureType;
-
namespace utils = extension_function_test_utils;
namespace extensions {
@@ -414,24 +411,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Allowed) {
// Tests getWebGLStatus function when WebGL is blacklisted.
IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Blocked) {
- static const std::string json_blacklist =
- "{\n"
- " \"name\": \"gpu blacklist\",\n"
- " \"version\": \"1.0\",\n"
- " \"entries\": [\n"
- " {\n"
- " \"id\": 1,\n"
- " \"features\": [\n"
- " \"webgl\"\n"
- " ]\n"
- " }\n"
- " ]\n"
- "}";
- gpu::GPUInfo gpu_info;
- content::GpuDataManager::GetInstance()->InitializeForTesting(
- json_blacklist, gpu_info);
+ content::GpuDataManager::GetInstance()->BlacklistWebGLForTesting();
EXPECT_TRUE(content::GpuDataManager::GetInstance()->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_WEBGL));
+ gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL));
bool webgl_allowed = false;
RunTest(webgl_allowed);
diff --git a/chromium/chrome/browser/media/router/BUILD.gn b/chromium/chrome/browser/media/router/BUILD.gn
index 5e728ee6b95..5749c9b91d6 100644
--- a/chromium/chrome/browser/media/router/BUILD.gn
+++ b/chromium/chrome/browser/media/router/BUILD.gn
@@ -8,12 +8,14 @@ import("//testing/test.gni")
static_library("router") {
deps = [
+ ":mojo_bindings_common",
"//base",
"//chrome/common:constants",
"//components/keyed_service/content",
"//components/keyed_service/core",
"//content/public/browser",
"//content/public/common",
+ "//net",
"//third_party/icu",
"//url",
]
@@ -22,6 +24,8 @@ static_library("router") {
"browser_presentation_connection_proxy.h",
"create_presentation_connection_request.cc",
"create_presentation_connection_request.h",
+ "discovery/media_sink_internal.cc",
+ "discovery/media_sink_internal.h",
"issue.cc",
"issue.h",
"issue_manager.cc",
@@ -51,6 +55,10 @@ static_library("router") {
"media_source.h",
"media_source_helper.cc",
"media_source_helper.h",
+ "media_status.cc",
+ "media_status.h",
+ "mojo/media_route_controller.cc",
+ "mojo/media_route_controller.h",
"offscreen_presentation_manager.cc",
"offscreen_presentation_manager.h",
"offscreen_presentation_manager_factory.cc",
@@ -77,6 +85,7 @@ static_library("router") {
if (!is_android) {
deps += [
":mojo_bindings",
+ "discovery",
"//extensions/browser",
"//mojo/public/cpp/bindings",
]
@@ -97,17 +106,41 @@ static_library("router") {
}
}
+mojom("mojo_bindings_common") {
+ sources = [
+ "mojo/media_controller.mojom",
+ "mojo/media_status.mojom",
+ ]
+
+ public_deps = [
+ "//mojo/common:common_custom_types",
+ ]
+}
+
mojom("mojo_bindings") {
sources = [
"mojo/media_router.mojom",
]
public_deps = [
+ ":mojo_bindings_common",
"//mojo/common:common_custom_types",
+ "//net/interfaces:interfaces",
+ "//url/mojo:url_mojom_gurl",
"//url/mojo:url_mojom_origin",
]
}
+mojom("mojo_test_interfaces") {
+ sources = [
+ "mojo/media_router_traits_test_service.mojom",
+ ]
+
+ public_deps = [
+ ":mojo_bindings",
+ ]
+}
+
static_library("test_support") {
testonly = true
deps = [
@@ -127,6 +160,7 @@ static_library("test_support") {
if (!is_android) {
deps += [
":mojo_bindings",
+ ":mojo_test_interfaces",
"//extensions/common",
]
sources += [
diff --git a/chromium/chrome/browser/media/router/discovery/BUILD.gn b/chromium/chrome/browser/media/router/discovery/BUILD.gn
new file mode 100644
index 00000000000..3115fe58610
--- /dev/null
+++ b/chromium/chrome/browser/media/router/discovery/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+static_library("discovery") {
+ inputs = [
+ "$root_gen_dir/chrome/grit/generated_resources.h",
+ ]
+ deps = [
+ "//base",
+ "//base:i18n",
+ "//chrome/app:generated_resources",
+ "//chrome/common:constants",
+ "//content/public/browser",
+ "//content/public/common",
+ ]
+ sources = [
+ "dial/device_description_fetcher.cc",
+ "dial/device_description_fetcher.h",
+ "dial/dial_device_data.cc",
+ "dial/dial_device_data.h",
+ "dial/dial_registry.cc",
+ "dial/dial_registry.h",
+ "dial/dial_service.cc",
+ "dial/dial_service.h",
+ "dial/safe_dial_device_description_parser.cc",
+ "dial/safe_dial_device_description_parser.h",
+ ]
+}
diff --git a/chromium/chrome/browser/media/router/mojo/media_controller.mojom b/chromium/chrome/browser/media/router/mojo/media_controller.mojom
new file mode 100644
index 00000000000..497cd4161a9
--- /dev/null
+++ b/chromium/chrome/browser/media/router/mojo/media_controller.mojom
@@ -0,0 +1,35 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media_router.mojom;
+
+import "chrome/browser/media/router/mojo/media_status.mojom";
+import "mojo/common/time.mojom";
+
+// Interface for a controller to change the current state of a media content.
+// This interface should be kept free of details specific to Media Router, so
+// that it can be moved to the media namespace and be reused for other features
+// in the future.
+interface MediaController {
+ // Starts playing the media if it is paused. Is a no-op if not supported by
+ // the media or the media is already playing.
+ Play();
+
+ // Pauses the media if it is playing. Is a no-op if not supported by the media
+ // or the media is already paused.
+ Pause();
+
+ // Mutes the media if |mute| is true, and unmutes it if false. Is a no-op if
+ // not supported by the media.
+ SetMute(bool mute);
+
+ // Changes the current volume of the media, with 1 being the highest and 0
+ // being the lowest/no sound. Does not change the (un)muted state of the
+ // media. Is a no-op if not supported by the media.
+ SetVolume(float volume);
+
+ // Sets the current playback position. |time| must be less than or equal to
+ // the duration of the media. Is a no-op if the media doesn't support seeking.
+ Seek(mojo.common.mojom.TimeDelta time);
+};
diff --git a/chromium/chrome/browser/media/router/mojo/media_router.mojom b/chromium/chrome/browser/media/router/mojo/media_router.mojom
index 37fc064748d..d5e44099480 100644
--- a/chromium/chrome/browser/media/router/mojo/media_router.mojom
+++ b/chromium/chrome/browser/media/router/mojo/media_router.mojom
@@ -5,7 +5,9 @@
module media_router.mojom;
import "mojo/common/time.mojom";
+import "net/interfaces/ip_address.mojom";
import "url/mojo/origin.mojom";
+import "url/mojo/url.mojom";
// Represents an output sink to which media can be routed.
struct MediaSink {
@@ -13,8 +15,9 @@ struct MediaSink {
CAST,
CAST_AUDIO,
CAST_AUDIO_GROUP,
- GENERIC,
- HANGOUT
+ MEETING,
+ HANGOUT,
+ GENERIC
};
// The sink identifier, e.g. "rs71w7mFzYLFlabir_qO4NHl6SUc."
@@ -27,6 +30,45 @@ struct MediaSink {
string? domain;
// The type of icon to show in the UI for this media sink.
IconType icon_type;
+ // This is currently only set by MediaRouter in OnSinksDiscovered().
+ MediaSinkExtraData? extra_data;
+};
+
+union MediaSinkExtraData {
+ DialMediaSink dial_media_sink;
+ CastMediaSink cast_media_sink;
+};
+
+struct DialMediaSink {
+ net.interfaces.IPAddress ip_address;
+
+ // Model name of the sink, if it represents a physical device.
+ string model_name;
+
+ // Used for DIAL launch
+ url.mojom.Url app_url;
+};
+
+struct CastMediaSink {
+ net.interfaces.IPAddress ip_address;
+
+ // Model name of the sink, if it represents a physical device.
+ string model_name;
+
+ // A bit vector representing capabilities of the sink. Meaning of capacity
+ // value for each bit:
+ // NONE: 0,
+ // VIDEO_OUT: 1 << 0,
+ // VIDEO_IN: 1 << 1,
+ // AUDIO_OUT: 1 << 2,
+ // AUDIO_IN: 1 << 3,
+ // DEV_MODE: 1 << 4,
+ // MULTIZONE_GROUP: 1 << 5
+ uint8 capabilities;
+
+ // ID of Cast channel opened by Media Router. The ID is defined by the
+ // chrome.cast.channel API.
+ int32 cast_channel_id;
};
// Should be kept in sync with media_route.h.
@@ -322,6 +364,11 @@ interface MediaRouteProvider {
string media_source,
SinkSearchCriteria search_criteria) =>
(string sink_id);
+
+ // Called when the list of MediaSinks discovered by Media Router has been
+ // updated. The sinks are supplied to the MediaRouteProvider so that they can
+ // be used for other operations, such as route creation.
+ ProvideSinks(string provider_name, array<MediaSink> sinks);
};
// Interface for a service which observes state changes across media
@@ -339,7 +386,7 @@ interface MediaRouter {
AVAILABLE
};
- // Keep in sync with content/public/common/presentation_session.h.
+ // Keep in sync with content/public/common/presentation_info.h.
enum PresentationConnectionState {
CONNECTING,
CONNECTED,
@@ -347,7 +394,7 @@ interface MediaRouter {
TERMINATED
};
- // Keep in sync with content/public/common/presentation_session.h.
+ // Keep in sync with content/public/common/presentation_info.h.
enum PresentationConnectionCloseReason {
CONNECTION_ERROR,
CLOSED,
diff --git a/chromium/chrome/browser/media/router/mojo/media_router.typemap b/chromium/chrome/browser/media/router/mojo/media_router.typemap
index de2b10cb2cb..18b266cb950 100644
--- a/chromium/chrome/browser/media/router/mojo/media_router.typemap
+++ b/chromium/chrome/browser/media/router/mojo/media_router.typemap
@@ -4,15 +4,17 @@
mojom = "//chrome/browser/media/router/mojo/media_router.mojom"
public_headers = [
+ "//chrome/browser/media/router/discovery/media_sink_internal.h",
"//chrome/browser/media/router/issue.h",
"//chrome/browser/media/router/media_route.h",
- "//chrome/browser/media/router/media_sink.h",
"//chrome/browser/media/router/route_message.h",
"//chrome/browser/media/router/route_request_result.h",
- "//content/public/common/presentation_session.h",
+ "//content/public/common/presentation_info.h",
]
deps = [
+ "//net",
"//third_party/icu", # For issue.h
+ "//url",
]
traits_headers =
[ "//chrome/browser/media/router/mojo/media_router_struct_traits.h" ]
@@ -26,7 +28,7 @@ type_mappings = [
"media_router.mojom.MediaRoute=media_router::MediaRoute",
"media_router.mojom.MediaRouter.PresentationConnectionCloseReason=content::PresentationConnectionCloseReason",
"media_router.mojom.MediaRouter.PresentationConnectionState=content::PresentationConnectionState",
- "media_router.mojom.MediaSink=media_router::MediaSink",
+ "media_router.mojom.MediaSink=media_router::MediaSinkInternal",
"media_router.mojom.RouteMessage=media_router::RouteMessage",
"media_router.mojom.RouteRequestResultCode=media_router::RouteRequestResult::ResultCode",
]
diff --git a/chromium/chrome/browser/media/router/mojo/media_router_traits_test_service.mojom b/chromium/chrome/browser/media/router/mojo/media_router_traits_test_service.mojom
new file mode 100644
index 00000000000..9229fd8a6a3
--- /dev/null
+++ b/chromium/chrome/browser/media/router/mojo/media_router_traits_test_service.mojom
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media_router.mojom;
+
+import "chrome/browser/media/router/mojo/media_router.mojom";
+
+// All functions on this interface echo their arguments to test StructTraits
+// serialization and deserialization.
+interface MediaRouterTraitsTestService {
+ [Sync]
+ EchoMediaSink(MediaSink s) => (MediaSink sink);
+};
diff --git a/chromium/chrome/browser/media/router/mojo/media_status.mojom b/chromium/chrome/browser/media/router/mojo/media_status.mojom
new file mode 100644
index 00000000000..d0ae472cc6b
--- /dev/null
+++ b/chromium/chrome/browser/media/router/mojo/media_status.mojom
@@ -0,0 +1,60 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media_router.mojom;
+
+import "mojo/common/time.mojom";
+
+// Represents the current state of a media content. This struct should be kept
+// free of details specific to Media Router, so that it can be moved to the
+// media namespace and be reused for other features in the future.
+struct MediaStatus {
+ // The main title of the media. For example, in a MediaStatus representing
+ // a YouTube Cast session, this could be the title of the video.
+ string title;
+
+ // Text describing the media, or a secondary title. For example, in a
+ // MediaStatus representing a YouTube Cast session, this could be "YouTube".
+ string description;
+
+ // If this is true, the media can be played and paused through its
+ // MediaController.
+ bool can_play_pause;
+
+ // If this is true, the media can be muted and unmuted through its
+ // MediaController.
+ bool can_mute;
+
+ // If this is true, the media's volume can be changed through its
+ // MediaController.
+ bool can_set_volume;
+
+ // If this is true, the media's current playback position can be changed
+ // through its MediaController.
+ bool can_seek;
+
+ bool is_paused;
+
+ bool is_muted;
+
+ // Current volume of the media, with 1 being the highest and 0 being the
+ // lowest/no sound. When |is_muted| is true, there should be no sound
+ // regardless of |volume|.
+ float volume;
+
+ // The length of the media. A value of 0 indicates that this is a media with
+ // no set duration (e.g. a live stream).
+ mojo.common.mojom.TimeDelta duration;
+
+ // Current playback position. Must be less than or equal to |duration|.
+ mojo.common.mojom.TimeDelta current_time;
+};
+
+// Interface for being notified whenever the MediaStatus of a media changes.
+// This interface should be kept free of details specific to Media Router, so
+// that it can be moved to the media namespace and be reused for other features
+// in the future.
+interface MediaStatusObserver {
+ OnMediaStatusUpdated(MediaStatus status);
+};
diff --git a/chromium/chrome/browser/media/router/mojo/media_status.typemap b/chromium/chrome/browser/media/router/mojo/media_status.typemap
new file mode 100644
index 00000000000..fef7db135fc
--- /dev/null
+++ b/chromium/chrome/browser/media/router/mojo/media_status.typemap
@@ -0,0 +1,12 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//chrome/browser/media/router/mojo/media_status.mojom"
+public_headers = [ "//chrome/browser/media/router/media_status.h" ]
+traits_headers =
+ [ "//chrome/browser/media/router/mojo/media_status_struct_traits.h" ]
+sources = [
+ "//chrome/browser/media/router/mojo/media_status_struct_traits.cc",
+]
+type_mappings = [ "media_router.mojom.MediaStatus=media_router::MediaStatus" ]
diff --git a/chromium/chrome/browser/media/router/mojo/typemaps.gni b/chromium/chrome/browser/media/router/mojo/typemaps.gni
index ab7c2f84093..1b82d583528 100644
--- a/chromium/chrome/browser/media/router/mojo/typemaps.gni
+++ b/chromium/chrome/browser/media/router/mojo/typemaps.gni
@@ -2,4 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-typemaps = [ "//chrome/browser/media/router/mojo/media_router.typemap" ]
+typemaps = [
+ "//chrome/browser/media/router/mojo/media_router.typemap",
+ "//chrome/browser/media/router/mojo/media_status.typemap",
+]
diff --git a/chromium/chrome/browser/ntp_snippets/BUILD.gn b/chromium/chrome/browser/ntp_snippets/BUILD.gn
deleted file mode 100644
index 474a6f8fb15..00000000000
--- a/chromium/chrome/browser/ntp_snippets/BUILD.gn
+++ /dev/null
@@ -1,13 +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.
-
-source_set("test_support") {
- testonly = true
- sources = [
- "fake_download_item.cc",
- "fake_download_item.h",
- ]
-
- deps = []
-}
diff --git a/chromium/chrome/browser/prefs/forwarder_manifest.json b/chromium/chrome/browser/prefs/forwarder_manifest.json
new file mode 100644
index 00000000000..93a1576a31b
--- /dev/null
+++ b/chromium/chrome/browser/prefs/forwarder_manifest.json
@@ -0,0 +1,16 @@
+{
+ "name": "preferences_forwarder",
+ "display_name": "Preferences Forwarder",
+ "interface_provider_specs": {
+ "service_manager:connector": {
+ "provides": {
+ "pref_client": [
+ "prefs::mojom::PrefStoreConnector"
+ ]
+ },
+ "requires": {
+ "preferences": [ "pref_client" ]
+ }
+ }
+ }
+}
diff --git a/chromium/chrome/browser/prefs/preferences_manifest.json b/chromium/chrome/browser/prefs/preferences_manifest.json
deleted file mode 100644
index bb498c205a8..00000000000
--- a/chromium/chrome/browser/prefs/preferences_manifest.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name": "preferences",
- "display_name": "Preferences",
- "interface_provider_specs": {
- "service_manager:connector": {
- "provides": {
- "preferences_manager": [ "prefs::mojom::PreferencesServiceFactory" ]
- },
- "requires": {
- }
- }
- }
-}
diff --git a/chromium/chrome/browser/printing/background_printing_manager.cc b/chromium/chrome/browser/printing/background_printing_manager.cc
index 2807c0f8780..6912ec1e5be 100644
--- a/chromium/chrome/browser/printing/background_printing_manager.cc
+++ b/chromium/chrome/browser/printing/background_printing_manager.cc
@@ -19,6 +19,7 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
+using content::BrowserContext;
using content::BrowserThread;
using content::WebContents;
@@ -97,6 +98,21 @@ void BackgroundPrintingManager::Observe(
DeletePreviewContents(content::Source<WebContents>(source).ptr());
}
+void BackgroundPrintingManager::DeletePreviewContentsForBrowserContext(
+ BrowserContext* browser_context) {
+ std::vector<WebContents*> preview_contents_to_delete;
+ for (const auto& iter : printing_contents_map_) {
+ WebContents* preview_contents = iter.first;
+ if (preview_contents->GetBrowserContext() == browser_context) {
+ preview_contents_to_delete.push_back(preview_contents);
+ }
+ }
+
+ for (size_t i = 0; i < preview_contents_to_delete.size(); i++) {
+ DeletePreviewContents(preview_contents_to_delete[i]);
+ }
+}
+
void BackgroundPrintingManager::DeletePreviewContents(
WebContents* preview_contents) {
auto i = printing_contents_map_.find(preview_contents);
diff --git a/chromium/chrome/browser/printing/background_printing_manager.h b/chromium/chrome/browser/printing/background_printing_manager.h
index f2f9140621b..6957e541066 100644
--- a/chromium/chrome/browser/printing/background_printing_manager.h
+++ b/chromium/chrome/browser/printing/background_printing_manager.h
@@ -17,6 +17,7 @@
namespace content {
class WebContents;
+class BrowserContext;
}
namespace printing {
@@ -44,6 +45,10 @@ class BackgroundPrintingManager : public base::NonThreadSafe,
// Let others see the list of background printing contents.
std::set<content::WebContents*> CurrentContentSet();
+ // Delete all preview contents that are associated with |browser_context|.
+ void DeletePreviewContentsForBrowserContext(
+ content::BrowserContext* browser_context);
+
private:
// content::NotificationObserver overrides:
void Observe(int type,
diff --git a/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.cc b/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.cc
index 19537782ad0..3e12b0ecf25 100644
--- a/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.cc
+++ b/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.cc
@@ -4,19 +4,12 @@
#include "chrome/browser/printing/cloud_print/cloud_print_printer_list.h"
-#include <utility>
-
+#include "base/values.h"
#include "chrome/common/cloud_print/cloud_print_constants.h"
#include "components/cloud_devices/common/cloud_devices_urls.h"
namespace cloud_print {
-CloudPrintPrinterList::Device::Device() {}
-
-CloudPrintPrinterList::Device::~Device() {}
-
-CloudPrintPrinterList::Delegate::Delegate() {}
-
CloudPrintPrinterList::Delegate::~Delegate() {}
CloudPrintPrinterList::CloudPrintPrinterList(Delegate* delegate)
@@ -32,23 +25,19 @@ void CloudPrintPrinterList::OnGCDApiFlowError(GCDApiFlow::Status status) {
void CloudPrintPrinterList::OnGCDApiFlowComplete(
const base::DictionaryValue& value) {
const base::ListValue* printers;
-
if (!value.GetList(cloud_print::kPrinterListValue, &printers)) {
delegate_->OnDeviceListUnavailable();
return;
}
DeviceList devices;
- for (base::ListValue::const_iterator i = printers->begin();
- i != printers->end();
- i++) {
- base::DictionaryValue* printer;
- Device printer_details;
-
- if (!(*i)->GetAsDictionary(&printer))
+ for (const auto& printer : *printers) {
+ const base::DictionaryValue* printer_dict;
+ if (!printer.GetAsDictionary(&printer_dict))
continue;
- if (!FillPrinterDetails(*printer, &printer_details))
+ Device printer_details;
+ if (!FillPrinterDetails(*printer_dict, &printer_details))
continue;
devices.push_back(printer_details);
@@ -61,6 +50,11 @@ GURL CloudPrintPrinterList::GetURL() {
return cloud_devices::GetCloudPrintRelativeURL("search");
}
+GCDApiFlow::Request::NetworkTrafficAnnotation
+CloudPrintPrinterList::GetNetworkTrafficAnnotationType() {
+ return TYPE_SEARCH;
+}
+
bool CloudPrintPrinterList::FillPrinterDetails(
const base::DictionaryValue& printer_value,
Device* printer_details) {
diff --git a/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.h b/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.h
index abfadf5eb7a..01abe9e8170 100644
--- a/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.h
+++ b/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list.h
@@ -8,7 +8,6 @@
#include <string>
#include <vector>
-#include "base/values.h"
#include "chrome/browser/printing/cloud_print/gcd_api_flow.h"
namespace cloud_print {
@@ -16,18 +15,14 @@ namespace cloud_print {
class CloudPrintPrinterList : public CloudPrintApiFlowRequest {
public:
struct Device {
- Device();
- ~Device();
-
std::string id;
std::string display_name;
std::string description;
};
- typedef std::vector<Device> DeviceList;
+ using DeviceList = std::vector<Device>;
class Delegate {
public:
- Delegate();
virtual ~Delegate();
virtual void OnDeviceListReady(const DeviceList& devices) = 0;
@@ -37,17 +32,17 @@ class CloudPrintPrinterList : public CloudPrintApiFlowRequest {
explicit CloudPrintPrinterList(Delegate* delegate);
~CloudPrintPrinterList() override;
+ // CloudPrintApiFlowRequest implementation:
void OnGCDApiFlowError(GCDApiFlow::Status status) override;
-
void OnGCDApiFlowComplete(const base::DictionaryValue& value) override;
-
GURL GetURL() override;
+ NetworkTrafficAnnotation GetNetworkTrafficAnnotationType() override;
private:
bool FillPrinterDetails(const base::DictionaryValue& printer_value,
Device* printer_details);
- Delegate* delegate_;
+ Delegate* const delegate_;
};
} // namespace cloud_print
diff --git a/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list_unittest.cc b/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list_unittest.cc
index 6a9421dee84..db9b696d119 100644
--- a/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list_unittest.cc
+++ b/chromium/chrome/browser/printing/cloud_print/cloud_print_printer_list_unittest.cc
@@ -10,6 +10,7 @@
#include <set>
#include "base/json/json_reader.h"
+#include "base/values.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -44,7 +45,6 @@ TEST(CloudPrintPrinterListTest, Params) {
device_list.GetURL());
EXPECT_EQ("https://www.googleapis.com/auth/cloudprint",
device_list.GetOAuthScope());
- EXPECT_EQ(net::URLFetcher::GET, device_list.GetRequestType());
EXPECT_FALSE(device_list.GetExtraRequestHeaders().empty());
}
@@ -62,16 +62,14 @@ TEST(CloudPrintPrinterListTest, Parsing) {
Mock::VerifyAndClear(&delegate);
- std::set<std::string> ids_found;
std::set<std::string> ids_expected;
ids_expected.insert("someID");
- for (size_t i = 0; i != devices.size(); ++i) {
- ids_found.insert(devices[i].id);
- }
+ std::set<std::string> ids_found;
+ for (const auto& device : devices)
+ ids_found.insert(device.id);
ASSERT_EQ(ids_expected, ids_found);
-
EXPECT_EQ("someID", devices[0].id);
EXPECT_EQ("someDisplayName", devices[0].display_name);
EXPECT_EQ("someDescription", devices[0].description);
diff --git a/chromium/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc b/chromium/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
index a7f92acbf05..a2246942bdc 100644
--- a/chromium/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
+++ b/chromium/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
@@ -244,9 +245,9 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyDisabled) {
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
- prefs->SetUserPref(
- prefs::kCloudPrintEmail,
- new base::StringValue(MockServiceProcessControl::EnabledUserId()));
+ prefs->SetUserPref(prefs::kCloudPrintEmail,
+ base::MakeUnique<base::Value>(
+ MockServiceProcessControl::EnabledUserId()));
service.Initialize();
@@ -262,7 +263,7 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyEnabled) {
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
prefs->SetUserPref(prefs::kCloudPrintEmail,
- new base::StringValue(std::string()));
+ base::MakeUnique<base::Value>(std::string()));
service.Initialize();
service.RefreshStatusFromService();
@@ -280,8 +281,9 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithPolicySetProxyDisabled) {
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
prefs->SetUserPref(prefs::kCloudPrintEmail,
- new base::StringValue(std::string()));
- prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, new base::Value(false));
+ base::MakeUnique<base::Value>(std::string()));
+ prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
+ base::MakeUnique<base::Value>(false));
service.Initialize();
@@ -298,8 +300,9 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithPolicySetProxyEnabled) {
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
prefs->SetUserPref(prefs::kCloudPrintEmail,
- new base::StringValue(std::string()));
- prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, new base::Value(false));
+ base::MakeUnique<base::Value>(std::string()));
+ prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
+ base::MakeUnique<base::Value>(false));
service.Initialize();
@@ -314,15 +317,16 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyDisabledThenSetPolicy) {
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
- prefs->SetUserPref(
- prefs::kCloudPrintEmail,
- new base::StringValue(MockServiceProcessControl::EnabledUserId()));
+ prefs->SetUserPref(prefs::kCloudPrintEmail,
+ base::MakeUnique<base::Value>(
+ MockServiceProcessControl::EnabledUserId()));
service.Initialize();
EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
- prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, new base::Value(false));
+ prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
+ base::MakeUnique<base::Value>(false));
EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
}
@@ -336,7 +340,7 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyEnabledThenSetPolicy) {
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
prefs->SetUserPref(prefs::kCloudPrintEmail,
- new base::StringValue(std::string()));
+ base::MakeUnique<base::Value>(std::string()));
service.Initialize();
service.RefreshStatusFromService();
@@ -345,7 +349,8 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyEnabledThenSetPolicy) {
prefs->GetString(prefs::kCloudPrintEmail));
service.GetMockServiceProcessControl()->SetWillBeDisabledExpectations();
- prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, new base::Value(false));
+ prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
+ base::MakeUnique<base::Value>(false));
EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
}
@@ -360,8 +365,9 @@ TEST_F(CloudPrintProxyPolicyTest,
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
prefs->SetUserPref(prefs::kCloudPrintEmail,
- new base::StringValue(std::string()));
- prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, new base::Value(false));
+ base::MakeUnique<base::Value>(std::string()));
+ prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
+ base::MakeUnique<base::Value>(false));
service.Initialize();
@@ -381,8 +387,9 @@ TEST_F(CloudPrintProxyPolicyTest,
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
prefs->SetUserPref(prefs::kCloudPrintEmail,
- new base::StringValue(std::string()));
- prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, new base::Value(false));
+ base::MakeUnique<base::Value>(std::string()));
+ prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
+ base::MakeUnique<base::Value>(false));
service.Initialize();
@@ -399,9 +406,9 @@ TEST_F(CloudPrintProxyPolicyTest, StartWithNoPolicyProxyDisabledThenEnable) {
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
- prefs->SetUserPref(
- prefs::kCloudPrintEmail,
- new base::StringValue(MockServiceProcessControl::EnabledUserId()));
+ prefs->SetUserPref(prefs::kCloudPrintEmail,
+ base::MakeUnique<base::Value>(
+ MockServiceProcessControl::EnabledUserId()));
service.Initialize();
EXPECT_EQ(std::string(), prefs->GetString(prefs::kCloudPrintEmail));
@@ -424,8 +431,9 @@ TEST_F(CloudPrintProxyPolicyTest,
sync_preferences::TestingPrefServiceSyncable* prefs =
profile_.GetTestingPrefService();
prefs->SetUserPref(prefs::kCloudPrintEmail,
- new base::StringValue(std::string()));
- prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled, new base::Value(false));
+ base::MakeUnique<base::Value>(std::string()));
+ prefs->SetManagedPref(prefs::kCloudPrintProxyEnabled,
+ base::MakeUnique<base::Value>(false));
service.Initialize();
diff --git a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.cc b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.cc
index 2d41fb77dcc..90b1bd6ace3 100644
--- a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.cc
+++ b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.cc
@@ -13,22 +13,9 @@
namespace cloud_print {
-GCDApiFlow::Request::Request() {
-}
-
GCDApiFlow::Request::~Request() {
}
-net::URLFetcher::RequestType GCDApiFlow::Request::GetRequestType() {
- return net::URLFetcher::GET;
-}
-
-void GCDApiFlow::Request::GetUploadData(std::string* upload_type,
- std::string* upload_data) {
- *upload_type = std::string();
- *upload_data = std::string();
-}
-
std::unique_ptr<GCDApiFlow> GCDApiFlow::Create(
net::URLRequestContextGetter* request_context,
OAuth2TokenService* token_service,
diff --git a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.h b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.h
index 6597af737bf..4f7de56dc4e 100644
--- a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.h
+++ b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow.h
@@ -10,9 +10,14 @@
#include "base/macros.h"
#include "google_apis/gaia/oauth2_token_service.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
+namespace base {
+class DictionaryValue;
+}
+
namespace cloud_print {
// API flow for communicating with cloud print and cloud devices.
@@ -32,27 +37,30 @@ class GCDApiFlow {
// Parses results of requests.
class Request {
public:
- Request();
+ enum NetworkTrafficAnnotation {
+ TYPE_SEARCH,
+ TYPE_PRIVET_REGISTER,
+ };
+
virtual ~Request();
+ // Called if the API flow fails.
virtual void OnGCDApiFlowError(Status status) = 0;
+ // Called when the API flow finishes.
virtual void OnGCDApiFlowComplete(const base::DictionaryValue& value) = 0;
+ // Returns the URL for this request.
virtual GURL GetURL() = 0;
+ // Returns the scope parameter for use with OAuth.
virtual std::string GetOAuthScope() = 0;
- virtual net::URLFetcher::RequestType GetRequestType();
-
+ // Returns extra headers, if any, to send with this request.
virtual std::vector<std::string> GetExtraRequestHeaders() = 0;
- // If there is no data, set upload_type and upload_data to ""
- virtual void GetUploadData(std::string* upload_type,
- std::string* upload_data);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Request);
+ // Returns the network traffic annotation tag for this request.
+ virtual NetworkTrafficAnnotation GetNetworkTrafficAnnotationType() = 0;
};
GCDApiFlow();
diff --git a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
index 039a0edccfc..16a19621723 100644
--- a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
+++ b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
@@ -23,8 +23,60 @@
#include "net/http/http_status_code.h"
#include "net/url_request/url_request_status.h"
+using net::DefineNetworkTrafficAnnotation;
+
namespace cloud_print {
+namespace {
+
+const char kCloudPrintOAuthHeaderFormat[] = "Authorization: Bearer %s";
+
+net::NetworkTrafficAnnotationTag GetNetworkTrafficAnnotation(
+ GCDApiFlow::Request::NetworkTrafficAnnotation type) {
+ if (type == CloudPrintApiFlowRequest::TYPE_PRIVET_REGISTER) {
+ return DefineNetworkTrafficAnnotation("cloud_print_privet_register", R"(
+ semantics {
+ sender: "Cloud Print"
+ description:
+ "Registers a locally discovered Privet printer with a Cloud Print "
+ "Server."
+ trigger:
+ "Users can select Privet printers on chrome://devices/ and "
+ "register them."
+ data:
+ "Token id for a printer retrieved from a previous request to a "
+ "Cloud Print Server."
+ destination: OTHER
+ }
+ policy {
+ cookies_allowed: false
+ setting: "User triggered requests cannot be disabled."
+ policy_exception_justification: "Not implemented, it's good to do so."
+ })");
+ } else {
+ DCHECK_EQ(CloudPrintApiFlowRequest::TYPE_SEARCH, type);
+ return DefineNetworkTrafficAnnotation("cloud_print_search", R"(
+ semantics {
+ sender: "Cloud Print"
+ description:
+ "Queries a Cloud Print Server for the list of printers."
+ trigger:
+ "chrome://devices/ fetches the list when the user logs in, "
+ "re-enable the Cloud Print service, or manually requests a printer "
+ "list refresh."
+ data: "None"
+ destination: OTHER
+ }
+ policy {
+ cookies_allowed: false
+ setting: "User triggered requests cannot be disabled."
+ policy_exception_justification: "Not implemented, it's good to do so."
+ })");
+ }
+}
+
+} // namespace
+
GCDApiFlowImpl::GCDApiFlowImpl(net::URLRequestContextGetter* request_context,
OAuth2TokenService* token_service,
const std::string& account_id)
@@ -49,7 +101,7 @@ void GCDApiFlowImpl::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
- CreateRequest(request_->GetURL());
+ CreateRequest();
std::string authorization_header =
base::StringPrintf(kCloudPrintOAuthHeaderFormat, access_token.c_str());
@@ -66,25 +118,18 @@ void GCDApiFlowImpl::OnGetTokenFailure(
request_->OnGCDApiFlowError(ERROR_TOKEN);
}
-void GCDApiFlowImpl::CreateRequest(const GURL& url) {
- net::URLFetcher::RequestType request_type = request_->GetRequestType();
-
- url_fetcher_ = net::URLFetcher::Create(url, request_type, this);
+void GCDApiFlowImpl::CreateRequest() {
+ url_fetcher_ = net::URLFetcher::Create(
+ request_->GetURL(), net::URLFetcher::GET, this,
+ GetNetworkTrafficAnnotation(request_->GetNetworkTrafficAnnotationType()));
+ url_fetcher_->SetRequestContext(request_context_.get());
- if (request_type != net::URLFetcher::GET) {
- std::string upload_type;
- std::string upload_data;
- request_->GetUploadData(&upload_type, &upload_data);
- url_fetcher_->SetUploadData(upload_type, upload_data);
- }
+ std::vector<std::string> extra_headers = request_->GetExtraRequestHeaders();
+ for (const std::string& header : extra_headers)
+ url_fetcher_->AddExtraRequestHeader(header);
data_use_measurement::DataUseUserData::AttachToFetcher(
url_fetcher_.get(), data_use_measurement::DataUseUserData::CLOUD_PRINT);
- url_fetcher_->SetRequestContext(request_context_.get());
-
- std::vector<std::string> extra_headers = request_->GetExtraRequestHeaders();
- for (size_t i = 0; i < extra_headers.size(); ++i)
- url_fetcher_->AddExtraRequestHeader(extra_headers[i]);
}
void GCDApiFlowImpl::OnURLFetchComplete(const net::URLFetcher* source) {
diff --git a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.h b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.h
index 34d55ada5da..8cfdbf2295e 100644
--- a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.h
+++ b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.h
@@ -14,10 +14,6 @@
namespace cloud_print {
-namespace {
-const char kCloudPrintOAuthHeaderFormat[] = "Authorization: Bearer %s";
-}
-
class GCDApiFlowImpl : public GCDApiFlow,
public net::URLFetcherDelegate,
public OAuth2TokenService::Consumer {
@@ -26,9 +22,9 @@ class GCDApiFlowImpl : public GCDApiFlow,
GCDApiFlowImpl(net::URLRequestContextGetter* request_context,
OAuth2TokenService* token_service,
const std::string& account_id);
-
~GCDApiFlowImpl() override;
+ // GCDApiFlow implementation:
void Start(std::unique_ptr<Request> request) override;
// net::URLFetcherDelegate implementation:
@@ -42,7 +38,7 @@ class GCDApiFlowImpl : public GCDApiFlow,
const GoogleServiceAuthError& error) override;
private:
- void CreateRequest(const GURL& url);
+ void CreateRequest();
std::unique_ptr<net::URLFetcher> url_fetcher_;
std::unique_ptr<OAuth2TokenService::Request> oauth_request_;
diff --git a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_unittest.cc b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_unittest.cc
index db924b215e6..14db01e80ae 100644
--- a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_unittest.cc
+++ b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_unittest.cc
@@ -40,8 +40,9 @@ class MockDelegate : public CloudPrintApiFlowRequest {
public:
MOCK_METHOD1(OnGCDApiFlowError, void(GCDApiFlow::Status));
MOCK_METHOD1(OnGCDApiFlowComplete, void(const base::DictionaryValue&));
-
MOCK_METHOD0(GetURL, GURL());
+ MOCK_METHOD0(GetNetworkTrafficAnnotationType,
+ GCDApiFlow::Request::NetworkTrafficAnnotation());
};
class GCDApiFlowTest : public testing::Test {
@@ -61,15 +62,16 @@ class GCDApiFlowTest : public testing::Test {
token_service_.AddAccount(account_id_);
ui_thread_.Stop(); // HACK: Fake being on the UI thread
- std::unique_ptr<MockDelegate> delegate(new MockDelegate);
+ std::unique_ptr<MockDelegate> delegate = base::MakeUnique<MockDelegate>();
mock_delegate_ = delegate.get();
EXPECT_CALL(*mock_delegate_, GetURL())
.WillRepeatedly(Return(
GURL("https://www.google.com/cloudprint/confirm?token=SomeToken")));
- gcd_flow_.reset(new GCDApiFlowImpl(
- request_context_.get(), &token_service_, account_id_));
+ gcd_flow_ = base::MakeUnique<GCDApiFlowImpl>(request_context_.get(),
+ &token_service_, account_id_);
gcd_flow_->Start(std::move(delegate));
}
+
base::MessageLoopForUI loop_;
content::TestBrowserThread ui_thread_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
diff --git a/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.cc b/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.cc
index 50fe1272256..b877102258f 100644
--- a/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.cc
+++ b/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.cc
@@ -14,15 +14,6 @@
namespace cloud_print {
-namespace {
-
-GURL GetConfirmFlowUrl(const std::string& token) {
- return net::AppendQueryParameter(
- cloud_devices::GetCloudPrintRelativeURL("confirm"), "token", token);
-}
-
-} // namespace
-
PrivetConfirmApiCallFlow::PrivetConfirmApiCallFlow(
const std::string& token,
const ResponseCallback& callback)
@@ -39,25 +30,22 @@ void PrivetConfirmApiCallFlow::OnGCDApiFlowError(GCDApiFlow::Status status) {
void PrivetConfirmApiCallFlow::OnGCDApiFlowComplete(
const base::DictionaryValue& value) {
bool success = false;
-
if (!value.GetBoolean(cloud_print::kSuccessValue, &success)) {
callback_.Run(GCDApiFlow::ERROR_MALFORMED_RESPONSE);
return;
}
- if (success) {
- callback_.Run(GCDApiFlow::SUCCESS);
- } else {
- callback_.Run(GCDApiFlow::ERROR_FROM_SERVER);
- }
+ callback_.Run(success ? GCDApiFlow::SUCCESS : GCDApiFlow::ERROR_FROM_SERVER);
}
-net::URLFetcher::RequestType PrivetConfirmApiCallFlow::GetRequestType() {
- return net::URLFetcher::GET;
+GURL PrivetConfirmApiCallFlow::GetURL() {
+ return net::AppendQueryParameter(
+ cloud_devices::GetCloudPrintRelativeURL("confirm"), "token", token_);
}
-GURL PrivetConfirmApiCallFlow::GetURL() {
- return GetConfirmFlowUrl(token_);
+GCDApiFlow::Request::NetworkTrafficAnnotation
+PrivetConfirmApiCallFlow::GetNetworkTrafficAnnotationType() {
+ return TYPE_PRIVET_REGISTER;
}
} // namespace cloud_print
diff --git a/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.h b/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.h
index dc52e452703..97a1e0a43ab 100644
--- a/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.h
+++ b/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow.h
@@ -7,32 +7,29 @@
#include <string>
-#include "base/values.h"
#include "chrome/browser/printing/cloud_print/gcd_api_flow.h"
-#include "net/url_request/url_request_context_getter.h"
namespace cloud_print {
// API call flow for server-side communication with CloudPrint for registration.
class PrivetConfirmApiCallFlow : public CloudPrintApiFlowRequest {
public:
- typedef base::Callback<void(GCDApiFlow::Status /*success*/)> ResponseCallback;
+ using ResponseCallback = base::Callback<void(GCDApiFlow::Status)>;
// Create an OAuth2-based confirmation
PrivetConfirmApiCallFlow(const std::string& token,
const ResponseCallback& callback);
-
~PrivetConfirmApiCallFlow() override;
+ // CloudPrintApiFlowRequest implementation:
void OnGCDApiFlowError(GCDApiFlow::Status status) override;
void OnGCDApiFlowComplete(const base::DictionaryValue& value) override;
- net::URLFetcher::RequestType GetRequestType() override;
-
GURL GetURL() override;
+ NetworkTrafficAnnotation GetNetworkTrafficAnnotationType() override;
private:
ResponseCallback callback_;
- std::string token_;
+ const std::string token_;
};
} // namespace cloud_print
diff --git a/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow_unittest.cc b/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow_unittest.cc
index 307c3b91867..3dc36e74016 100644
--- a/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow_unittest.cc
+++ b/chromium/chrome/browser/printing/cloud_print/privet_confirm_api_flow_unittest.cc
@@ -8,6 +8,7 @@
#include <set>
#include "base/json/json_reader.h"
+#include "base/values.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,7 +34,6 @@ TEST(PrivetConfirmApiFlowTest, Params) {
confirmation.GetURL());
EXPECT_EQ("https://www.googleapis.com/auth/cloudprint",
confirmation.GetOAuthScope());
- EXPECT_EQ(net::URLFetcher::GET, confirmation.GetRequestType());
EXPECT_FALSE(confirmation.GetExtraRequestHeaders().empty());
}
diff --git a/chromium/chrome/browser/printing/cloud_print/privet_http_impl.cc b/chromium/chrome/browser/printing/cloud_print/privet_http_impl.cc
index 0235abaa42e..b83a3746e24 100644
--- a/chromium/chrome/browser/printing/cloud_print/privet_http_impl.cc
+++ b/chromium/chrome/browser/printing/cloud_print/privet_http_impl.cc
@@ -14,6 +14,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
@@ -713,8 +714,7 @@ const std::string& PrivetHTTPClientImpl::GetName() {
std::unique_ptr<PrivetJSONOperation> PrivetHTTPClientImpl::CreateInfoOperation(
const PrivetJSONOperation::ResultCallback& callback) {
- return std::unique_ptr<PrivetJSONOperation>(
- new PrivetInfoOperationImpl(this, callback));
+ return base::MakeUnique<PrivetInfoOperationImpl>(this, callback);
}
std::unique_ptr<PrivetURLFetcher> PrivetHTTPClientImpl::CreateURLFetcher(
@@ -746,16 +746,15 @@ std::unique_ptr<PrivetURLFetcher> PrivetHTTPClientImpl::CreateURLFetcher(
setting:
"Users can enable or disable background requests by 'Show "
"notifications when new printers are detected on the network' in "
- "Chrome's settings under Advanced Settings, Google Cloud Print. "
+ "Chromium's settings under Advanced Settings, Google Cloud Print. "
"User triggered requests, like from print preview or "
"chrome://devices/ cannot be disabled."
- }
policy_exception_justification:
"Not implemented, it's good to do so."
})");
- return std::unique_ptr<PrivetURLFetcher>(
- new PrivetURLFetcher(url.ReplaceComponents(replacements), request_type,
- context_getter_, traffic_annotation, delegate));
+ return base::MakeUnique<PrivetURLFetcher>(url.ReplaceComponents(replacements),
+ request_type, context_getter_,
+ traffic_annotation, delegate);
}
void PrivetHTTPClientImpl::RefreshPrivetToken(
@@ -811,25 +810,25 @@ std::unique_ptr<PrivetRegisterOperation>
PrivetV1HTTPClientImpl::CreateRegisterOperation(
const std::string& user,
PrivetRegisterOperation::Delegate* delegate) {
- return std::unique_ptr<PrivetRegisterOperation>(
- new PrivetRegisterOperationImpl(info_client(), user, delegate));
+ return base::MakeUnique<PrivetRegisterOperationImpl>(info_client(), user,
+ delegate);
}
std::unique_ptr<PrivetJSONOperation>
PrivetV1HTTPClientImpl::CreateCapabilitiesOperation(
const PrivetJSONOperation::ResultCallback& callback) {
- return std::unique_ptr<PrivetJSONOperation>(new PrivetJSONOperationImpl(
- info_client(), kPrivetCapabilitiesPath, "", callback));
+ return base::MakeUnique<PrivetJSONOperationImpl>(
+ info_client(), kPrivetCapabilitiesPath, "", callback);
}
std::unique_ptr<PrivetLocalPrintOperation>
PrivetV1HTTPClientImpl::CreateLocalPrintOperation(
PrivetLocalPrintOperation::Delegate* delegate) {
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
- return std::unique_ptr<PrivetLocalPrintOperation>(
- new PrivetLocalPrintOperationImpl(info_client(), delegate));
+ return base::MakeUnique<PrivetLocalPrintOperationImpl>(info_client(),
+ delegate);
#else
- return std::unique_ptr<PrivetLocalPrintOperation>();
+ return nullptr;
#endif // ENABLE_PRINT_PREVIEW
}
diff --git a/chromium/chrome/browser/printing/pdf_to_emf_converter.cc b/chromium/chrome/browser/printing/pdf_to_emf_converter.cc
index 84a9c21eac7..e876c331eb5 100644
--- a/chromium/chrome/browser/printing/pdf_to_emf_converter.cc
+++ b/chromium/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -596,10 +596,7 @@ void PdfConverterUtilityProcessHostClient::SendStartMessage(
void PdfConverterUtilityProcessHostClient::SendStopMessage() {
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop());
}
-/*void PdfToPostScriptUtilityProcessHostClient::OnPageDone(bool success) {
- PdfConverterUtilityProcessHostClient::OnPageDone(success, 0.0f);
-}
-*/
+
// Pdf Converter Impl and subclasses
PdfConverterImpl::PdfConverterImpl() : weak_ptr_factory_(this) {}
diff --git a/chromium/chrome/browser/printing/print_job.cc b/chromium/chrome/browser/printing/print_job.cc
index 2404fe65107..f001c876f0f 100644
--- a/chromium/chrome/browser/printing/print_job.cc
+++ b/chromium/chrome/browser/printing/print_job.cc
@@ -283,7 +283,7 @@ void PrintJob::StartPdfToEmfConversion(
base::MakeUnique<PdfConversionState>(page_size, content_area);
const int kPrinterDpi = settings().dpi();
PdfRenderSettings settings(
- content_area, gfx::Point(0,0), kPrinterDpi, /*autorotate=*/true,
+ content_area, gfx::Point(0, 0), kPrinterDpi, /*autorotate=*/true,
print_text_with_gdi ? PdfRenderSettings::Mode::GDI_TEXT
: PdfRenderSettings::Mode::NORMAL);
pdf_conversion_state_->Start(
@@ -331,7 +331,7 @@ void PrintJob::StartPdfToPostScriptConversion(
gfx::Size(), gfx::Rect());
const int kPrinterDpi = settings().dpi();
PdfRenderSettings settings(
- content_area, physical_offsets, kPrinterDpi, true /* autorotate? */,
+ content_area, physical_offsets, kPrinterDpi, /*autorotate=*/true,
ps_level2 ? PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2
: PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3);
pdf_conversion_state_->Start(
diff --git a/chromium/chrome/browser/printing/print_view_manager.cc b/chromium/chrome/browser/printing/print_view_manager.cc
index bfce3a7c57f..29cb6876a50 100644
--- a/chromium/chrome/browser/printing/print_view_manager.cc
+++ b/chromium/chrome/browser/printing/print_view_manager.cc
@@ -31,7 +31,7 @@ namespace {
// Keeps track of pending scripted print preview closures.
// No locking, only access on the UI thread.
-base::LazyInstance<std::map<content::RenderProcessHost*, base::Closure>>
+base::LazyInstance<std::map<content::RenderProcessHost*, base::Closure>>::Leaky
g_scripted_print_preview_closure_map = LAZY_INSTANCE_INITIALIZER;
void EnableInternalPDFPluginForContents(int render_process_id,
@@ -94,13 +94,7 @@ bool PrintViewManager::BasicPrint(content::RenderFrameHost* rfh) {
if (!print_preview_dialog)
return PrintNow(rfh);
- if (!print_preview_dialog->GetWebUI())
- return false;
-
- PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(
- print_preview_dialog->GetWebUI()->GetController());
- print_preview_ui->OnShowSystemDialog();
- return true;
+ return !!print_preview_dialog->GetWebUI();
}
#endif // BUILDFLAG(ENABLE_BASIC_PRINTING)
diff --git a/chromium/chrome/browser/printing/pwg_raster_converter.cc b/chromium/chrome/browser/printing/pwg_raster_converter.cc
index 1636bdde6a3..29a0fb59800 100644
--- a/chromium/chrome/browser/printing/pwg_raster_converter.cc
+++ b/chromium/chrome/browser/printing/pwg_raster_converter.cc
@@ -301,7 +301,7 @@ PdfRenderSettings PWGRasterConverter::GetConversionSettings(
// by autorotate.
gfx::Rect area(std::min(page_size.width(), page_size.height()) * scale,
std::max(page_size.width(), page_size.height()) * scale);
- return PdfRenderSettings(area, gfx::Point(0,0), dpi, /*autorotate=*/true,
+ return PdfRenderSettings(area, gfx::Point(0, 0), dpi, /*autorotate=*/true,
PdfRenderSettings::Mode::NORMAL);
}
diff --git a/chromium/chrome/browser/printing/pwg_raster_converter.h b/chromium/chrome/browser/printing/pwg_raster_converter.h
index 4a975ee7c39..f36cf0d0a48 100644
--- a/chromium/chrome/browser/printing/pwg_raster_converter.h
+++ b/chromium/chrome/browser/printing/pwg_raster_converter.h
@@ -25,7 +25,6 @@ class Size;
namespace printing {
-struct PdfRenderSettings;
struct PwgRasterSettings;
class PWGRasterConverter {
diff --git a/chromium/chrome/browser/resources/.clang-format b/chromium/chrome/browser/resources/.clang-format
deleted file mode 100644
index d455a85e50f..00000000000
--- a/chromium/chrome/browser/resources/.clang-format
+++ /dev/null
@@ -1,8 +0,0 @@
-# Please keep this file the same as ui/webui/resources/.clang-format.
-BasedOnStyle: Chromium
-
-# Renaming quotes in <include> and <if> break things.
-# For normal JS code, please prefer ' to ".
-JavaScriptQuotes: Leave
-
-AllowShortFunctionsOnASingleLine: Empty
diff --git a/chromium/chrome/browser/resources/BUILD.gn b/chromium/chrome/browser/resources/BUILD.gn
index 231a50630a1..8d4b2551a05 100644
--- a/chromium/chrome/browser/resources/BUILD.gn
+++ b/chromium/chrome/browser/resources/BUILD.gn
@@ -5,9 +5,10 @@
import("//chrome/common/features.gni")
import("//tools/grit/grit_rule.gni")
+assert(!is_ios, "Chromium/iOS shouldn't use anything in //chrome")
+
grit("net_internals_resources") {
source = "net_internals_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/net_internals_resources.h",
@@ -18,7 +19,6 @@ grit("net_internals_resources") {
grit("invalidations_resources") {
source = "invalidations_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/invalidations_resources.h",
@@ -29,7 +29,6 @@ grit("invalidations_resources") {
grit("password_manager_internals_resources") {
source = "password_manager_internals_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/password_manager_internals_resources.h",
@@ -41,8 +40,6 @@ grit("password_manager_internals_resources") {
grit("policy_resources") {
source = "md_policy/policy_resources.grd"
defines = chrome_grit_defines
-
- # TODO(thestig): use_qualified_include = true
outputs = [
"grit/policy_resources.h",
"grit/policy_resources_map.cc",
@@ -54,7 +51,6 @@ grit("policy_resources") {
grit("task_scheduler_internals_resources") {
source = "task_scheduler_internals/resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/task_scheduler_internals_resources.h",
@@ -65,7 +61,6 @@ grit("task_scheduler_internals_resources") {
grit("translate_internals_resources") {
source = "translate_internals_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/translate_internals_resources.h",
@@ -74,11 +69,9 @@ grit("translate_internals_resources") {
output_dir = "$root_gen_dir/chrome"
}
-if (!is_ios && !is_android) {
+if (!is_android) {
grit("component_extension_resources") {
source = "component_extension_resources.grd"
-
- # TODO(thestig): use_qualified_include = true
defines = chrome_grit_defines
if (enable_hangout_services_extension) {
defines += [ "enable_hangout_services_extension" ]
@@ -107,7 +100,6 @@ if (!is_ios && !is_android) {
source = "settings/settings_resources.grd"
}
- # TODO(thestig): use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/settings_resources.h",
@@ -120,7 +112,6 @@ if (!is_ios && !is_android) {
grit("options_resources") {
source = "options_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/options_resources.h",
@@ -131,7 +122,6 @@ if (!is_ios && !is_android) {
grit("options_test_resources") {
source = "options_test_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/options_test_resources.h",
@@ -141,34 +131,29 @@ if (!is_ios && !is_android) {
}
}
-if (!is_ios) {
- grit("quota_internals_resources") {
- source = "quota_internals_resources.grd"
- use_qualified_include = true
- defines = chrome_grit_defines
- outputs = [
- "grit/quota_internals_resources.h",
- "quota_internals_resources.pak",
- ]
- output_dir = "$root_gen_dir/chrome"
- }
+grit("quota_internals_resources") {
+ source = "quota_internals_resources.grd"
+ defines = chrome_grit_defines
+ outputs = [
+ "grit/quota_internals_resources.h",
+ "quota_internals_resources.pak",
+ ]
+ output_dir = "$root_gen_dir/chrome"
+}
- grit("webapks_ui_resources") {
- source = "webapks_ui_resources.grd"
- use_qualified_include = true
- defines = chrome_grit_defines
- outputs = [
- "grit/webapks_ui_resources.h",
- "webapks_ui_resources.pak",
- ]
- output_dir = "$root_gen_dir/chrome"
- }
+grit("webapks_ui_resources") {
+ source = "webapks_ui_resources.grd"
+ defines = chrome_grit_defines
+ outputs = [
+ "grit/webapks_ui_resources.h",
+ "webapks_ui_resources.pak",
+ ]
+ output_dir = "$root_gen_dir/chrome"
}
if (enable_extensions) {
grit("sync_file_system_internals_resources") {
source = "sync_file_system_internals_resources.grd"
- use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/sync_file_system_internals_resources.h",
diff --git a/chromium/chrome/browser/resources/PRESUBMIT.py b/chromium/chrome/browser/resources/PRESUBMIT.py
index 3f14fe79313..891533fe71f 100644
--- a/chromium/chrome/browser/resources/PRESUBMIT.py
+++ b/chromium/chrome/browser/resources/PRESUBMIT.py
@@ -91,6 +91,11 @@ def IsBoolean(new_content_lines, metric_name, input_api):
any(input_api.re.search(type_re, match.group(i)) for i in (1, 3)))
+def CheckHtml(input_api, output_api):
+ return input_api.canned_checks.CheckLongLines(
+ input_api, output_api, 80, lambda x: x.LocalPath().endswith('.html'))
+
+
def RunVulcanizeTests(input_api, output_api):
presubmit_path = input_api.PresubmitLocalPath()
tests = [input_api.os_path.join(presubmit_path, 'vulcanize_gn_test.py')]
@@ -100,6 +105,8 @@ def RunVulcanizeTests(input_api, output_api):
def _CheckChangeOnUploadOrCommit(input_api, output_api):
results = CheckUserActionUpdate(input_api, output_api, ACTION_XML_PATH)
affected = input_api.AffectedFiles()
+ if any(f for f in affected if f.LocalPath().endswith('.html')):
+ results += CheckHtml(input_api, output_api)
if any(f for f in affected if f.LocalPath().endswith('vulcanize_gn.py')):
results += RunVulcanizeTests(input_api, output_api)
return results
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn
index da1a4ddfbed..0cb2c8a04f9 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -43,7 +43,6 @@ chromevox_modules = [
"chromevox/background/tabs_api_handler.js",
"chromevox/injected/active_indicator.js",
"chromevox/injected/api_implementation.js",
- "chromevox/injected/api_util.js",
"chromevox/injected/console_tts.js",
"chromevox/injected/event_suspender.js",
"chromevox/injected/event_watcher.js",
@@ -146,7 +145,6 @@ chromevox_modules = [
"cvox2/background/panel_command.js",
"cvox2/background/panel_menu.js",
"cvox2/background/panel_menu_item.js",
- "cvox2/background/stubs.js",
"cvox2/background/tabs_automation_handler.js",
"cvox2/background/tree_walker.js",
"cvox2/background/tutorial.js",
@@ -267,6 +265,7 @@ run_jsbundler("chromevox_copied_files") {
dest_dir = chromevox_out_dir
sources = [
"chromevox/background/background.html",
+ "chromevox/background/checked.png",
"chromevox/background/earcons/alert_modal.ogg",
"chromevox/background/earcons/alert_nonmodal.ogg",
"chromevox/background/earcons/button.ogg",
@@ -327,7 +326,9 @@ run_jsbundler("chromevox_copied_files") {
"chromevox/background/mathmaps/symbols/math_symbols.json",
"chromevox/background/mathmaps/symbols/math_whitespace.json",
"chromevox/background/mathmaps/symbols/other_stars.json",
+ "chromevox/background/options.css",
"chromevox/background/options.html",
+ "chromevox/background/unchecked.png",
"chromevox/injected/api.js",
"cvox2/background/background.html",
"cvox2/background/earcons/control.wav",
@@ -349,9 +350,7 @@ run_jsbundler("chromevox_copied_files") {
"images/options-hover-19.png",
"images/triangle-6.png",
]
- if (chromevox_compress_js) {
- sources += [ "chromevox/injected/api_util.js" ]
- } else {
+ if (!chromevox_compress_js) {
sources += chromevox_modules
sources += [
"closure/closure_preinit.js",
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json b/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json
index de5c4bf5b00..c08ebdc2bf8 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json
@@ -726,6 +726,15 @@
}
},
{
+ "command": "toggleBrailleTable",
+ "sequence": {
+ "cvoxModifier": true,
+ "keys": {
+ "keyCode": [65, 71]
+ }
+ }
+ },
+ {
"command": "viewGraphicAsBraille",
"sequence": {
"cvoxModifier": true,
@@ -895,6 +904,34 @@
"ctrlKey": [true]
}
}
+ },
+ {
+ "command": "darkenScreen",
+ "sequence": {
+ "cvoxModifier": true,
+ "keys": {
+ "keyCode": [118],
+ "shiftKey": [true]
+ }
+ }
+ },
+ {
+ "command": "undarkenScreen",
+ "sequence": {
+ "cvoxModifier": true,
+ "keys": {
+ "keyCode": [118]
+ }
+ }
+ },
+ {
+ "command": "toggleSpeechOnOrOff",
+ "sequence": {
+ "cvoxModifier": true,
+ "keys": {
+ "keyCode": [119]
+ }
+ }
}
]
}
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/strings/BUILD.gn b/chromium/chrome/browser/resources/chromeos/chromevox/strings/BUILD.gn
index 5ff0a39e72a..dfd90efebef 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/strings/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/strings/BUILD.gn
@@ -10,7 +10,6 @@ chromevox_out_dir = "$root_out_dir/resources/chromeos/chromevox"
grit("chromevox_strings") {
source = "chromevox_strings.grd"
defines = chrome_grit_defines
- use_qualified_include = true
outputs = [
"_locales/am/messages.json",
"_locales/ar/messages.json",
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
index 6439204991d..2761bdac993 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -441,11 +441,15 @@
<message desc="An options page section header for options about the ChromeVox virtual display. This section lets users change the rows, columns, and display style of the virtual braille display." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY">
Virtual Braille Display
</message>
- <message desc="The label for a numberic input field where the user can choose the number of rows in a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_ROWS">
- Rows:
+ <message desc="An explanatory paragraph as part of the ChromeVox options page. Explains that the section on virtual braille display allows the user to control a simulation of a refreshable braille display (a physical hardware device) in the panel at the top of the screen." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_DETAILS">
+ Simulates the output of a refreshable braille display
+ in the ChromeVox panel at the top of the screen.
</message>
- <message desc="The label for a numberic input field where the user can choose the number of columns in a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_COLUMNS">
- Columns:
+ <message desc="The label for a numberic input field where the user can choose the number of lines of text in a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_ROWS">
+ Lines:
+ </message>
+ <message desc="The label for a numberic input field where the user can choose the number of cells in each line of a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_COLUMNS">
+ Cells in each line:
</message>
<message desc="A description that tells the user that the current display style of the virtual display interleaves braille and regular text, one on top of the other." name="IDS_CHROMEVOX_OPTIONS_CURRENT_DISPLAY_STYLE_INTERLEAVE">
Current display style is interleave.
@@ -496,7 +500,7 @@
Voices
</message>
<message desc="Labels the voice selection list box." name="IDS_CHROMEVOX_OPTIONS_VOICES_DESCRIPTION">
- Change the current voice by selecting an option from the list below.
+ Select current voice:
</message>
<message desc="An options page section header for options about the ChromeVox braille support. This section allows the user to customize varous aspects of the braille output and input support." name="IDS_CHROMEVOX_OPTIONS_BRAILLE">
Braille
@@ -508,7 +512,7 @@
Switch to 6 dot braille
</message>
<message desc="Labels the braille table selection list box. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_DESCRIPTION_6">
- Change the current 6 dot braille table by selecting an option from the list below.
+ Select a 6-dot braille table:
</message>
<message desc="How to present the name of a braille table to the user. For example, a locale could be 'English (United States)' and a grade could be '2'. Together they would be 'English (UnitedStates), Grade 2'. A braille table describes how text gets converted from Unicode text into a pattern of braille dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_BRAILLE_TABLE_NAME_WITH_GRADE">
<ph name="locale">$1</ph>, Grade <ph name="grade">$2</ph>
@@ -520,7 +524,7 @@
<ph name="locale">$1</ph> (<ph name="variant">$2</ph>), Grade <ph name="grade">$3</ph>
</message>
<message desc="Labels the braille table selection list box. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_DESCRIPTION_8">
- Change the current 8 dot braille table by selecting an option from the list below.
+ Select an 8-dot braille table:
</message>
<message desc="Labels the checkbox that enables wrapping of words if a whole line doesn't fit on a braille display. When this option is enabled, an effort is made to keep the characters of words together on the display. Otherwise, as many characters as possible are put on each braille display line, possible splitting words between lines." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_WORD_WRAP">
Enable word wrap
@@ -1629,8 +1633,8 @@
<message desc="Describes an &lt;input&gt; element with type=email." name="IDS_CHROMEVOX_INPUT_TYPE_EMAIL">
Edit text, email entry
</message>
- <message desc="Shown on a braille display for a text field that accept an email address as input. When translating, keep the @ sign and try to find an abbreviation for 'edit field'. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_EMAIL_BRL">
- @ed
+ <message desc="Shown on a braille display for a text field that accept an email address as input. When translating, keep the @ sign and try to find an abbreviation for 'edit field 8 dot' according to local conventions; 8 dot refers to the braille table chosen by the user that includes 8 dots in a braille cell appropriate for writing computer symbols. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_EMAIL_BRL">
+ @ed 8dot
</message>
<message desc="Describes an &lt;input&gt; element with type=file." name="IDS_CHROMEVOX_INPUT_TYPE_FILE">
File selection
@@ -1677,8 +1681,8 @@
<message desc="Describes an &lt;input&gt; element with type=url." name="IDS_CHROMEVOX_INPUT_TYPE_URL">
Edit text, URL entry
</message>
- <message desc="Shown on a braille display to describe a text field for entering a URL. When translating, try to find a contracted form of the translation for 'url edit field' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_URL_BRL">
- urled
+ <message desc="Shown on a braille display to describe a text field for entering a URL. When translating, try to find a contracted form of the translation for 'url edit field 8 dot' according to local conventions; 8 dot refers to the braille table chosen by the user that includes 8 dots in a braille cell appropriate for writing computer symbols. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_URL_BRL">
+ urled 8dot
</message>
<message desc="Describes an &lt;input&gt; element with type=week." name="IDS_CHROMEVOX_INPUT_TYPE_WEEK">
Week of the year control
@@ -2708,6 +2712,24 @@ If you're done with the tutorial, use ChromeVox to navigate to the Close button
<message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_WRAP_EARCON_DESCRIPTION">
Wrap from beginning to end or end to beginning inside of a page, dialog, or other container
</message>
+ <message desc="Describes a command to turn off the visual display for accessibility without impacting usage of the machine." name="IDS_CHROMEVOX_DARKEN_SCREEN">
+ Darken screen
+ </message>
+ <message desc="Describes a command to turn the visual display on for accessibility undoing any previous request to turn off the visual display." name="IDS_CHROMEVOX_UNDARKEN_SCREEN">
+ Undarken screen
+ </message>
+ <message desc="Describes a command that turns text to speech feedback off." name="IDS_CHROMEVOX_SPEECH_OFF">
+ Speech off
+ </message>
+ <message desc="Describes a command that turns text to speech feedback on." name="IDS_CHROMEVOX_SPEECH_ON">
+ Speech on
+ </message>
+ <message desc="Description of a command that toggles text to speech feedback on or off." name="IDS_CHROMEVOX_SPEECH_ON_OFF_DESCRIPTION">
+ Toggle speech on or off
+ </message>
+ <message desc="Description of a command that toggles between 6 and 8 dot braille." name="IDS_CHROMEVOX_TOGGLE_BRAILLE_TABLE">
+ Toggle between 6 and 8 dot braille
+ </message>
</messages>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/chromeos/crosh_builtin/manifest.json b/chromium/chrome/browser/resources/chromeos/crosh_builtin/manifest.json
index dc85297eef3..9938484de90 100644
--- a/chromium/chrome/browser/resources/chromeos/crosh_builtin/manifest.json
+++ b/chromium/chrome/browser/resources/chromeos/crosh_builtin/manifest.json
@@ -1,9 +1,9 @@
{
"key": "AAAAB3NzaC1yc2EAAAADAQABAAAAgQDtKfIKWzC4HnQbyAeddk5h78K7LSyrIEnLKDsQCNxhfsavJ+otV9JprDSz3nF7EHZokXiC72SHxdMndt2IlId/aRfhbU4UGidrmFBKg6v1Fs2zey6niB+xLOhJQMe9XtwVNWDpiGXHLmwNhG/FLhj0bBBf1HZDBV18Xp47ymLiuQ==",
- "name": "crosh_builtin",
+ "name": "Chrome OS developer shell",
"manifest_version": 2,
"content_security_policy": "script-src 'self' blob: filesystem:; object-src 'self' blob: filesystem:",
- "version": "0.8.22",
+ "version": "0.8.36",
"default_locale": "en",
"description": "Built-in terminal for crosh.",
"offline_enabled": true,
diff --git a/chromium/chrome/browser/resources/chromeos/first_run/app/manifest.json b/chromium/chrome/browser/resources/chromeos/first_run/app/manifest.json
index de6564bc3cb..b30774838a3 100644
--- a/chromium/chrome/browser/resources/chromeos/first_run/app/manifest.json
+++ b/chromium/chrome/browser/resources/chromeos/first_run/app/manifest.json
@@ -20,6 +20,7 @@
"content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem: chrome://resources; style-src 'self' blob: filesystem: 'unsafe-inline' chrome://resources; img-src 'self' blob: filesystem: chrome://theme chrome://resources"
},
"permissions": [
+ "accessibilityFeatures.read",
"firstRunPrivate",
"chrome://theme/",
"chrome://resources/"
diff --git a/chromium/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn b/chromium/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
index 61a9069f3cc..8486295ae70 100644
--- a/chromium/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
@@ -16,6 +16,7 @@ group("select_to_speak") {
":select_to_speak_copied_files",
":select_to_speak_guest_manifest",
":select_to_speak_manifest",
+ "//chrome/browser/resources/chromeos/select_to_speak/strings:select_to_speak_strings",
]
}
@@ -25,7 +26,13 @@ run_jsbundler("select_to_speak_copied_files") {
mode = "copy"
dest_dir = select_to_speak_out_dir
sources = [
+ "checked.png",
+ "options.css",
+ "options.html",
"select_to_speak.js",
+ "select_to_speak_main.js",
+ "select_to_speak_options.js",
+ "unchecked.png",
]
rewrite_rules = [
rebase_path(".", root_build_dir) + ":",
diff --git a/chromium/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp b/chromium/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp
index 0a405333bcd..7920ad89a63 100644
--- a/chromium/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp
@@ -6,11 +6,26 @@
{
'target_name': 'select_to_speak',
'dependencies': [
+ 'externs',
'<(EXTERNS_GYP):accessibility_private',
'<(EXTERNS_GYP):automation',
'<(EXTERNS_GYP):chrome_extensions',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'select_to_speak_options',
+ 'dependencies': [
+ 'externs',
+ '<(EXTERNS_GYP):accessibility_private',
+ '<(EXTERNS_GYP):automation',
+ '<(EXTERNS_GYP):chrome_extensions',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'externs',
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
],
}
diff --git a/chromium/chrome/browser/resources/chromeos/select_to_speak/strings/BUILD.gn b/chromium/chrome/browser/resources/chromeos/select_to_speak/strings/BUILD.gn
new file mode 100644
index 00000000000..7c2a9ea8ccb
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/select_to_speak/strings/BUILD.gn
@@ -0,0 +1,73 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chrome/common/features.gni")
+import("//tools/grit/grit_rule.gni")
+
+select_to_speak_out_dir = "$root_out_dir/resources/chromeos/select_to_speak"
+
+grit("select_to_speak_strings") {
+ source = "select_to_speak_strings.grd"
+ defines = chrome_grit_defines
+ outputs = [
+ "_locales/am/messages.json",
+ "_locales/ar/messages.json",
+ "_locales/bg/messages.json",
+ "_locales/bn/messages.json",
+ "_locales/ca/messages.json",
+ "_locales/cs/messages.json",
+ "_locales/da/messages.json",
+ "_locales/de/messages.json",
+ "_locales/el/messages.json",
+ "_locales/en_GB/messages.json",
+ "_locales/en/messages.json",
+ "_locales/es/messages.json",
+ "_locales/es_419/messages.json",
+ "_locales/et/messages.json",
+ "_locales/fa/messages.json",
+ "_locales/fi/messages.json",
+ "_locales/fil/messages.json",
+ "_locales/fr/messages.json",
+ "_locales/gu/messages.json",
+ "_locales/he/messages.json",
+ "_locales/hi/messages.json",
+ "_locales/hr/messages.json",
+ "_locales/hu/messages.json",
+ "_locales/id/messages.json",
+ "_locales/it/messages.json",
+ "_locales/ja/messages.json",
+ "_locales/kn/messages.json",
+ "_locales/ko/messages.json",
+ "_locales/lt/messages.json",
+ "_locales/lv/messages.json",
+ "_locales/ml/messages.json",
+ "_locales/mr/messages.json",
+ "_locales/ms/messages.json",
+ "_locales/nl/messages.json",
+ "_locales/nb/messages.json",
+ "_locales/pl/messages.json",
+ "_locales/pt_BR/messages.json",
+ "_locales/pt_PT/messages.json",
+ "_locales/ro/messages.json",
+ "_locales/ru/messages.json",
+ "_locales/sk/messages.json",
+ "_locales/sl/messages.json",
+ "_locales/sr/messages.json",
+ "_locales/sv/messages.json",
+ "_locales/sw/messages.json",
+ "_locales/ta/messages.json",
+ "_locales/te/messages.json",
+ "_locales/th/messages.json",
+ "_locales/tr/messages.json",
+ "_locales/uk/messages.json",
+ "_locales/vi/messages.json",
+ "_locales/zh_CN/messages.json",
+ "_locales/zh_TW/messages.json",
+ ]
+ output_dir = select_to_speak_out_dir
+
+ # Don't polute the extension directory with stamp and .d files.
+ depfile_dir = target_out_dir
+ resource_ids = ""
+}
diff --git a/chromium/chrome/browser/resources/chromeos/select_to_speak/strings/select_to_speak_strings.grd b/chromium/chrome/browser/resources/chromeos/select_to_speak/strings/select_to_speak_strings.grd
new file mode 100644
index 00000000000..757e7d97841
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/select_to_speak/strings/select_to_speak_strings.grd
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<grit base_dir="." current_release="1" latest_public_release="0"
+ output_all_resource_defines="false" enc_check="möl" source_lang_id="en">
+ <outputs>
+ <output filename="_locales/am/messages.json" type="chrome_messages_json" lang="am"/>
+ <output filename="_locales/ar/messages.json" type="chrome_messages_json" lang="ar"/>
+ <output filename="_locales/bg/messages.json" type="chrome_messages_json" lang="bg"/>
+ <output filename="_locales/bn/messages.json" type="chrome_messages_json" lang="bn"/>
+ <output filename="_locales/ca/messages.json" type="chrome_messages_json" lang="ca"/>
+ <output filename="_locales/cs/messages.json" type="chrome_messages_json" lang="cs"/>
+ <output filename="_locales/da/messages.json" type="chrome_messages_json" lang="da"/>
+ <output filename="_locales/de/messages.json" type="chrome_messages_json" lang="de"/>
+ <output filename="_locales/el/messages.json" type="chrome_messages_json" lang="el"/>
+ <output filename="_locales/en_GB/messages.json" type="chrome_messages_json" lang="en-GB"/>
+ <output filename="_locales/en/messages.json" type="chrome_messages_json" lang="en"/>
+ <output filename="_locales/es/messages.json" type="chrome_messages_json" lang="es"/>
+ <output filename="_locales/es_419/messages.json" type="chrome_messages_json" lang="es-419"/>
+ <output filename="_locales/et/messages.json" type="chrome_messages_json" lang="et"/>
+ <output filename="_locales/fa/messages.json" type="chrome_messages_json" lang="fa"/>
+ <output filename="_locales/fi/messages.json" type="chrome_messages_json" lang="fi"/>
+ <output filename="_locales/fil/messages.json" type="chrome_messages_json" lang="fil"/>
+ <output filename="_locales/fr/messages.json" type="chrome_messages_json" lang="fr"/>
+ <output filename="_locales/gu/messages.json" type="chrome_messages_json" lang="gu"/>
+ <output filename="_locales/he/messages.json" type="chrome_messages_json" lang="he"/>
+ <output filename="_locales/hi/messages.json" type="chrome_messages_json" lang="hi"/>
+ <output filename="_locales/hr/messages.json" type="chrome_messages_json" lang="hr"/>
+ <output filename="_locales/hu/messages.json" type="chrome_messages_json" lang="hu"/>
+ <output filename="_locales/id/messages.json" type="chrome_messages_json" lang="id"/>
+ <output filename="_locales/it/messages.json" type="chrome_messages_json" lang="it"/>
+ <output filename="_locales/ja/messages.json" type="chrome_messages_json" lang="ja"/>
+ <output filename="_locales/kn/messages.json" type="chrome_messages_json" lang="kn"/>
+ <output filename="_locales/ko/messages.json" type="chrome_messages_json" lang="ko"/>
+ <output filename="_locales/lt/messages.json" type="chrome_messages_json" lang="lt"/>
+ <output filename="_locales/lv/messages.json" type="chrome_messages_json" lang="lv"/>
+ <output filename="_locales/ml/messages.json" type="chrome_messages_json" lang="ml"/>
+ <output filename="_locales/mr/messages.json" type="chrome_messages_json" lang="mr"/>
+ <output filename="_locales/ms/messages.json" type="chrome_messages_json" lang="ms"/>
+ <output filename="_locales/nl/messages.json" type="chrome_messages_json" lang="nl"/>
+ <output filename="_locales/nb/messages.json" type="chrome_messages_json" lang="no"/>
+ <output filename="_locales/pl/messages.json" type="chrome_messages_json" lang="pl"/>
+ <output filename="_locales/pt_BR/messages.json" type="chrome_messages_json" lang="pt-BR"/>
+ <output filename="_locales/pt_PT/messages.json" type="chrome_messages_json" lang="pt-PT"/>
+ <output filename="_locales/ro/messages.json" type="chrome_messages_json" lang="ro"/>
+ <output filename="_locales/ru/messages.json" type="chrome_messages_json" lang="ru"/>
+ <output filename="_locales/sk/messages.json" type="chrome_messages_json" lang="sk"/>
+ <output filename="_locales/sl/messages.json" type="chrome_messages_json" lang="sl"/>
+ <output filename="_locales/sr/messages.json" type="chrome_messages_json" lang="sr"/>
+ <output filename="_locales/sv/messages.json" type="chrome_messages_json" lang="sv"/>
+ <output filename="_locales/sw/messages.json" type="chrome_messages_json" lang="sw"/>
+ <output filename="_locales/ta/messages.json" type="chrome_messages_json" lang="ta"/>
+ <output filename="_locales/te/messages.json" type="chrome_messages_json" lang="te"/>
+ <output filename="_locales/th/messages.json" type="chrome_messages_json" lang="th"/>
+ <output filename="_locales/tr/messages.json" type="chrome_messages_json" lang="tr"/>
+ <output filename="_locales/uk/messages.json" type="chrome_messages_json" lang="uk"/>
+ <output filename="_locales/vi/messages.json" type="chrome_messages_json" lang="vi"/>
+ <output filename="_locales/zh_CN/messages.json" type="chrome_messages_json" lang="zh-CN"/>
+ <output filename="_locales/zh_TW/messages.json" type="chrome_messages_json" lang="zh-TW"/>
+ </outputs>
+ <translations>
+ <file path="select_to_speak_strings_am.xtb" lang="am" />
+ <file path="select_to_speak_strings_ar.xtb" lang="ar" />
+ <file path="select_to_speak_strings_bg.xtb" lang="bg" />
+ <file path="select_to_speak_strings_bn.xtb" lang="bn" />
+ <file path="select_to_speak_strings_ca.xtb" lang="ca" />
+ <file path="select_to_speak_strings_cs.xtb" lang="cs" />
+ <file path="select_to_speak_strings_da.xtb" lang="da" />
+ <file path="select_to_speak_strings_de.xtb" lang="de" />
+ <file path="select_to_speak_strings_el.xtb" lang="el" />
+ <file path="select_to_speak_strings_en-GB.xtb" lang="en-GB" />
+ <file path="select_to_speak_strings_es.xtb" lang="es" />
+ <file path="select_to_speak_strings_es-419.xtb" lang="es-419" />
+ <file path="select_to_speak_strings_et.xtb" lang="et" />
+ <file path="select_to_speak_strings_fa.xtb" lang="fa" />
+ <file path="select_to_speak_strings_fi.xtb" lang="fi" />
+ <file path="select_to_speak_strings_fil.xtb" lang="fil" />
+ <file path="select_to_speak_strings_fr.xtb" lang="fr" />
+ <file path="select_to_speak_strings_gu.xtb" lang="gu" />
+ <file path="select_to_speak_strings_hi.xtb" lang="hi" />
+ <file path="select_to_speak_strings_hr.xtb" lang="hr" />
+ <file path="select_to_speak_strings_hu.xtb" lang="hu" />
+ <file path="select_to_speak_strings_id.xtb" lang="id" />
+ <file path="select_to_speak_strings_it.xtb" lang="it" />
+ <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
+ <file path="select_to_speak_strings_iw.xtb" lang="he" />
+ <file path="select_to_speak_strings_ja.xtb" lang="ja" />
+ <file path="select_to_speak_strings_kn.xtb" lang="kn" />
+ <file path="select_to_speak_strings_ko.xtb" lang="ko" />
+ <file path="select_to_speak_strings_lt.xtb" lang="lt" />
+ <file path="select_to_speak_strings_lv.xtb" lang="lv" />
+ <file path="select_to_speak_strings_ml.xtb" lang="ml" />
+ <file path="select_to_speak_strings_mr.xtb" lang="mr" />
+ <file path="select_to_speak_strings_ms.xtb" lang="ms" />
+ <file path="select_to_speak_strings_nl.xtb" lang="nl" />
+ <file path="select_to_speak_strings_no.xtb" lang="no" />
+ <file path="select_to_speak_strings_pl.xtb" lang="pl" />
+ <file path="select_to_speak_strings_pt-BR.xtb" lang="pt-BR" />
+ <file path="select_to_speak_strings_pt-PT.xtb" lang="pt-PT" />
+ <file path="select_to_speak_strings_ro.xtb" lang="ro" />
+ <file path="select_to_speak_strings_ru.xtb" lang="ru" />
+ <file path="select_to_speak_strings_sk.xtb" lang="sk" />
+ <file path="select_to_speak_strings_sl.xtb" lang="sl" />
+ <file path="select_to_speak_strings_sr.xtb" lang="sr" />
+ <file path="select_to_speak_strings_sv.xtb" lang="sv" />
+ <file path="select_to_speak_strings_sw.xtb" lang="sw" />
+ <file path="select_to_speak_strings_ta.xtb" lang="ta" />
+ <file path="select_to_speak_strings_te.xtb" lang="te" />
+ <file path="select_to_speak_strings_th.xtb" lang="th" />
+ <file path="select_to_speak_strings_tr.xtb" lang="tr" />
+ <file path="select_to_speak_strings_uk.xtb" lang="uk" />
+ <file path="select_to_speak_strings_vi.xtb" lang="vi" />
+ <file path="select_to_speak_strings_zh-CN.xtb" lang="zh-CN" />
+ <file path="select_to_speak_strings_zh-TW.xtb" lang="zh-TW" />
+ </translations>
+ <release allow_pseudo="false" seq="1">
+ <messages fallback_to_english="true">
+ <message desc="The locale you're translating into. For use in URL to localized pages. e.g. http://www.google.com/?hl=en." name="IDS_LOCALE">
+ en
+ </message>
+ <message desc="The product name for Select-to-speak." name="IDS_SELECT_TO_SPEAK_NAME">
+ Select-to-speak
+ </message>
+ <message desc="The description for Select-to-speak." name="IDS_SELECT_TO_SPEAK_DESCRIPTION">
+ Hold down Search and click or drag to speak anything.
+ </message>
+ <message desc="The title of the Select-to-speak options page." name="IDS_SELECT_TO_SPEAK_OPTIONS_PAGE_TITLE">
+ Select-to-speak Options
+ </message>
+ <message desc="Section of the Select-to-speak options dialog where the user can adjust synthesized speech properties." name="IDS_SELECT_TO_SPEAK_OPTIONS_SPEECH">
+ Speech
+ </message>
+ <message desc="Label for the control in the Select-to-speak options dialog where the user can choose a voice from a list." name="IDS_SELECT_TO_SPEAK_OPTIONS_VOICES_DESCRIPTION">
+ Select a voice:
+ </message>
+ <message desc="Label for the control in the Select-to-speak options dialog where the user can choose the rate/speed of synthesized speech." name="IDS_SELECT_TO_SPEAK_OPTIONS_RATE_DESCRIPTION">
+ Select a speech rate:
+ </message>
+ <message desc="Label for the slowest synthesized speech rate in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_RATE_SLOWEST">
+ Slowest
+ </message>
+ <message desc="Label for slow synthesized speech rate in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_RATE_SLOW">
+ Slow
+ </message>
+ <message desc="Label for a normal synthesized speech rate in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_RATE_NORMAL">
+ Normal
+ </message>
+ <message desc="Label for fast synthesized speech rate in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_RATE_FAST">
+ Fast
+ </message>
+ <message desc="Label for faster synthesized speech rate in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_RATE_FASTER">
+ Faster
+ </message>
+ <message desc="Label for the fastest synthesized speech rate in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_RATE_FASTEST">
+ Fastest
+ </message>
+ </messages>
+ </release>
+</grit>
diff --git a/chromium/chrome/browser/resources/chromeos/switch_access/BUILD.gn b/chromium/chrome/browser/resources/chromeos/switch_access/BUILD.gn
index b40eaf9fa8e..9c112885a5d 100644
--- a/chromium/chrome/browser/resources/chromeos/switch_access/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/switch_access/BUILD.gn
@@ -25,7 +25,15 @@ run_jsbundler("switch_access_copied_files") {
mode = "copy"
dest_dir = switch_access_dir
sources = [
+ "auto_scan_manager.js",
+ "background.js",
+ "keyboard_handler.js",
+ "options.css",
+ "options.html",
+ "options.js",
+ "prefs.js",
"switch_access.js",
+ "tree_walker.js",
]
rewrite_rules = [
rebase_path(".", root_build_dir) + ":",
@@ -33,6 +41,26 @@ run_jsbundler("switch_access_copied_files") {
]
}
+test("switch_access_tests") {
+ deps = [
+ ":switch_access_webuijs_tests",
+ "//chrome/test:browser_tests_runner",
+ ]
+}
+
+js2gtest("switch_access_webuijs_tests") {
+ test_type = "webui"
+ sources = [
+ "auto_scan_manager_unittest.gtestjs",
+ "tree_walker_unittest.gtestjs",
+ ]
+ extra_js_files = [
+ "auto_scan_manager.js",
+ "tree_walker.js",
+ ]
+ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+}
+
# TODO: refactor this into another file like generate_manifest.gni
# to share with other extensions.
template("manifest") {
diff --git a/chromium/chrome/browser/resources/chromeos/switch_access/compiled_resources2.gyp b/chromium/chrome/browser/resources/chromeos/switch_access/compiled_resources2.gyp
index c070260bf16..56172d430e1 100644
--- a/chromium/chrome/browser/resources/chromeos/switch_access/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/chromeos/switch_access/compiled_resources2.gyp
@@ -5,13 +5,71 @@
{
'targets': [
{
+ 'target_name': 'auto_scan_manager',
+ 'dependencies': [
+ 'switch_access_interface',
+ 'prefs',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'background',
+ 'dependencies': [
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'switch_access',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'keyboard_handler',
+ 'dependencies': [
+ 'switch_access_interface',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'options',
+ 'dependencies': [
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'prefs',
+ 'switch_access',
+ 'background',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'prefs',
+ 'dependencies': [
+ '<(EXTERNS_GYP):chrome_extensions',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'switch_access',
'dependencies': [
'<(EXTERNS_GYP):accessibility_private',
- '<(EXTERNS_GYP):automation',
- '<(EXTERNS_GYP):chrome_extensions',
+ '<(EXTERNS_GYP):automation',
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'prefs',
+ 'auto_scan_manager',
+ 'keyboard_handler',
+ 'tree_walker',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'switch_access_interface',
+ 'dependencies': [
+ 'prefs',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'tree_walker',
+ 'dependencies': [
+ '<(EXTERNS_GYP):automation',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ }
],
}
diff --git a/chromium/chrome/browser/resources/cleanup_tool/cleanup.html b/chromium/chrome/browser/resources/cleanup_tool/cleanup.html
new file mode 100644
index 00000000000..52eabe8adac
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/cleanup.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+ <meta name="google" value="notranslate">
+ <meta charset="utf-8">
+ <title>$i18n{title}</title>
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+ <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
+
+ <style>
+ html {
+ --cleanup-card-margin: 25px;
+ --cleanup-card-width: 800px;
+ background: var(--md-background-color);
+ }
+
+ body {
+ margin: 0;
+ }
+ </style>
+</head>
+
+<body>
+ <cleanup-tool-toolbar></cleanup-tool-toolbar>
+ <cleanup-manager></cleanup-manager>
+ <link rel="import" href="chrome://resources/html/cr.html">
+ <link rel="import" href="chrome://resources/html/load_time_data.html">
+ <link rel="import" href="chrome://resources/html/polymer.html">
+ <link rel="import" href="chrome://cleanup/cleanup_browser_proxy.html">
+ <link rel="import" href="chrome://cleanup/icons.html">
+ <link rel="import" href="chrome://cleanup/manager.html">
+ <link rel="import" href="chrome://cleanup/toolbar.html">
+ <script src="strings.js"></script>
+</body>
+
+</html>
diff --git a/chromium/chrome/browser/resources/settings/animation/animation_group.html b/chromium/chrome/browser/resources/cleanup_tool/cleanup_browser_proxy.html
index ba28c97acf9..8b221d7c3b5 100644
--- a/chromium/chrome/browser/resources/settings/animation/animation_group.html
+++ b/chromium/chrome/browser/resources/cleanup_tool/cleanup_browser_proxy.html
@@ -1,2 +1,2 @@
<link rel="import" href="chrome://resources/html/cr.html">
-<script src="animation_group.js"></script>
+<script src="cleanup_browser_proxy.js"></script>
diff --git a/chromium/chrome/browser/resources/cleanup_tool/cleanup_browser_proxy.js b/chromium/chrome/browser/resources/cleanup_tool/cleanup_browser_proxy.js
new file mode 100644
index 00000000000..1e0e859e4b5
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/cleanup_browser_proxy.js
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Helper object and related behavior that encapsulate messaging
+ * between JS and C++ for interacting with the Chrome Cleanup Tool.
+ */
+
+/**
+ * @typedef {{
+ * hasScanResults: boolean,
+ * isInfected: boolean,
+ * detectionStatusText: string,
+ * detectionTimeText: string,
+ * }}
+ */
+var LastScanResult;
+
+cr.define('cleanup', function() {
+ /** @interface */
+ function CleanupBrowserProxy() {}
+
+ CleanupBrowserProxy.prototype = {
+ /**
+ * Fetch the result of the latest Chrome Cleanup Tool scanning task.
+ * @return {!Promise<LastScanResult>}
+ */
+ requestLastScanResult: function() {},
+ };
+
+ /**
+ * @constructor
+ * @implements {cleanup.CleanupBrowserProxy}
+ */
+ function CleanupBrowserProxyImpl() {}
+ cr.addSingletonGetter(CleanupBrowserProxyImpl);
+
+ CleanupBrowserProxyImpl.prototype = {
+ /** @override */
+ requestLastScanResult: function() {
+ return cr.sendWithPromise('requestLastScanResult');
+ },
+ };
+
+ return {
+ CleanupBrowserProxy: CleanupBrowserProxy,
+ CleanupBrowserProxyImpl: CleanupBrowserProxyImpl,
+ }
+});
diff --git a/chromium/chrome/browser/resources/cleanup_tool/compiled_resources2.gyp b/chromium/chrome/browser/resources/cleanup_tool/compiled_resources2.gyp
new file mode 100644
index 00000000000..7e5b6af69d7
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/compiled_resources2.gyp
@@ -0,0 +1,33 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'cleanup_browser_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'manager',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ '<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:ui',
+ 'cleanup_browser_proxy',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'toolbar',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/chrome/browser/resources/cleanup_tool/icons.html b/chromium/chrome/browser/resources/cleanup_tool/icons.html
new file mode 100644
index 00000000000..cbf91f1cd77
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/icons.html
@@ -0,0 +1,19 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
+
+<iron-iconset-svg size="24" name="cleanup">
+ <svg>
+ <defs>
+ <!--
+ This icon is not from Polymer's iron-icons; it was manually edited to put
+ an exclamation mark inside of a shield.
+ -->
+ <g id="infected-user"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm1 12h-2V6h2v6zm0 4h-2v-2h2v2z"></path></g>
+ <!--
+ These icons are copied from Polymer's iron-icons and kept in sorted order.
+ See http://goo.gl/Y1OdAq for instructions on adding additional icons.
+ -->
+ <g id="verified-user"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm-2 16l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path></g>
+ </defs>
+ </svg>
+</iron-iconset-svg>
diff --git a/chromium/chrome/browser/resources/cleanup_tool/manager.html b/chromium/chrome/browser/resources/cleanup_tool/manager.html
new file mode 100644
index 00000000000..a1c8c4d4a7b
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/manager.html
@@ -0,0 +1,145 @@
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/icon.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
+
+<dom-module id="cleanup-manager">
+ <template>
+ <style>
+ #content {
+ margin: 6px auto;
+ max-width: var(--cleanup-card-width);
+ }
+
+ :host {
+ -webkit-margin-start: 3px;
+ display: block;
+ }
+
+ #cleanup-tool-title {
+ margin: 24px auto 10px;
+ }
+
+ .section-title {
+ color: var(--paper-grey-600);
+ font-size: 13px;
+ font-weight: 500;
+ }
+
+ #card {
+ @apply(--shadow-elevation-2dp);
+ background: white;
+ border-radius: 2px;
+ font-size: 16px;
+ font-weight: 500;
+ }
+
+ .card-section {
+ align-items: center;
+ border-top: 1px solid var(--paper-grey-400);
+ display: flex;
+ min-height: 103px;
+ }
+
+ .card-section:first-child {
+ border-top: none;
+ }
+
+ .icon-wrapper {
+ margin: 0 24px;
+ }
+
+ .clean-icon {
+ color: var(--paper-blue-700);
+ }
+
+ .infected-icon {
+ color: var(--paper-red-700);
+ }
+
+ #status-icon {
+ height: 32px;
+ width: 32px;
+ }
+
+ .scan-details {
+ flex: 1;
+ min-width: 200px;
+ }
+
+ .under-text {
+ color: var(--paper-grey-500);
+ }
+
+ #spinner-container {
+ min-width: 28px;
+ }
+
+ #tool-action-container {
+ color: var(--paper-grey-700);
+ font-size: 18px;
+ padding: 24px;
+ }
+
+ .scan-or-cleanup-action {
+ @apply(--cr-actionable);
+ text-transform: uppercase;
+ }
+
+ #about-link {
+ color: var(--paper-blue-700);
+ padding: 24px;
+ text-decoration: none;
+ }
+ </style>
+
+ <div id="content">
+ <h3 id="cleanup-tool-title" class="section-title">
+ $i18n{sectionHeader}
+ </h3>
+ <div id="card">
+ <div class="card-section">
+ <div id="status-icon-wrapper" class="icon-wrapper">
+ <iron-icon icon="[[getStatusIcon_(hasScanResults, isInfected)]]"
+ class$="[[getIconClassName_(hasScanResults, isInfected)]]"
+ id="status-icon">
+ </iron-icon>
+ </div>
+ <div class="scan-details">
+ <div id="scan-detections">
+ [[detectionStatusText]]
+ </div>
+ <div class="under-text">
+ [[detectionTimeText]]
+ </div>
+ </div>
+ <div id="spinner-container" hidden="[[!isRunningScanner]]">
+ <paper-spinner active></paper-spinner>
+ </div>
+ <div id="tool-action-container">
+ <div class="scan-or-cleanup-action"
+ hidden="[[!shouldShowScan_(hasScanResults, isRunningScanner)]]"
+ on-tap="onScanTap_">$i18n{scanAction}</div>
+ <div hidden="[[!isRunningScanner]]">$i18n{scanning}</div>
+ <div class="scan-or-cleanup-action" hidden="[[!hasScanResults]]"
+ on-tap="onCleanupTap_">$i18n{cleanAction}</div>
+ </div>
+ </div>
+ <div class="card-section">
+ <!-- TODO(proberge): Replace answer ID with a P-link as per
+ crbug.com/679462 -->
+ <a id="about-link"
+ href="https://support.google.com/chrome/answer/6086368">
+ $i18n{about}
+ </a>
+ </div>
+ </div>
+ </div>
+
+ </template>
+ <script src="chrome://cleanup/manager.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/cleanup_tool/manager.js b/chromium/chrome/browser/resources/cleanup_tool/manager.js
new file mode 100644
index 00000000000..81ad5884cdb
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/manager.js
@@ -0,0 +1,117 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer({
+ is: 'cleanup-manager',
+
+ properties: {
+ hasScanResults: {
+ type: Boolean,
+ value: false,
+ },
+
+ isInfected: {
+ type: Boolean,
+ value: false,
+ },
+
+ isRunningScanner: {
+ type: Boolean,
+ value: false,
+ },
+
+ detectionStatusText: {
+ type: String,
+ value: ""
+ },
+
+ detectionTimeText: {
+ type: String,
+ value: ""
+ },
+
+ /** @private {!cleanup.CleanupBrowserProxy} */
+ browserProxy_: Object,
+ },
+
+ /** @override */
+ attached: function() {
+ // Fetch data to have it displayed as soon as possible.
+ this.requestLastScanResult_();
+ },
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = cleanup.CleanupBrowserProxyImpl.getInstance();
+ },
+
+ /**
+ * Sends a request for Chrome to start the Cleanup Tool's scanning process.
+ * @private
+ */
+ onScanTap_: function() {
+ // TODO implement me.
+ },
+
+ /**
+ * Sends a request for Chrome to open the Cleanup Tool's cleanup prompt.
+ * @private
+ */
+ onCleanupTap_: function() {
+ // TODO implement me.
+ },
+
+ /**
+ * @param {boolean} hasScanResults
+ * @param {boolean} isInfected
+ * @return {string} A class name for icon-specific styling.
+ * @private
+ */
+ getIconClassName_: function(hasScanResults, isInfected) {
+ return hasScanResults && isInfected ? "infected-icon" : "clean-icon";
+ },
+
+ /**
+ * @param {boolean} hasScanResults
+ * @param {boolean} isInfected
+ * @return {string} An icon id. See icons.html.
+ * @private
+ */
+ getStatusIcon_: function(hasScanResults, isInfected) {
+ return hasScanResults && isInfected ?
+ "cleanup:infected-user" :
+ "cleanup:verified-user";
+ },
+
+ /**
+ * @param {boolean} hasScanResults
+ * @param {boolean} isRunningScanner
+ * @return {boolean} True if the "Scan" button should be displayed, false
+ * otherwise.
+ * @private
+ */
+ shouldShowScan_: function(hasScanResults, isRunningScanner) {
+ return !hasScanResults && !isRunningScanner;
+ },
+
+ /**
+ * Requests the latest Chrome Cleanup Tool scan results from Chrome, then
+ * updates the local state with the new information.
+ * @private
+ */
+ requestLastScanResult_: function() {
+ this.browserProxy_.requestLastScanResult().then(
+ this.updateLastScanState_.bind(this));
+ },
+
+ /**
+ @param {LastScanResult} lastScanResults
+ */
+ updateLastScanState_: function(lastScanResults) {
+ this.hasScanResults = lastScanResults.hasScanResults;
+ this.isInfected = lastScanResults.hasScanResults;
+ this.detectionStatusText = lastScanResults.detectionStatusText;
+ this.detectionTimeText = lastScanResults.detectionTimeText;
+ }
+});
diff --git a/chromium/chrome/browser/resources/cleanup_tool/toolbar.html b/chromium/chrome/browser/resources/cleanup_tool/toolbar.html
new file mode 100644
index 00000000000..7180a88bb17
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/toolbar.html
@@ -0,0 +1,26 @@
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<dom-module id="cleanup-tool-toolbar">
+ <template>
+ <style>
+ :host {
+ align-items: center;
+ background: var(--md-toolbar-color);
+ color: white;
+ display: flex;
+ min-height: 56px;
+ }
+
+ #page-title {
+ -webkit-padding-start: 18px;
+ font-size: 123%;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+ </style>
+ <div id="page-title">$i18n{title}</div>
+ </template>
+ <script src="chrome://cleanup/toolbar.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/cleanup_tool/toolbar.js b/chromium/chrome/browser/resources/cleanup_tool/toolbar.js
new file mode 100644
index 00000000000..e12d720ed8d
--- /dev/null
+++ b/chromium/chrome/browser/resources/cleanup_tool/toolbar.js
@@ -0,0 +1,11 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('cleanup', function() {
+ var Toolbar = Polymer({
+ is: 'cleanup-tool-toolbar',
+ });
+
+ return {Toolbar: Toolbar};
+});
diff --git a/chromium/chrome/browser/resources/component_extension_resources.grd b/chromium/chrome/browser/resources/component_extension_resources.grd
index f9bf3c3e485..982e1910265 100644
--- a/chromium/chrome/browser/resources/component_extension_resources.grd
+++ b/chromium/chrome/browser/resources/component_extension_resources.grd
@@ -105,14 +105,6 @@
<include name="IDR_FEEDBACK_ICON_32" file="feedback/images/icon32.png" type="BINDATA" />
<include name="IDR_FEEDBACK_ICON_64" file="feedback/images/icon64.png" type="BINDATA" />
</if>
- <if expr="enable_google_now">
- <include name="IDR_GOOGLE_NOW_BACKGROUND_JS" file="google_now/background.js" type="BINDATA" />
- <include name="IDR_GOOGLE_NOW_CARDS_JS" file="google_now/cards.js" type="BINDATA" />
- <include name="IDR_GOOGLE_NOW_UTILITY_JS" file="google_now/utility.js" type="BINDATA" />
- <include name="IDR_GOOGLE_NOW_ICON_16" file="google_now/images/icon16.png" type="BINDATA" />
- <include name="IDR_GOOGLE_NOW_ICON_48" file="google_now/images/icon48.png" type="BINDATA" />
- <include name="IDR_GOOGLE_NOW_ICON_128" file="google_now/images/icon128.png" type="BINDATA" />
- </if>
<include name="IDR_IDENTITY_API_SCOPE_APPROVAL_BACKGROUND_JS" file="identity_scope_approval_dialog/background.js" type="BINDATA" />
<include name="IDR_IDENTITY_API_SCOPE_APPROVAL_DIALOG_CSS" file="identity_scope_approval_dialog/scope_approval_dialog.css" type="BINDATA" />
<include name="IDR_IDENTITY_API_SCOPE_APPROVAL_DIALOG" file="identity_scope_approval_dialog/scope_approval_dialog.html" type="BINDATA" />
diff --git a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css
index d89cc7a87ae..e4dc5da42b6 100644
--- a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css
+++ b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css
@@ -97,7 +97,7 @@ body {
height: 14px;
margin-top: 2px;
padding: 0 4px 2px 4px;
- width: 50px;
+ width: 65px;
}
.log-type-login {
diff --git a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html
index fbf99dfa2d8..17635afc445 100644
--- a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html
+++ b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html
@@ -46,6 +46,10 @@
<span i18n-content="logTypePowerText"></span>
</label>
<label>
+ <input id="log-type-bluetooth" type="checkbox">
+ <span i18n-content="logTypeBluetoothText"></span>
+ </label>
+ <label>
<input id="log-type-usb" type="checkbox">
<span i18n-content="logTypeUsbText"></span>
</label>
diff --git a/chromium/chrome/browser/resources/easy_unlock/OWNERS b/chromium/chrome/browser/resources/easy_unlock/OWNERS
index e7d31dab528..0e2febfea64 100644
--- a/chromium/chrome/browser/resources/easy_unlock/OWNERS
+++ b/chromium/chrome/browser/resources/easy_unlock/OWNERS
@@ -1,2 +1,4 @@
tengs@chromium.org
tbarzic@chromium.org
+
+# COMPONENT: UI>ProximityAuth
diff --git a/chromium/chrome/browser/resources/engagement/site_engagement.html b/chromium/chrome/browser/resources/engagement/site_engagement.html
index 4a519fab486..9a7f960ddde 100644
--- a/chromium/chrome/browser/resources/engagement/site_engagement.html
+++ b/chromium/chrome/browser/resources/engagement/site_engagement.html
@@ -61,7 +61,7 @@
box-shadow: 0 0 2px rgb(113, 158, 206);
outline: none;
}
-
+
table tr:hover {
background: rgb(255, 255, 187);
}
@@ -83,7 +83,7 @@
<th sort-key="origin">
Origin
</th>
- <th sort-key="score" class="sort-column" sort-reverse>
+ <th sort-key="total_score" class="sort-column" sort-reverse>
Points
</th>
</tr>
diff --git a/chromium/chrome/browser/resources/engagement/site_engagement.js b/chromium/chrome/browser/resources/engagement/site_engagement.js
index 3557fd03845..5e826d27255 100644
--- a/chromium/chrome/browser/resources/engagement/site_engagement.js
+++ b/chromium/chrome/browser/resources/engagement/site_engagement.js
@@ -4,26 +4,37 @@
'use strict';
+// Allow a function to be provided by tests, which will be called when
+// the page has been populated with site engagement details.
+var resolvePageIsPopulated = null;
+var pageIsPopulatedPromise = new Promise((resolve, reject) => {
+ resolvePageIsPopulated = resolve;
+});
+
+function whenPageIsPopulatedForTest() {
+ return pageIsPopulatedPromise;
+}
+
define('main', [
- 'chrome/browser/ui/webui/engagement/site_engagement.mojom',
+ 'chrome/browser/engagement/site_engagement_details.mojom',
'content/public/renderer/frame_interfaces',
-], function(siteEngagementMojom, frameInterfaces) {
- return function() {
- var uiHandler = new siteEngagementMojom.SiteEngagementUIHandlerPtr(
+], (siteEngagementMojom, frameInterfaces) => {
+ return () => {
+ var uiHandler = new siteEngagementMojom.SiteEngagementDetailsProviderPtr(
frameInterfaces.getInterface(
- siteEngagementMojom.SiteEngagementUIHandler.name));
+ siteEngagementMojom.SiteEngagementDetailsProvider.name));
var engagementTableBody = $('engagement-table-body');
var updateInterval = null;
var info = null;
- var sortKey = 'score';
+ var sortKey = 'total_score';
var sortReverse = true;
// Set table header sort handlers.
var engagementTableHeader = $('engagement-table-header');
var headers = engagementTableHeader.children;
for (var i = 0; i < headers.length; i++) {
- headers[i].addEventListener('click', function(e) {
+ headers[i].addEventListener('click', (e) => {
var newSortKey = e.target.getAttribute('sort-key');
if (sortKey == newSortKey) {
sortReverse = !sortReverse;
@@ -44,7 +55,7 @@ define('main', [
/**
* Creates a single row in the engagement table.
- * @param {SiteEngagementInfo} info The info to create the row from.
+ * @param {SiteEngagementDetails} info The info to create the row from.
* @return {HTMLElement}
*/
function createRow(info) {
@@ -56,13 +67,13 @@ define('main', [
'change', handleScoreChange.bind(undefined, info.origin));
scoreInput.addEventListener('focus', disableAutoupdate);
scoreInput.addEventListener('blur', enableAutoupdate);
- scoreInput.value = info.score;
+ scoreInput.value = info.total_score;
var scoreCell = createElementWithClassName('td', 'score-cell');
scoreCell.appendChild(scoreInput);
var engagementBar = createElementWithClassName('div', 'engagement-bar');
- engagementBar.style.width = (info.score * 4) + 'px';
+ engagementBar.style.width = (info.total_score * 4) + 'px';
var engagementBarCell =
createElementWithClassName('td', 'engagement-bar-cell');
@@ -100,7 +111,7 @@ define('main', [
*/
function handleScoreChange(origin, e) {
var scoreInput = e.target;
- uiHandler.setSiteEngagementScoreForOrigin(origin, scoreInput.value);
+ uiHandler.setSiteEngagementBaseScoreForUrl(origin, scoreInput.value);
scoreInput.barCellRef.style.width = (scoreInput.value * 4) + 'px';
scoreInput.blur();
enableAutoupdate();
@@ -117,14 +128,14 @@ define('main', [
* Sort the engagement info based on |sortKey| and |sortReverse|.
*/
function sortInfo() {
- info.sort(function(a, b) {
+ info.sort((a, b) => {
return (sortReverse ? -1 : 1) *
compareTableItem(sortKey, a, b);
});
}
/**
- * Compares two SiteEngagementInfo objects based on |sortKey|.
+ * Compares two SiteEngagementDetails objects based on |sortKey|.
* @param {string} sortKey The name of the property to sort by.
* @return {number} A negative number if |a| should be ordered before |b|, a
* positive number otherwise.
@@ -137,7 +148,7 @@ define('main', [
if (sortKey == 'origin')
return new URL(val1.url).host > new URL(val2.url).host ? 1 : -1;
- if (sortKey == 'score')
+ if (sortKey == 'total_score')
return val1 - val2;
assertNotReached('Unsupported sort key: ' + sortKey);
@@ -151,10 +162,12 @@ define('main', [
clearTable();
sortInfo();
// Round each score to 2 decimal places.
- info.forEach(function(info) {
- info.score = Number(Math.round(info.score * 100) / 100);
+ info.forEach((info) => {
+ info.total_score = Number(Math.round(info.total_score * 100) / 100);
engagementTableBody.appendChild(createRow(info));
});
+
+ resolvePageIsPopulated();
}
/**
@@ -162,7 +175,7 @@ define('main', [
*/
function updateEngagementTable() {
// Populate engagement table.
- uiHandler.getSiteEngagementInfo().then(function(response) {
+ uiHandler.getSiteEngagementDetails().then((response) => {
info = response.info;
renderTable(info);
});
diff --git a/chromium/chrome/browser/resources/extensions/OWNERS b/chromium/chrome/browser/resources/extensions/OWNERS
index ccdcd27a2b2..b4ef9535bac 100644
--- a/chromium/chrome/browser/resources/extensions/OWNERS
+++ b/chromium/chrome/browser/resources/extensions/OWNERS
@@ -1,3 +1,6 @@
dbeam@chromium.org
finnur@chromium.org
rdevlin.cronin@chromium.org
+
+# TEAM: extensions-dev@chromium.org
+# COMPONENT: Platform>Extensions
diff --git a/chromium/chrome/browser/resources/extensions/extension_options_overlay.html b/chromium/chrome/browser/resources/extensions/extension_options_overlay.html
index 6f2c9177f3f..2398ac35be6 100644
--- a/chromium/chrome/browser/resources/extensions/extension_options_overlay.html
+++ b/chromium/chrome/browser/resources/extensions/extension_options_overlay.html
@@ -6,7 +6,8 @@ in the LICENSE file.
<div id="extension-options-overlay" class="page">
<div class="close-button"></div>
<div id="extension-options-overlay-header">
- <img id="extension-options-overlay-icon"></img>
+ <img id="extension-options-overlay-icon"
+ aria-hidden="true"></img>
<h1 id="extension-options-overlay-title"></h1>
</div>
<div id="extension-options-overlay-guest"></div>
diff --git a/chromium/chrome/browser/resources/extensions/extensions.js b/chromium/chrome/browser/resources/extensions/extensions.js
index d792412d2ab..fb146e6653c 100644
--- a/chromium/chrome/browser/resources/extensions/extensions.js
+++ b/chromium/chrome/browser/resources/extensions/extensions.js
@@ -392,7 +392,8 @@ cr.define('extensions', function() {
var pages = document.querySelectorAll('.page');
for (var i = 0; i < pages.length; i++) {
- pages[i].setAttribute('aria-hidden', node ? 'true' : 'false');
+ var hidden = (node != pages[i]) ? 'true' : 'false';
+ pages[i].setAttribute('aria-hidden', hidden);
}
$('overlay').hidden = !node;
diff --git a/chromium/chrome/browser/resources/feedback/OWNERS b/chromium/chrome/browser/resources/feedback/OWNERS
index 13e3b599939..806a1cef4fb 100644
--- a/chromium/chrome/browser/resources/feedback/OWNERS
+++ b/chromium/chrome/browser/resources/feedback/OWNERS
@@ -1,2 +1,4 @@
afakhry@chromium.org
-steel@chromium.org
+rkc@chromium.org
+
+# COMPONENT: Platform>Apps>Feedback
diff --git a/chromium/chrome/browser/resources/feedback/css/feedback.css b/chromium/chrome/browser/resources/feedback/css/feedback.css
index c94f224f93a..bde797c782c 100644
--- a/chromium/chrome/browser/resources/feedback/css/feedback.css
+++ b/chromium/chrome/browser/resources/feedback/css/feedback.css
@@ -9,6 +9,8 @@ html {
body {
background-color: #fbfbfb;
+ display: flex;
+ flex-direction: column;
height: 100%;
margin: 0;
overflow: auto;
@@ -42,6 +44,7 @@ body {
.content {
color: #646464;
+ flex-grow: 1;
font-size: 12px;
margin: 20px;
}
@@ -105,7 +108,7 @@ body {
}
.content #screenshot-image {
- -webkit-margin-start: 150px;
+ -webkit-margin-end: 25px;
display: block;
height: 60px;
margin-top: 40px;
@@ -113,7 +116,7 @@ body {
}
.content #screenshot-image:hover {
- -webkit-margin-start: 80px;
+ -webkit-margin-end: 0;
height: 125px;
margin-top: 80px;
z-index: 1;
@@ -129,6 +132,10 @@ body {
width: 200px;
}
+.content #screenshot-label {
+ flex: auto;
+}
+
.content #privacy-note {
color: #969696;
font-size: 10px;
@@ -142,6 +149,7 @@ body {
display: -webkit-flex;
justify-content: flex-end;
left: 20px;
+ position: absolute;
right: 20px;
}
diff --git a/chromium/chrome/browser/resources/feedback/html/default.html b/chromium/chrome/browser/resources/feedback/html/default.html
index 5b03af1326a..debe0a53e2b 100644
--- a/chromium/chrome/browser/resources/feedback/html/default.html
+++ b/chromium/chrome/browser/resources/feedback/html/default.html
@@ -49,7 +49,7 @@
<input id="page-url-text" aria-labelledby="page-url-label" type="text">
</div>
<!-- User e-mail -->
- <div id="user-email" class="text-field-container">
+ <div id="user-email" class="text-field-container" hidden>
<label id="user-email-label" i18n-content="user-email"></label>
<select id="user-email-drop-down" aria-labelledby="user-email-label">
<option id="anonymous-user-option" value="anonymous_user"
diff --git a/chromium/chrome/browser/resources/feedback/js/feedback.js b/chromium/chrome/browser/resources/feedback/js/feedback.js
index cb51b962991..a60b24a0ac4 100644
--- a/chromium/chrome/browser/resources/feedback/js/feedback.js
+++ b/chromium/chrome/browser/resources/feedback/js/feedback.js
@@ -354,6 +354,9 @@ function initialize() {
// Make sure the "Report anonymously" option comes last.
$('user-email-drop-down').insertBefore(optionElement,
$('anonymous-user-option'));
+
+ // Now we can unhide the user email section:
+ $('user-email').hidden = false;
});
// Initiate getting the system info.
diff --git a/chromium/chrome/browser/resources/google_now/OWNERS b/chromium/chrome/browser/resources/google_now/OWNERS
deleted file mode 100644
index 18583cd0452..00000000000
--- a/chromium/chrome/browser/resources/google_now/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-robliao@chromium.org
diff --git a/chromium/chrome/browser/resources/google_now/background.js b/chromium/chrome/browser/resources/google_now/background.js
deleted file mode 100644
index b0bda7a6aca..00000000000
--- a/chromium/chrome/browser/resources/google_now/background.js
+++ /dev/null
@@ -1,1504 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-/**
- * @fileoverview The event page for Google Now for Chrome implementation.
- * The Google Now event page gets Google Now cards from the server and shows
- * them as Chrome notifications.
- * The service performs periodic updating of Google Now cards.
- * Each updating of the cards includes 4 steps:
- * 1. Processing requests for cards dismissals that are not yet sent to the
- * server.
- * 2. Making a server request.
- * 3. Showing the received cards as notifications.
- */
-
-// TODO(robliao): Decide what to do in incognito mode.
-
-/**
- * Standard response code for successful HTTP requests. This is the only success
- * code the server will send.
- */
-var HTTP_OK = 200;
-var HTTP_NOCONTENT = 204;
-
-var HTTP_BAD_REQUEST = 400;
-var HTTP_UNAUTHORIZED = 401;
-var HTTP_FORBIDDEN = 403;
-var HTTP_METHOD_NOT_ALLOWED = 405;
-
-var MS_IN_SECOND = 1000;
-var MS_IN_MINUTE = 60 * 1000;
-
-/**
- * Initial period for polling for Google Now Notifications cards to use when the
- * period from the server is not available.
- */
-var INITIAL_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes
-
-/**
- * Mininal period for polling for Google Now Notifications cards.
- */
-var MINIMUM_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes
-
-/**
- * Maximal period for polling for Google Now Notifications cards to use when the
- * period from the server is not available.
- */
-var MAXIMUM_POLLING_PERIOD_SECONDS = 30 * 60; // 30 minutes
-
-/**
- * Initial period for polling for Google Now optin notification after push
- * messaging indicates Google Now is enabled.
- */
-var INITIAL_OPTIN_RECHECK_PERIOD_SECONDS = 60; // 1 minute
-
-/**
- * Maximum period for polling for Google Now optin notification after push
- * messaging indicates Google Now is enabled. It is expected that the alarm
- * will be stopped after this.
- */
-var MAXIMUM_OPTIN_RECHECK_PERIOD_SECONDS = 16 * 60; // 16 minutes
-
-/**
- * Initial period for retrying the server request for dismissing cards.
- */
-var INITIAL_RETRY_DISMISS_PERIOD_SECONDS = 60; // 1 minute
-
-/**
- * Maximum period for retrying the server request for dismissing cards.
- */
-var MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS = 60 * 60; // 1 hour
-
-/**
- * Time we keep retrying dismissals.
- */
-var MAXIMUM_DISMISSAL_AGE_MS = 24 * 60 * 60 * 1000; // 1 day
-
-/**
- * Time we keep dismissals after successful server dismiss requests.
- */
-var DISMISS_RETENTION_TIME_MS = 20 * 60 * 1000; // 20 minutes
-
-/**
- * Default period for checking whether the user is opted in to Google Now.
- */
-var DEFAULT_OPTIN_CHECK_PERIOD_SECONDS = 60 * 60 * 24 * 7; // 1 week
-
-/**
- * URL to open when the user clicked on a link for the our notification
- * settings.
- */
-var SETTINGS_URL = 'https://support.google.com/chrome/?p=ib_google_now_welcome';
-
-/**
- * GCM registration URL.
- */
-var GCM_REGISTRATION_URL =
- 'https://android.googleapis.com/gcm/googlenotification';
-
-/**
- * DevConsole project ID for GCM API use.
- */
-var GCM_PROJECT_ID = '437902709571';
-
-/**
- * Number of cards that need an explanatory link.
- */
-var EXPLANATORY_CARDS_LINK_THRESHOLD = 4;
-
-/**
- * Names for tasks that can be created by the extension.
- */
-var UPDATE_CARDS_TASK_NAME = 'update-cards';
-var DISMISS_CARD_TASK_NAME = 'dismiss-card';
-var RETRY_DISMISS_TASK_NAME = 'retry-dismiss';
-var STATE_CHANGED_TASK_NAME = 'state-changed';
-var SHOW_ON_START_TASK_NAME = 'show-cards-on-start';
-var ON_PUSH_MESSAGE_START_TASK_NAME = 'on-push-message';
-
-/**
- * Group as received from the server.
- *
- * @typedef {{
- * nextPollSeconds: (string|undefined),
- * rank: (number|undefined),
- * requested: (boolean|undefined)
- * }}
- */
-var ReceivedGroup;
-
-/**
- * Server response with notifications and groups.
- *
- * @typedef {{
- * googleNowDisabled: (boolean|undefined),
- * groups: Object<ReceivedGroup>,
- * notifications: Array<ReceivedNotification>
- * }}
- */
-var ServerResponse;
-
-/**
- * Notification group as the client stores it. |cardsTimestamp| and |rank| are
- * defined if |cards| is non-empty. |nextPollTime| is undefined if the server
- * (1) never sent 'nextPollSeconds' for the group or
- * (2) didn't send 'nextPollSeconds' with the last group update containing a
- * cards update and all the times after that.
- *
- * @typedef {{
- * cards: Array<ReceivedNotification>,
- * cardsTimestamp: (number|undefined),
- * nextPollTime: (number|undefined),
- * rank: (number|undefined)
- * }}
- */
-var StoredNotificationGroup;
-
-/**
- * Pending (not yet successfully sent) dismissal for a received notification.
- * |time| is the moment when the user requested dismissal.
- *
- * @typedef {{
- * chromeNotificationId: ChromeNotificationId,
- * time: number,
- * dismissalData: DismissalData
- * }}
- */
-var PendingDismissal;
-
-/**
- * Checks if a new task can't be scheduled when another task is already
- * scheduled.
- * @param {string} newTaskName Name of the new task.
- * @param {string} scheduledTaskName Name of the scheduled task.
- * @return {boolean} Whether the new task conflicts with the existing task.
- */
-function areTasksConflicting(newTaskName, scheduledTaskName) {
- if (newTaskName == UPDATE_CARDS_TASK_NAME &&
- scheduledTaskName == UPDATE_CARDS_TASK_NAME) {
- // If a card update is requested while an old update is still scheduled, we
- // don't need the new update.
- return true;
- }
-
- if (newTaskName == RETRY_DISMISS_TASK_NAME &&
- (scheduledTaskName == UPDATE_CARDS_TASK_NAME ||
- scheduledTaskName == DISMISS_CARD_TASK_NAME ||
- scheduledTaskName == RETRY_DISMISS_TASK_NAME)) {
- // No need to schedule retry-dismiss action if another action that tries to
- // send dismissals is scheduled.
- return true;
- }
-
- return false;
-}
-
-var tasks = buildTaskManager(areTasksConflicting);
-
-// Add error processing to API calls.
-wrapper.instrumentChromeApiFunction('gcm.onMessage.addListener', 0);
-wrapper.instrumentChromeApiFunction('gcm.register', 1);
-wrapper.instrumentChromeApiFunction('gcm.unregister', 0);
-wrapper.instrumentChromeApiFunction('metricsPrivate.getVariationParams', 1);
-wrapper.instrumentChromeApiFunction('notifications.clear', 1);
-wrapper.instrumentChromeApiFunction('notifications.create', 2);
-wrapper.instrumentChromeApiFunction('notifications.getPermissionLevel', 0);
-wrapper.instrumentChromeApiFunction('notifications.update', 2);
-wrapper.instrumentChromeApiFunction('notifications.getAll', 0);
-wrapper.instrumentChromeApiFunction(
- 'notifications.onButtonClicked.addListener', 0);
-wrapper.instrumentChromeApiFunction('notifications.onClicked.addListener', 0);
-wrapper.instrumentChromeApiFunction('notifications.onClosed.addListener', 0);
-wrapper.instrumentChromeApiFunction(
- 'notifications.onPermissionLevelChanged.addListener', 0);
-wrapper.instrumentChromeApiFunction(
- 'notifications.onShowSettings.addListener', 0);
-wrapper.instrumentChromeApiFunction('permissions.contains', 1);
-wrapper.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0);
-wrapper.instrumentChromeApiFunction('runtime.onStartup.addListener', 0);
-wrapper.instrumentChromeApiFunction('storage.onChanged.addListener', 0);
-wrapper.instrumentChromeApiFunction('tabs.create', 1);
-
-var updateCardsAttempts = buildAttemptManager(
- 'cards-update',
- requestCards,
- INITIAL_POLLING_PERIOD_SECONDS,
- MAXIMUM_POLLING_PERIOD_SECONDS);
-var optInPollAttempts = buildAttemptManager(
- 'optin',
- pollOptedInNoImmediateRecheck,
- INITIAL_POLLING_PERIOD_SECONDS,
- MAXIMUM_POLLING_PERIOD_SECONDS);
-var optInRecheckAttempts = buildAttemptManager(
- 'optin-recheck',
- pollOptedInWithRecheck,
- INITIAL_OPTIN_RECHECK_PERIOD_SECONDS,
- MAXIMUM_OPTIN_RECHECK_PERIOD_SECONDS);
-var dismissalAttempts = buildAttemptManager(
- 'dismiss',
- retryPendingDismissals,
- INITIAL_RETRY_DISMISS_PERIOD_SECONDS,
- MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS);
-var cardSet = buildCardSet();
-
-var authenticationManager = buildAuthenticationManager();
-
-/**
- * Google Now UMA event identifier.
- * @enum {number}
- */
-var GoogleNowEvent = {
- REQUEST_FOR_CARDS_TOTAL: 0,
- REQUEST_FOR_CARDS_SUCCESS: 1,
- CARDS_PARSE_SUCCESS: 2,
- DISMISS_REQUEST_TOTAL: 3,
- DISMISS_REQUEST_SUCCESS: 4,
- LOCATION_REQUEST: 5,
- DELETED_LOCATION_UPDATE: 6,
- EXTENSION_START: 7,
- DELETED_SHOW_WELCOME_TOAST: 8,
- STOPPED: 9,
- DELETED_USER_SUPPRESSED: 10,
- SIGNED_OUT: 11,
- NOTIFICATION_DISABLED: 12,
- GOOGLE_NOW_DISABLED: 13,
- EVENTS_TOTAL: 14 // EVENTS_TOTAL is not an event; all new events need to be
- // added before it.
-};
-
-/**
- * Records a Google Now Event.
- * @param {GoogleNowEvent} event Event identifier.
- */
-function recordEvent(event) {
- var metricDescription = {
- metricName: 'GoogleNow.Event',
- type: chrome.metricsPrivate.MetricTypeType.HISTOGRAM_LINEAR,
- min: 1,
- max: GoogleNowEvent.EVENTS_TOTAL,
- buckets: GoogleNowEvent.EVENTS_TOTAL + 1
- };
-
- chrome.metricsPrivate.recordValue(metricDescription, event);
-}
-
-/**
- * Records a notification clicked event.
- * @param {number|undefined} cardTypeId Card type ID.
- */
-function recordNotificationClick(cardTypeId) {
- if (cardTypeId !== undefined) {
- chrome.metricsPrivate.recordSparseValue(
- 'GoogleNow.Card.Clicked', cardTypeId);
- }
-}
-
-/**
- * Records a button clicked event.
- * @param {number|undefined} cardTypeId Card type ID.
- * @param {number} buttonIndex Button Index
- */
-function recordButtonClick(cardTypeId, buttonIndex) {
- if (cardTypeId !== undefined) {
- chrome.metricsPrivate.recordSparseValue(
- 'GoogleNow.Card.Button.Clicked' + buttonIndex, cardTypeId);
- }
-}
-
-/**
- * Checks the result of the HTTP Request and updates the authentication
- * manager on any failure.
- * @param {string} token Authentication token to validate against an
- * XMLHttpRequest.
- * @return {function(XMLHttpRequest)} Function that validates the token with the
- * supplied XMLHttpRequest.
- */
-function checkAuthenticationStatus(token) {
- return function(request) {
- if (request.status == HTTP_FORBIDDEN ||
- request.status == HTTP_UNAUTHORIZED) {
- authenticationManager.removeToken(token);
- }
- }
-}
-
-/**
- * Builds and sends an authenticated request to the notification server.
- * @param {string} method Request method.
- * @param {string} handlerName Server handler to send the request to.
- * @param {string=} opt_contentType Value for the Content-type header.
- * @return {Promise} A promise to issue a request to the server.
- * The promise rejects if the response is not within the HTTP 200 range.
- */
-function requestFromServer(method, handlerName, opt_contentType) {
- return authenticationManager.getAuthToken().then(function(token) {
- var request = buildServerRequest(method, handlerName, opt_contentType);
- request.setRequestHeader('Authorization', 'Bearer ' + token);
- var requestPromise = new Promise(function(resolve, reject) {
- request.addEventListener('loadend', function() {
- if ((200 <= request.status) && (request.status < 300)) {
- resolve(request);
- } else {
- reject(request);
- }
- }, false);
- request.send();
- });
- requestPromise.catch(checkAuthenticationStatus(token));
- return requestPromise;
- });
-}
-
-/**
- * Shows the notification groups as notification cards.
- * @param {Object<StoredNotificationGroup>} notificationGroups Map from group
- * name to group information.
- * @param {function(ReceivedNotification)=} opt_onCardShown Optional parameter
- * called when each card is shown.
- * @return {Promise} A promise to show the notification groups as cards.
- */
-function showNotificationGroups(notificationGroups, opt_onCardShown) {
- /** @type {Object<ChromeNotificationId, CombinedCard>} */
- var cards = combineCardsFromGroups(notificationGroups);
- console.log('showNotificationGroups ' + JSON.stringify(cards));
-
- return new Promise(function(resolve) {
- instrumented.notifications.getAll(function(notifications) {
- console.log('showNotificationGroups-getAll ' +
- JSON.stringify(notifications));
- notifications = notifications || {};
-
- // Mark notifications that didn't receive an update as having received
- // an empty update.
- for (var chromeNotificationId in notifications) {
- cards[chromeNotificationId] = cards[chromeNotificationId] || [];
- }
-
- /** @type {Object<ChromeNotificationId, NotificationDataEntry>} */
- var notificationsData = {};
-
- // Create/update/delete notifications.
- for (var chromeNotificationId in cards) {
- notificationsData[chromeNotificationId] = cardSet.update(
- chromeNotificationId,
- cards[chromeNotificationId],
- notificationGroups,
- opt_onCardShown);
- }
- chrome.storage.local.set({notificationsData: notificationsData});
- resolve();
- });
- });
-}
-
-/**
- * Removes all cards and card state on Google Now close down.
- */
-function removeAllCards() {
- console.log('removeAllCards');
-
- // TODO(robliao): Once Google Now clears its own checkbox in the
- // notifications center and bug 260376 is fixed, the below clearing
- // code is no longer necessary.
- instrumented.notifications.getAll(function(notifications) {
- notifications = notifications || {};
- for (var chromeNotificationId in notifications) {
- instrumented.notifications.clear(chromeNotificationId, function() {});
- }
- chrome.storage.local.remove(['notificationsData', 'notificationGroups']);
- });
-}
-
-/**
- * Adds a card group into a set of combined cards.
- * @param {Object<ChromeNotificationId, CombinedCard>} combinedCards Map from
- * chromeNotificationId to a combined card.
- * This is an input/output parameter.
- * @param {StoredNotificationGroup} storedGroup Group to combine into the
- * combined card set.
- */
-function combineGroup(combinedCards, storedGroup) {
- for (var i = 0; i < storedGroup.cards.length; i++) {
- /** @type {ReceivedNotification} */
- var receivedNotification = storedGroup.cards[i];
-
- /** @type {UncombinedNotification} */
- var uncombinedNotification = {
- receivedNotification: receivedNotification,
- showTime: receivedNotification.trigger.showTimeSec &&
- (storedGroup.cardsTimestamp +
- receivedNotification.trigger.showTimeSec * MS_IN_SECOND),
- hideTime: storedGroup.cardsTimestamp +
- receivedNotification.trigger.hideTimeSec * MS_IN_SECOND
- };
-
- var combinedCard =
- combinedCards[receivedNotification.chromeNotificationId] || [];
- combinedCard.push(uncombinedNotification);
- combinedCards[receivedNotification.chromeNotificationId] = combinedCard;
- }
-}
-
-/**
- * Calculates the soonest poll time from a map of groups as an absolute time.
- * @param {Object<StoredNotificationGroup>} groups Map from group name to group
- * information.
- * @return {number} The next poll time based off of the groups.
- */
-function calculateNextPollTimeMilliseconds(groups) {
- var nextPollTime = null;
-
- for (var groupName in groups) {
- var group = groups[groupName];
- if (group.nextPollTime !== undefined) {
- nextPollTime = nextPollTime == null ?
- group.nextPollTime : Math.min(group.nextPollTime, nextPollTime);
- }
- }
-
- // At least one of the groups must have nextPollTime.
- verify(nextPollTime != null, 'calculateNextPollTime: nextPollTime is null');
- return nextPollTime;
-}
-
-/**
- * Schedules next cards poll.
- * @param {Object<StoredNotificationGroup>} groups Map from group name to group
- * information.
- */
-function scheduleNextCardsPoll(groups) {
- var nextPollTimeMs = calculateNextPollTimeMilliseconds(groups);
-
- var nextPollDelaySeconds = Math.max(
- (nextPollTimeMs - Date.now()) / MS_IN_SECOND,
- MINIMUM_POLLING_PERIOD_SECONDS);
- updateCardsAttempts.start(nextPollDelaySeconds);
-}
-
-/**
- * Schedules the next opt-in check poll.
- */
-function scheduleOptInCheckPoll() {
- instrumented.metricsPrivate.getVariationParams(
- 'GoogleNow', function(params) {
- var optinPollPeriodSeconds =
- parseInt(params && params.optinPollPeriodSeconds, 10) ||
- DEFAULT_OPTIN_CHECK_PERIOD_SECONDS;
- optInPollAttempts.start(optinPollPeriodSeconds);
- });
-}
-
-/**
- * Combines notification groups into a set of Chrome notifications.
- * @param {Object<StoredNotificationGroup>} notificationGroups Map from group
- * name to group information.
- * @return {Object<ChromeNotificationId, CombinedCard>} Cards to show.
- */
-function combineCardsFromGroups(notificationGroups) {
- console.log('combineCardsFromGroups ' + JSON.stringify(notificationGroups));
- /** @type {Object<ChromeNotificationId, CombinedCard>} */
- var combinedCards = {};
-
- for (var groupName in notificationGroups)
- combineGroup(combinedCards, notificationGroups[groupName]);
-
- return combinedCards;
-}
-
-/**
- * Processes a server response for consumption by showNotificationGroups.
- * @param {ServerResponse} response Server response.
- * @return {Promise} A promise to process the server response and provide
- * updated groups. Rejects if the server response shouldn't be processed.
- */
-function processServerResponse(response) {
- console.log('processServerResponse ' + JSON.stringify(response));
-
- if (response.googleNowDisabled) {
- chrome.storage.local.set({googleNowEnabled: false});
- // Stop processing now. The state change will clear the cards.
- return Promise.reject();
- }
-
- var receivedGroups = response.groups;
-
- return fillFromChromeLocalStorage({
- /** @type {Object<StoredNotificationGroup>} */
- notificationGroups: {},
- /** @type {Object<ServerNotificationId, number>} */
- recentDismissals: {}
- }).then(function(items) {
- console.log('processServerResponse-get ' + JSON.stringify(items));
-
- // Build a set of non-expired recent dismissals. It will be used for
- // client-side filtering of cards.
- /** @type {Object<ServerNotificationId, number>} */
- var updatedRecentDismissals = {};
- var now = Date.now();
- for (var serverNotificationId in items.recentDismissals) {
- var dismissalAge = now - items.recentDismissals[serverNotificationId];
- if (dismissalAge < DISMISS_RETENTION_TIME_MS) {
- updatedRecentDismissals[serverNotificationId] =
- items.recentDismissals[serverNotificationId];
- }
- }
-
- // Populate groups with corresponding cards.
- if (response.notifications) {
- for (var i = 0; i < response.notifications.length; ++i) {
- /** @type {ReceivedNotification} */
- var card = response.notifications[i];
- if (!(card.notificationId in updatedRecentDismissals)) {
- var group = receivedGroups[card.groupName];
- group.cards = group.cards || [];
- group.cards.push(card);
- }
- }
- }
-
- // Build updated set of groups.
- var updatedGroups = {};
-
- for (var groupName in receivedGroups) {
- var receivedGroup = receivedGroups[groupName];
- var storedGroup = items.notificationGroups[groupName] || {
- cards: [],
- cardsTimestamp: undefined,
- nextPollTime: undefined,
- rank: undefined
- };
-
- if (receivedGroup.requested)
- receivedGroup.cards = receivedGroup.cards || [];
-
- if (receivedGroup.cards) {
- // If the group contains a cards update, all its fields will get new
- // values.
- storedGroup.cards = receivedGroup.cards;
- storedGroup.cardsTimestamp = now;
- storedGroup.rank = receivedGroup.rank;
- storedGroup.nextPollTime = undefined;
- // The code below assigns nextPollTime a defined value if
- // nextPollSeconds is specified in the received group.
- // If the group's cards are not updated, and nextPollSeconds is
- // unspecified, this method doesn't change group's nextPollTime.
- }
-
- // 'nextPollSeconds' may be sent even for groups that don't contain
- // cards updates.
- if (receivedGroup.nextPollSeconds !== undefined) {
- storedGroup.nextPollTime =
- now + receivedGroup.nextPollSeconds * MS_IN_SECOND;
- }
-
- updatedGroups[groupName] = storedGroup;
- }
-
- scheduleNextCardsPoll(updatedGroups);
- return {
- updatedGroups: updatedGroups,
- recentDismissals: updatedRecentDismissals
- };
- });
-}
-
-/**
- * Update the Explanatory Total Cards Shown Count.
- */
-function countExplanatoryCard() {
- localStorage['explanatoryCardsShown']++;
-}
-
-/**
- * Determines if cards should have an explanation link.
- * @return {boolean} true if an explanatory card should be shown.
- */
-function shouldShowExplanatoryCard() {
- var isBelowThreshold =
- localStorage['explanatoryCardsShown'] < EXPLANATORY_CARDS_LINK_THRESHOLD;
- return isBelowThreshold;
-}
-
-/**
- * Requests notification cards from the server for specified groups.
- * @param {Array<string>} groupNames Names of groups that need to be refreshed.
- * @return {Promise} A promise to request the specified notification groups.
- */
-function requestNotificationGroupsFromServer(groupNames) {
- console.log(
- 'requestNotificationGroupsFromServer from ' + NOTIFICATION_CARDS_URL +
- ', groupNames=' + JSON.stringify(groupNames));
-
- recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
-
- var requestParameters = '?timeZoneOffsetMs=' +
- (-new Date().getTimezoneOffset() * MS_IN_MINUTE);
-
- if (shouldShowExplanatoryCard()) {
- requestParameters += '&cardExplanation=true';
- }
-
- groupNames.forEach(function(groupName) {
- requestParameters += ('&requestTypes=' + groupName);
- });
-
- requestParameters += '&uiLocale=' + navigator.language;
-
- console.log(
- 'requestNotificationGroupsFromServer: request=' + requestParameters);
-
- return requestFromServer('GET', 'notifications' + requestParameters).then(
- function(request) {
- console.log(
- 'requestNotificationGroupsFromServer-received ' + request.status);
- if (request.status == HTTP_OK) {
- recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
- return JSON.parse(request.responseText);
- }
- });
-}
-
-/**
- * Performs an opt-in poll without an immediate recheck.
- * If the response is not opted-in, schedule an opt-in check poll.
- */
-function pollOptedInNoImmediateRecheck() {
- requestAndUpdateOptedIn()
- .then(function(optedIn) {
- if (!optedIn) {
- // Request a repoll if we're not opted in.
- return Promise.reject();
- }
- })
- .catch(function() {
- scheduleOptInCheckPoll();
- });
-}
-
-/**
- * Requests the account opted-in state from the server and updates any
- * state as necessary.
- * @return {Promise} A promise to request and update the opted-in state.
- * The promise resolves with the opt-in state.
- */
-function requestAndUpdateOptedIn() {
- console.log('requestOptedIn from ' + NOTIFICATION_CARDS_URL);
-
- return requestFromServer('GET', 'settings/optin').then(function(request) {
- console.log(
- 'requestOptedIn-received ' + request.status + ' ' + request.response);
- if (request.status == HTTP_OK) {
- var parsedResponse = JSON.parse(request.responseText);
- return parsedResponse.value;
- }
- }).then(function(optedIn) {
- chrome.storage.local.set({googleNowEnabled: optedIn});
- return optedIn;
- });
-}
-
-/**
- * Determines the groups that need to be requested right now.
- * @return {Promise} A promise to determine the groups to request.
- */
-function getGroupsToRequest() {
- return fillFromChromeLocalStorage({
- /** @type {Object<StoredNotificationGroup>} */
- notificationGroups: {}
- }).then(function(items) {
- console.log('getGroupsToRequest-storage-get ' + JSON.stringify(items));
- var groupsToRequest = [];
- var now = Date.now();
-
- for (var groupName in items.notificationGroups) {
- var group = items.notificationGroups[groupName];
- if (group.nextPollTime !== undefined && group.nextPollTime <= now)
- groupsToRequest.push(groupName);
- }
- return groupsToRequest;
- });
-}
-
-/**
- * Requests notification cards from the server.
- * @return {Promise} A promise to request the notification cards.
- * Rejects if the cards won't be requested.
- */
-function requestNotificationCards() {
- console.log('requestNotificationCards');
- return getGroupsToRequest()
- .then(requestNotificationGroupsFromServer)
- .then(processServerResponse)
- .then(function(processedResponse) {
- var onCardShown =
- shouldShowExplanatoryCard() ? countExplanatoryCard : undefined;
- return showNotificationGroups(
- processedResponse.updatedGroups, onCardShown).then(function() {
- chrome.storage.local.set({
- notificationGroups: processedResponse.updatedGroups,
- recentDismissals: processedResponse.updatedRecentDismissals
- });
- recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS);
- }
- );
- });
-}
-
-/**
- * Determines if an immediate retry should occur based off of the given groups.
- * The NOR group is expected most often and less latency sensitive, so we will
- * simply wait MAXIMUM_POLLING_PERIOD_SECONDS before trying again.
- * @param {Array<string>} groupNames Names of groups that need to be refreshed.
- * @return {boolean} Whether a retry should occur.
- */
-function shouldScheduleRetryFromGroupList(groupNames) {
- return (groupNames.length != 1) || (groupNames[0] !== 'NOR');
-}
-
-/**
- * Requests and shows notification cards.
- */
-function requestCards() {
- console.log('requestCards @' + new Date());
- // LOCATION_REQUEST is a legacy histogram value when we requested location.
- // This corresponds to the extension attempting to request for cards.
- // We're keeping the name the same to keep our histograms in order.
- recordEvent(GoogleNowEvent.LOCATION_REQUEST);
- tasks.add(UPDATE_CARDS_TASK_NAME, function() {
- console.log('requestCards-task-begin');
- updateCardsAttempts.isRunning(function(running) {
- if (running) {
- // The cards are requested only if there are no unsent dismissals.
- processPendingDismissals()
- .then(requestNotificationCards)
- .catch(function() {
- return getGroupsToRequest().then(function(groupsToRequest) {
- if (shouldScheduleRetryFromGroupList(groupsToRequest)) {
- updateCardsAttempts.scheduleRetry();
- }
- });
- });
- }
- });
- });
-}
-
-/**
- * Sends a server request to dismiss a card.
- * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of
- * the card.
- * @param {number} dismissalTimeMs Time of the user's dismissal of the card in
- * milliseconds since epoch.
- * @param {DismissalData} dismissalData Data to build a dismissal request.
- * @return {Promise} A promise to request the card dismissal, rejects on error.
- */
-function requestCardDismissal(
- chromeNotificationId, dismissalTimeMs, dismissalData) {
- console.log('requestDismissingCard ' + chromeNotificationId +
- ' from ' + NOTIFICATION_CARDS_URL +
- ', dismissalData=' + JSON.stringify(dismissalData));
-
- var dismissalAge = Date.now() - dismissalTimeMs;
-
- if (dismissalAge > MAXIMUM_DISMISSAL_AGE_MS) {
- return Promise.resolve();
- }
-
- recordEvent(GoogleNowEvent.DISMISS_REQUEST_TOTAL);
-
- var requestParameters = 'notifications/' + dismissalData.notificationId +
- '?age=' + dismissalAge +
- '&chromeNotificationId=' + chromeNotificationId;
-
- for (var paramField in dismissalData.parameters)
- requestParameters += ('&' + paramField +
- '=' + dismissalData.parameters[paramField]);
-
- console.log('requestCardDismissal: requestParameters=' + requestParameters);
-
- return requestFromServer('DELETE', requestParameters).then(function(request) {
- console.log('requestDismissingCard-onloadend ' + request.status);
- if (request.status == HTTP_NOCONTENT)
- recordEvent(GoogleNowEvent.DISMISS_REQUEST_SUCCESS);
-
- // A dismissal doesn't require further retries if it was successful or
- // doesn't have a chance for successful completion.
- return (request.status == HTTP_NOCONTENT) ?
- Promise.resolve() :
- Promise.reject();
- }).catch(function(request) {
- request = (typeof request === 'object') ? request : {};
- return (request.status == HTTP_BAD_REQUEST ||
- request.status == HTTP_METHOD_NOT_ALLOWED) ?
- Promise.resolve() :
- Promise.reject();
- });
-}
-
-/**
- * Tries to send dismiss requests for all pending dismissals.
- * @return {Promise} A promise to process the pending dismissals.
- * The promise is rejected if a problem was encountered.
- */
-function processPendingDismissals() {
- return fillFromChromeLocalStorage({
- /** @type {Array<PendingDismissal>} */
- pendingDismissals: [],
- /** @type {Object<ServerNotificationId, number>} */
- recentDismissals: {}
- }).then(function(items) {
- console.log(
- 'processPendingDismissals-storage-get ' + JSON.stringify(items));
-
- var dismissalsChanged = false;
-
- function onFinish(success) {
- if (dismissalsChanged) {
- chrome.storage.local.set({
- pendingDismissals: items.pendingDismissals,
- recentDismissals: items.recentDismissals
- });
- }
- return success ? Promise.resolve() : Promise.reject();
- }
-
- function doProcessDismissals() {
- if (items.pendingDismissals.length == 0) {
- dismissalAttempts.stop();
- return onFinish(true);
- }
-
- // Send dismissal for the first card, and if successful, repeat
- // recursively with the rest.
- /** @type {PendingDismissal} */
- var dismissal = items.pendingDismissals[0];
- return requestCardDismissal(
- dismissal.chromeNotificationId,
- dismissal.time,
- dismissal.dismissalData).then(function() {
- dismissalsChanged = true;
- items.pendingDismissals.splice(0, 1);
- items.recentDismissals[dismissal.dismissalData.notificationId] =
- Date.now();
- return doProcessDismissals();
- }).catch(function() {
- return onFinish(false);
- });
- }
-
- return doProcessDismissals();
- });
-}
-
-/**
- * Submits a task to send pending dismissals.
- */
-function retryPendingDismissals() {
- tasks.add(RETRY_DISMISS_TASK_NAME, function() {
- processPendingDismissals().catch(dismissalAttempts.scheduleRetry);
- });
-}
-
-/**
- * Opens a URL in a new tab.
- * @param {string} url URL to open.
- */
-function openUrl(url) {
- instrumented.tabs.create({url: url}, function(tab) {
- if (tab)
- chrome.windows.update(tab.windowId, {focused: true});
- else
- chrome.windows.create({url: url, focused: true});
- });
-}
-
-/**
- * Opens URL corresponding to the clicked part of the notification.
- * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of
- * the card.
- * @param {function(NotificationDataEntry): (string|undefined)} selector
- * Function that extracts the url for the clicked area from the
- * notification data entry.
- */
-function onNotificationClicked(chromeNotificationId, selector) {
- fillFromChromeLocalStorage({
- /** @type {Object<ChromeNotificationId, NotificationDataEntry>} */
- notificationsData: {}
- }).then(function(items) {
- /** @type {(NotificationDataEntry|undefined)} */
- var notificationDataEntry = items.notificationsData[chromeNotificationId];
- if (!notificationDataEntry)
- return;
-
- var url = selector(notificationDataEntry);
- if (!url)
- return;
-
- openUrl(url);
- });
-}
-
-/**
- * Callback for chrome.notifications.onClosed event.
- * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of
- * the card.
- * @param {boolean} byUser Whether the notification was closed by the user.
- */
-function onNotificationClosed(chromeNotificationId, byUser) {
- if (!byUser)
- return;
-
- // At this point we are guaranteed that the notification is a now card.
- chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed');
-
- tasks.add(DISMISS_CARD_TASK_NAME, function() {
- dismissalAttempts.start();
-
- fillFromChromeLocalStorage({
- /** @type {Array<PendingDismissal>} */
- pendingDismissals: [],
- /** @type {Object<ChromeNotificationId, NotificationDataEntry>} */
- notificationsData: {},
- /** @type {Object<StoredNotificationGroup>} */
- notificationGroups: {}
- }).then(function(items) {
- /** @type {NotificationDataEntry} */
- var notificationData =
- items.notificationsData[chromeNotificationId] ||
- {
- timestamp: Date.now(),
- combinedCard: []
- };
-
- var dismissalResult =
- cardSet.onDismissal(
- chromeNotificationId,
- notificationData,
- items.notificationGroups);
-
- for (var i = 0; i < dismissalResult.dismissals.length; i++) {
- /** @type {PendingDismissal} */
- var dismissal = {
- chromeNotificationId: chromeNotificationId,
- time: Date.now(),
- dismissalData: dismissalResult.dismissals[i]
- };
- items.pendingDismissals.push(dismissal);
- }
-
- items.notificationsData[chromeNotificationId] =
- dismissalResult.notificationData;
-
- chrome.storage.local.set(items);
-
- processPendingDismissals();
- });
- });
-}
-
-/**
- * Initializes the polling system to start fetching cards.
- */
-function startPollingCards() {
- console.log('startPollingCards');
- // Create an update timer for a case when for some reason requesting
- // cards gets stuck.
- updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS);
- requestCards();
-}
-
-/**
- * Stops all machinery in the polling system.
- */
-function stopPollingCards() {
- console.log('stopPollingCards');
- updateCardsAttempts.stop();
- // Since we're stopping everything, clear all runtime storage.
- // We don't clear localStorage since those values are still relevant
- // across Google Now start-stop events.
- chrome.storage.local.clear();
-}
-
-/**
- * Initializes the event page on install or on browser startup.
- */
-function initialize() {
- recordEvent(GoogleNowEvent.EXTENSION_START);
- onStateChange();
-}
-
-/**
- * Starts or stops the main pipeline for polling cards.
- * @param {boolean} shouldPollCardsRequest true to start and
- * false to stop polling cards.
- */
-function setShouldPollCards(shouldPollCardsRequest) {
- updateCardsAttempts.isRunning(function(currentValue) {
- if (shouldPollCardsRequest != currentValue) {
- console.log('Action Taken setShouldPollCards=' + shouldPollCardsRequest);
- if (shouldPollCardsRequest)
- startPollingCards();
- else
- stopPollingCards();
- } else {
- console.log(
- 'Action Ignored setShouldPollCards=' + shouldPollCardsRequest);
- }
- });
-}
-
-/**
- * Starts or stops the optin check and GCM channel to receive optin
- * notifications.
- * @param {boolean} shouldPollOptInStatus true to start and false to stop
- * polling the optin status.
- */
-function setShouldPollOptInStatus(shouldPollOptInStatus) {
- optInPollAttempts.isRunning(function(currentValue) {
- if (shouldPollOptInStatus != currentValue) {
- console.log(
- 'Action Taken setShouldPollOptInStatus=' + shouldPollOptInStatus);
- if (shouldPollOptInStatus) {
- pollOptedInNoImmediateRecheck();
- } else {
- optInPollAttempts.stop();
- }
- } else {
- console.log(
- 'Action Ignored setShouldPollOptInStatus=' + shouldPollOptInStatus);
- }
- });
-
- if (shouldPollOptInStatus) {
- registerForGcm();
- } else {
- unregisterFromGcm();
- }
-}
-
-/**
- * Enables or disables the Google Now background permission.
- * @param {boolean} backgroundEnable true to run in the background.
- * false to not run in the background.
- */
-function setBackgroundEnable(backgroundEnable) {
- instrumented.permissions.contains({permissions: ['background']},
- function(hasPermission) {
- if (backgroundEnable != hasPermission) {
- console.log('Action Taken setBackgroundEnable=' + backgroundEnable);
- if (backgroundEnable)
- chrome.permissions.request({permissions: ['background']});
- else
- chrome.permissions.remove({permissions: ['background']});
- } else {
- console.log('Action Ignored setBackgroundEnable=' + backgroundEnable);
- }
- });
-}
-
-/**
- * Record why this extension would not poll for cards.
- * @param {boolean} signedIn true if the user is signed in.
- * @param {boolean} notificationEnabled true if
- * Google Now for Chrome is allowed to show notifications.
- * @param {boolean} googleNowEnabled true if
- * the Google Now is enabled for the user.
- */
-function recordEventIfNoCards(signedIn, notificationEnabled, googleNowEnabled) {
- if (!signedIn) {
- recordEvent(GoogleNowEvent.SIGNED_OUT);
- } else if (!notificationEnabled) {
- recordEvent(GoogleNowEvent.NOTIFICATION_DISABLED);
- } else if (!googleNowEnabled) {
- recordEvent(GoogleNowEvent.GOOGLE_NOW_DISABLED);
- }
-}
-
-/**
- * Does the actual work of deciding what Google Now should do
- * based off of the current state of Chrome.
- * @param {boolean} signedIn true if the user is signed in.
- * @param {boolean} canEnableBackground true if
- * the background permission can be requested.
- * @param {boolean} notificationEnabled true if
- * Google Now for Chrome is allowed to show notifications.
- * @param {boolean} googleNowEnabled true if
- * the Google Now is enabled for the user.
- */
-function updateRunningState(
- signedIn,
- canEnableBackground,
- notificationEnabled,
- googleNowEnabled) {
- console.log(
- 'State Update signedIn=' + signedIn + ' ' +
- 'canEnableBackground=' + canEnableBackground + ' ' +
- 'notificationEnabled=' + notificationEnabled + ' ' +
- 'googleNowEnabled=' + googleNowEnabled);
-
- var shouldPollCards = false;
- var shouldPollOptInStatus = false;
- var shouldSetBackground = false;
-
- if (signedIn && notificationEnabled) {
- shouldPollCards = googleNowEnabled;
- shouldPollOptInStatus = !googleNowEnabled;
- shouldSetBackground = canEnableBackground && googleNowEnabled;
- } else {
- recordEvent(GoogleNowEvent.STOPPED);
- }
-
- recordEventIfNoCards(signedIn, notificationEnabled, googleNowEnabled);
-
- console.log(
- 'Requested Actions shouldSetBackground=' + shouldSetBackground + ' ' +
- 'setShouldPollCards=' + shouldPollCards + ' ' +
- 'shouldPollOptInStatus=' + shouldPollOptInStatus);
-
- setBackgroundEnable(shouldSetBackground);
- setShouldPollCards(shouldPollCards);
- setShouldPollOptInStatus(shouldPollOptInStatus);
- if (!shouldPollCards) {
- removeAllCards();
- }
-}
-
-/**
- * Coordinates the behavior of Google Now for Chrome depending on
- * Chrome and extension state.
- */
-function onStateChange() {
- tasks.add(STATE_CHANGED_TASK_NAME, function() {
- Promise.all([
- authenticationManager.isSignedIn(),
- canEnableBackground(),
- isNotificationsEnabled(),
- isGoogleNowEnabled()])
- .then(function(results) {
- updateRunningState.apply(null, results);
- });
- });
-}
-
-/**
- * Determines if background mode should be requested.
- * @return {Promise} A promise to determine if background can be enabled.
- */
-function canEnableBackground() {
- return new Promise(function(resolve) {
- instrumented.metricsPrivate.getVariationParams(
- 'GoogleNow',
- function(response) {
- resolve(!response || (response.canEnableBackground != 'false'));
- });
- });
-}
-
-/**
- * Checks if Google Now is enabled in the notifications center.
- * @return {Promise} A promise to determine if Google Now is enabled
- * in the notifications center.
- */
-function isNotificationsEnabled() {
- return new Promise(function(resolve) {
- instrumented.notifications.getPermissionLevel(function(level) {
- resolve(level == 'granted');
- });
- });
-}
-
-/**
- * Gets the previous Google Now opt-in state.
- * @return {Promise} A promise to determine the previous Google Now
- * opt-in state.
- */
-function isGoogleNowEnabled() {
- return fillFromChromeLocalStorage({googleNowEnabled: false})
- .then(function(items) {
- return items.googleNowEnabled;
- });
-}
-
-/**
- * Ensures the extension is ready to listen for GCM messages.
- */
-function registerForGcm() {
- // We don't need to use the key yet, just ensure the channel is set up.
- getGcmNotificationKey();
-}
-
-/**
- * Returns a Promise resolving to either a cached or new GCM notification key.
- * Rejects if registration fails.
- * @return {Promise} A Promise that resolves to a potentially-cached GCM key.
- */
-function getGcmNotificationKey() {
- return fillFromChromeLocalStorage({gcmNotificationKey: undefined})
- .then(function(items) {
- if (items.gcmNotificationKey) {
- console.log('Reused gcm key from storage.');
- return Promise.resolve(items.gcmNotificationKey);
- }
- return requestNewGcmNotificationKey();
- });
-}
-
-/**
- * Returns a promise resolving to a GCM Notificaiton Key. May call
- * chrome.gcm.register() first if required. Rejects on registration failure.
- * @return {Promise} A Promise that resolves to a fresh GCM Notification key.
- */
-function requestNewGcmNotificationKey() {
- return getGcmRegistrationId().then(function(gcmId) {
- authenticationManager.getAuthToken().then(function(token) {
- authenticationManager.getLogin().then(function(username) {
- return new Promise(function(resolve, reject) {
- var xhr = new XMLHttpRequest();
- xhr.responseType = 'application/json';
- xhr.open('POST', GCM_REGISTRATION_URL, true);
- xhr.setRequestHeader('Content-Type', 'application/json');
- xhr.setRequestHeader('Authorization', 'Bearer ' + token);
- xhr.setRequestHeader('project_id', GCM_PROJECT_ID);
- var payload = {
- 'operation': 'add',
- 'notification_key_name': username,
- 'registration_ids': [gcmId]
- };
- xhr.onloadend = function() {
- if (xhr.status != 200) {
- reject();
- }
- var obj = JSON.parse(xhr.responseText);
- var key = obj && obj.notification_key;
- if (!key) {
- reject();
- }
- console.log('gcm notification key POST: ' + key);
- chrome.storage.local.set({gcmNotificationKey: key});
- resolve(key);
- };
- xhr.send(JSON.stringify(payload));
- });
- });
- }).catch(function() {
- // Couldn't obtain a GCM ID. Ignore and fallback to polling.
- });
- });
-}
-
-/**
- * Returns a promise resolving to either a cached or new GCM registration ID.
- * Rejects if registration fails.
- * @return {Promise} A Promise that resolves to a GCM registration ID.
- */
-function getGcmRegistrationId() {
- return fillFromChromeLocalStorage({gcmRegistrationId: undefined})
- .then(function(items) {
- if (items.gcmRegistrationId) {
- console.log('Reused gcm registration id from storage.');
- return Promise.resolve(items.gcmRegistrationId);
- }
-
- return new Promise(function(resolve, reject) {
- instrumented.gcm.register([GCM_PROJECT_ID], function(registrationId) {
- console.log('gcm.register(): ' + registrationId);
- if (registrationId) {
- chrome.storage.local.set({gcmRegistrationId: registrationId});
- resolve(registrationId);
- } else {
- reject();
- }
- });
- });
- });
-}
-
-/**
- * Unregisters from GCM if previously registered.
- */
-function unregisterFromGcm() {
- fillFromChromeLocalStorage({gcmRegistrationId: undefined})
- .then(function(items) {
- if (items.gcmRegistrationId) {
- console.log('Unregistering from gcm.');
- instrumented.gcm.unregister(function() {
- if (!chrome.runtime.lastError) {
- chrome.storage.local.remove(
- ['gcmNotificationKey', 'gcmRegistrationId']);
- }
- });
- }
- });
-}
-
-/**
- * Polls the optin state.
- * Sometimes we get the response to the opted in result too soon during
- * push messaging. We'll recheck the optin state a few times before giving up.
- */
-function pollOptedInWithRecheck() {
- /**
- * Cleans up any state used to recheck the opt-in poll.
- */
- function clearPollingState() {
- localStorage.removeItem('optedInCheckCount');
- optInRecheckAttempts.stop();
- }
-
- if (localStorage.optedInCheckCount === undefined) {
- localStorage.optedInCheckCount = 0;
- optInRecheckAttempts.start();
- }
-
- console.log(new Date() +
- ' checkOptedIn Attempt ' + localStorage.optedInCheckCount);
-
- requestAndUpdateOptedIn().then(function(optedIn) {
- if (optedIn) {
- clearPollingState();
- return Promise.resolve();
- } else {
- // If we're not opted in, reject to retry.
- return Promise.reject();
- }
- }).catch(function() {
- if (localStorage.optedInCheckCount < 5) {
- localStorage.optedInCheckCount++;
- optInRecheckAttempts.scheduleRetry();
- } else {
- clearPollingState();
- }
- });
-}
-
-instrumented.runtime.onInstalled.addListener(function(details) {
- console.log('onInstalled ' + JSON.stringify(details));
- if (details.reason != 'chrome_update') {
- initialize();
- }
-});
-
-instrumented.runtime.onStartup.addListener(function() {
- console.log('onStartup');
-
- // Show notifications received by earlier polls. Doing this as early as
- // possible to reduce latency of showing first notifications. This mimics how
- // persistent notifications will work.
- tasks.add(SHOW_ON_START_TASK_NAME, function() {
- fillFromChromeLocalStorage({
- /** @type {Object<StoredNotificationGroup>} */
- notificationGroups: {}
- }).then(function(items) {
- console.log('onStartup-get ' + JSON.stringify(items));
-
- showNotificationGroups(items.notificationGroups).then(function() {
- chrome.storage.local.set(items);
- });
- });
- });
-
- initialize();
-});
-
-authenticationManager.addListener(function() {
- console.log('signIn State Change');
- onStateChange();
-});
-
-instrumented.notifications.onClicked.addListener(
- function(chromeNotificationId) {
- chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked');
- onNotificationClicked(chromeNotificationId,
- function(notificationDataEntry) {
- var actionUrls = notificationDataEntry.actionUrls;
- var url = actionUrls && actionUrls.messageUrl;
- if (url) {
- recordNotificationClick(notificationDataEntry.cardTypeId);
- }
- return url;
- });
- });
-
-instrumented.notifications.onButtonClicked.addListener(
- function(chromeNotificationId, buttonIndex) {
- chrome.metricsPrivate.recordUserAction(
- 'GoogleNow.ButtonClicked' + buttonIndex);
- onNotificationClicked(chromeNotificationId,
- function(notificationDataEntry) {
- var actionUrls = notificationDataEntry.actionUrls;
- var url = actionUrls.buttonUrls[buttonIndex];
- if (url) {
- recordButtonClick(notificationDataEntry.cardTypeId, buttonIndex);
- } else {
- verify(false, 'onButtonClicked: no url for a button');
- console.log(
- 'buttonIndex=' + buttonIndex + ' ' +
- 'chromeNotificationId=' + chromeNotificationId + ' ' +
- 'notificationDataEntry=' +
- JSON.stringify(notificationDataEntry));
- }
- return url;
- });
- });
-
-instrumented.notifications.onClosed.addListener(onNotificationClosed);
-
-instrumented.notifications.onPermissionLevelChanged.addListener(
- function(permissionLevel) {
- console.log('Notifications permissionLevel Change');
- onStateChange();
- });
-
-instrumented.notifications.onShowSettings.addListener(function() {
- openUrl(SETTINGS_URL);
-});
-
-// Handles state change notifications for the Google Now enabled bit.
-instrumented.storage.onChanged.addListener(function(changes, areaName) {
- if (areaName === 'local') {
- if ('googleNowEnabled' in changes) {
- onStateChange();
- }
- }
-});
-
-instrumented.gcm.onMessage.addListener(function(message) {
- console.log('gcm.onMessage ' + JSON.stringify(message));
- if (!message || !message.data) {
- return;
- }
-
- var payload = message.data.payload;
- var tag = message.data.tag;
- if (payload.startsWith('REQUEST_CARDS')) {
- tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() {
- // Accept promise rejection on failure since it's safer to do nothing,
- // preventing polling the server when the payload really didn't change.
- fillFromChromeLocalStorage({
- lastPollNowPayloads: {},
- /** @type {Object<StoredNotificationGroup>} */
- notificationGroups: {}
- }, PromiseRejection.ALLOW).then(function(items) {
- if (items.lastPollNowPayloads[tag] != payload) {
- items.lastPollNowPayloads[tag] = payload;
-
- items.notificationGroups['PUSH' + tag] = {
- cards: [],
- nextPollTime: Date.now()
- };
-
- chrome.storage.local.set({
- lastPollNowPayloads: items.lastPollNowPayloads,
- notificationGroups: items.notificationGroups
- });
-
- pollOptedInWithRecheck();
- }
- });
- });
- }
-});
diff --git a/chromium/chrome/browser/resources/google_now/background_test_util.js b/chromium/chrome/browser/resources/google_now/background_test_util.js
deleted file mode 100644
index 7f6e4aa0d21..00000000000
--- a/chromium/chrome/browser/resources/google_now/background_test_util.js
+++ /dev/null
@@ -1,32 +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.
-
-// Mocks for globals needed for loading background.js.
-
-var wrapper = {instrumentChromeApiFunction: emptyMock};
-
-function buildAuthenticationManager() {
- return {
- addListener: emptyMock
- };
-}
-
-var instrumentApiFunction = emptyMock;
-var buildTaskManager = emptyMock;
-var buildAttemptManager = emptyMock;
-var buildCardSet = emptyMock;
-
-var instrumented = {};
-mockChromeEvent(instrumented, 'gcm.onMessage');
-mockChromeEvent(instrumented, 'notifications.onButtonClicked');
-mockChromeEvent(instrumented, 'notifications.onClicked');
-mockChromeEvent(instrumented, 'notifications.onClosed');
-mockChromeEvent(instrumented, 'notifications.onPermissionLevelChanged');
-mockChromeEvent(instrumented, 'notifications.onShowSettings');
-mockChromeEvent(instrumented, 'runtime.onInstalled');
-mockChromeEvent(instrumented, 'runtime.onStartup');
-mockChromeEvent(instrumented, 'storage.onChanged');
-
-NOTIFICATION_CARDS_URL = 'https://test/';
-navigator = {language: 'en-US'};
diff --git a/chromium/chrome/browser/resources/google_now/background_unittest.gtestjs b/chromium/chrome/browser/resources/google_now/background_unittest.gtestjs
deleted file mode 100644
index a9578a890bd..00000000000
--- a/chromium/chrome/browser/resources/google_now/background_unittest.gtestjs
+++ /dev/null
@@ -1,1354 +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.
-
-// TODO(robliao,vadimt): Determine the granularity of testing to perform.
-
-/**
- * Test fixture for background.js.
- * @constructor
- * @extends {testing.Test}
- */
-function GoogleNowBackgroundUnitTest () {
- testing.Test.call(this);
-}
-
-GoogleNowBackgroundUnitTest.prototype = {
- __proto__: testing.Test.prototype,
-
- /** @override */
- extraLibraries: [
- 'common_test_util.js',
- 'background_test_util.js',
- 'background.js'
- ]
-};
-
-var TEST_NAME = 'GoogleNowBackgroundUnitTest';
-
-/**
- * Tasks Conflict Test
- */
-TEST_F(TEST_NAME, 'AreTasksConflicting', function() {
- function testTaskPair(newTaskName, scheduledTaskName, expected) {
- assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected,
- '(' + newTaskName + ', ' + scheduledTaskName + ')');
- }
-
- testTaskPair(UPDATE_CARDS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
- testTaskPair(UPDATE_CARDS_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
- testTaskPair(UPDATE_CARDS_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
- testTaskPair(UPDATE_CARDS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
-
- testTaskPair(DISMISS_CARD_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
- testTaskPair(DISMISS_CARD_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
- testTaskPair(DISMISS_CARD_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
- testTaskPair(DISMISS_CARD_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
-
- testTaskPair(RETRY_DISMISS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
- testTaskPair(RETRY_DISMISS_TASK_NAME, DISMISS_CARD_TASK_NAME, true);
- testTaskPair(RETRY_DISMISS_TASK_NAME, RETRY_DISMISS_TASK_NAME, true);
- testTaskPair(RETRY_DISMISS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
-
- testTaskPair(STATE_CHANGED_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
- testTaskPair(STATE_CHANGED_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
- testTaskPair(STATE_CHANGED_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
- testTaskPair(STATE_CHANGED_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
-});
-
-/**
- * Server Request Tests
- */
-TEST_F(TEST_NAME, 'AuthServerRequestSuccess', function() {
- expectServerRequests(this, 200, '{}');
- var callbackCalled = false;
- requestFromServer('GET', 'test/target').then(function(request) {
- callbackCalled = true;
- assertTrue(request.status === 200);
- assertTrue(request.responseText === '{}');
- });
- assertTrue(callbackCalled);
-});
-
-TEST_F(TEST_NAME, 'AuthServerRequestForbidden', function() {
- this.makeAndRegisterMockApis(['authenticationManager.removeToken']);
- this.mockApis.expects(once()).authenticationManager_removeToken(ANYTHING);
-
- expectServerRequests(this, 403, '');
-
- var thenCalled = false;
- var catchCalled = false;
- requestFromServer('GET', 'test/target').then(function(request) {
- thenCalled = true;
- }).catch(function(request) {
- // The promise is rejected on HTTP failures.
- catchCalled = true;
- assertTrue(request.status === 403);
- });
- assertFalse(thenCalled);
- assertTrue(catchCalled);
-});
-
-TEST_F(TEST_NAME, 'AuthServerRequestNoAuth', function() {
- this.makeAndRegisterMockApis(['authenticationManager.removeToken']);
- this.mockApis.expects(once()).authenticationManager_removeToken(ANYTHING);
-
- expectServerRequests(this, 401, '');
-
- var thenCalled = false;
- var catchCalled = false;
- requestFromServer('GET', 'test/target').then(function(request) {
- thenCalled = true;
- }).catch(function(request) {
- // The promise is rejected on HTTP failures.
- catchCalled = true;
- assertTrue(request.status === 401);
- });
- assertFalse(thenCalled);
- assertTrue(catchCalled);
-});
-
-function expectServerRequests(fixture, httpStatus, responseText) {
- fixture.makeAndRegisterMockApis([
- 'authenticationManager.getAuthToken',
- 'buildServerRequest'
- ]);
-
- function XMLHttpRequest() {}
-
- XMLHttpRequest.prototype = {
- addEventListener: function(type, listener, wantsUntrusted) {},
- setRequestHeader: function(header, value) {},
- send: function() {}
- }
-
- fixture.mockApis.expects(once()).authenticationManager_getAuthToken()
- .will(returnValue(Promise.resolve('token')));
-
- var mockXMLHttpRequest = mock(XMLHttpRequest);
- var mockXMLHttpRequestProxy = mockXMLHttpRequest.proxy();
- fixture.mockApis.expects(once())
- .buildServerRequest(ANYTHING, ANYTHING, ANYTHING)
- .will(returnValue(mockXMLHttpRequestProxy));
-
- mockXMLHttpRequest.expects(once())
- .setRequestHeader('Authorization', 'Bearer token');
-
- var loadEndSavedArgs = new SaveMockArguments();
- mockXMLHttpRequest.expects(once())
- .addEventListener(
- loadEndSavedArgs.match(eq('loadend')),
- loadEndSavedArgs.match(ANYTHING),
- loadEndSavedArgs.match(eq(false)));
-
- mockXMLHttpRequestProxy.status = httpStatus;
- mockXMLHttpRequestProxy.response = responseText;
- mockXMLHttpRequestProxy.responseText = responseText;
-
- mockXMLHttpRequest.expects(once()).send()
- .will(invokeCallback(loadEndSavedArgs, 1, mockXMLHttpRequestProxy));
-}
-
-TEST_F(TEST_NAME, 'AuthServerRequestNoToken', function() {
- this.makeAndRegisterMockApis([
- 'authenticationManager.getAuthToken',
- 'buildServerRequest'
- ]);
-
- this.mockApis.expects(once()).authenticationManager_getAuthToken()
- .will(returnValue(Promise.reject()));
- this.mockApis.expects(never()).buildServerRequest()
-
- var thenCalled = false;
- var catchCalled = false;
- requestFromServer('GET', 'test/target').then(function(request) {
- thenCalled = true;
- }).catch(function() {
- catchCalled = true;
- });
- assertFalse(thenCalled);
- assertTrue(catchCalled);
-})
-
-/**
- * requestNotificationGroupsFromServer Tests
- */
-TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerEmpty', function() {
- this.makeAndRegisterMockGlobals([
- 'shouldShowExplanatoryCard',
- 'recordEvent',
- 'requestFromServer'
- ]);
-
- this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
- .will(returnValue(false));
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
-
- var requestFromServerArgs = new SaveMockArguments();
- this.mockGlobals.expects(once()).requestFromServer(
- requestFromServerArgs.match(eq('GET')),
- requestFromServerArgs.match(ANYTHING))
- .will(returnValue(
- Promise.resolve({status: 200, responseText: "{}"})));
-
- var thenCalled = false;
- var catchCalled = false;
- requestNotificationGroupsFromServer([]).then(function() {
- thenCalled = true;
- }).catch(function() {
- catchCalled = true;
- });
- assertTrue(thenCalled);
- assertFalse(catchCalled);
-
- var pathAndQuery = requestFromServerArgs.arguments[1];
- var query = pathAndQuery.split('?')[1];
- assertTrue(query.search('timeZoneOffsetMs') >= 0);
- assertTrue(query.search('uiLocale') >= 0);
- assertFalse(query.search('cardExplanation') >= 0);
-});
-
-TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerWithGroups', function() {
- this.makeAndRegisterMockGlobals([
- 'shouldShowExplanatoryCard',
- 'recordEvent',
- 'requestFromServer'
- ]);
-
- this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
- .will(returnValue(false));
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
-
- var requestFromServerArgs = new SaveMockArguments();
- this.mockGlobals.expects(once()).requestFromServer(
- requestFromServerArgs.match(eq('GET')),
- requestFromServerArgs.match(ANYTHING))
- .will(returnValue(
- Promise.resolve({status: 200, responseText: "{}"})));
-
- var thenCalled = false;
- var catchCalled = false;
- requestNotificationGroupsFromServer(['A', 'B', 'C']).then(function() {
- thenCalled = true;
- }).catch(function() {
- catchCalled = true;
- });
- assertTrue(thenCalled);
- assertFalse(catchCalled);
-
- var pathAndQuery = requestFromServerArgs.arguments[1];
- var query = pathAndQuery.split('?')[1];
- assertTrue(query.search('timeZoneOffsetMs') >= 0);
- assertTrue(query.search('uiLocale') >= 0);
- assertFalse(query.search('cardExplanation') >= 0);
- assertTrue(query.search('requestTypes=A') >= 0);
- assertTrue(query.search('requestTypes=B') >= 0);
- assertTrue(query.search('requestTypes=C') >= 0);
-});
-
-TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerExplanatory', function() {
- this.makeAndRegisterMockGlobals([
- 'shouldShowExplanatoryCard',
- 'recordEvent',
- 'requestFromServer'
- ]);
-
- this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
- .will(returnValue(true));
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
-
- var requestFromServerArgs = new SaveMockArguments();
- this.mockGlobals.expects(once()).requestFromServer(
- requestFromServerArgs.match(eq('GET')),
- requestFromServerArgs.match(ANYTHING))
- .will(returnValue(
- Promise.resolve({status: 200, responseText: "{}"})));
-
- var thenCalled = false;
- var catchCalled = false;
- requestNotificationGroupsFromServer([]).then(function() {
- thenCalled = true;
- }).catch(function() {
- catchCalled = true;
- });
- assertTrue(thenCalled);
- assertFalse(catchCalled);
-
- var pathAndQuery = requestFromServerArgs.arguments[1];
- var query = pathAndQuery.split('?')[1];
- assertTrue(query.search('timeZoneOffsetMs') >= 0);
- assertTrue(query.search('uiLocale') >= 0);
- assertTrue(query.search('cardExplanation=true') >= 0);
-});
-
-TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerFailure', function() {
- this.makeAndRegisterMockGlobals([
- 'shouldShowExplanatoryCard',
- 'recordEvent',
- 'requestFromServer'
- ]);
-
- this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
- .will(returnValue(false));
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
-
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
-
- var requestFromServerArgs = new SaveMockArguments();
- this.mockGlobals.expects(once()).requestFromServer(
- requestFromServerArgs.match(eq('GET')),
- requestFromServerArgs.match(ANYTHING))
- .will(returnValue(
- Promise.reject({status: 401})));
-
- var thenCalled = false;
- var catchCalled = false;
- requestNotificationGroupsFromServer([]).then(function() {
- thenCalled = true;
- }).catch(function() {
- catchCalled = true;
- });
- assertFalse(thenCalled);
- assertTrue(catchCalled);
-});
-
-/**
- * shouldScheduleRetryFromGroupList Tests
- */
-TEST_F(TEST_NAME, 'ShouldScheduleRetryEmptyGroupList', function() {
- assertTrue(shouldScheduleRetryFromGroupList([]));
-});
-
-TEST_F(TEST_NAME, 'ShouldScheduleRetryNorOnlyGroupList', function() {
- assertFalse(shouldScheduleRetryFromGroupList(['NOR']));
-});
-
-TEST_F(TEST_NAME, 'ShouldScheduleRetryNotOnlyGroupList', function() {
- assertTrue(shouldScheduleRetryFromGroupList(['NOT']));
-});
-
-TEST_F(TEST_NAME, 'ShouldScheduleRetryMultipleGroupsList', function() {
- assertTrue(shouldScheduleRetryFromGroupList(['NOR', 'NOT']));
-});
-
-/**
- * requestAndUpdateOptIn Tests
- */
-TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedIn', function() {
- this.makeAndRegisterMockApis([
- 'chrome.storage.local.set',
- 'requestFromServer'
- ]);
-
- this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
- .will(returnValue(Promise.resolve({
- status: 200,
- responseText: '{"value": true}'})));
-
- this.mockApis.expects(once())
- .chrome_storage_local_set(eqJSON({googleNowEnabled: true}));
-
- var thenCalled = false;
- var catchCalled = false;
- requestAndUpdateOptedIn().then(function(optedIn) {
- thenCalled = true;
- assertTrue(optedIn);
- }).catch(function() {
- catchCalled = true;
- });
- assertTrue(thenCalled);
- assertFalse(catchCalled);
-});
-
-TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedOut', function() {
- this.makeAndRegisterMockApis([
- 'chrome.storage.local.set',
- 'requestFromServer'
- ]);
-
- this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
- .will(returnValue(Promise.resolve({
- status: 200,
- responseText: '{"value": false}'})));
-
- this.mockApis.expects(once())
- .chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
-
- var thenCalled = false;
- var catchCalled = false;
- requestAndUpdateOptedIn().then(function(optedIn) {
- thenCalled = true;
- assertFalse(optedIn);
- }).catch(function() {
- catchCalled = true;
- });
- assertTrue(thenCalled);
- assertFalse(catchCalled);
-});
-
-TEST_F(TEST_NAME, 'RequestAndUpdateOptInFailure', function() {
- this.makeAndRegisterMockApis([
- 'chrome.storage.local.set',
- 'requestFromServer'
- ]);
-
- this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
- .will(returnValue(Promise.reject({status: 404})));
-
- this.mockApis.expects(never()).chrome_storage_local_set();
-
- var thenCalled = false;
- var catchCalled = false;
- requestAndUpdateOptedIn().then(function() {
- thenCalled = true;
- }).catch(function() {
- catchCalled = true;
- });
- assertFalse(thenCalled);
- assertTrue(catchCalled);
-});
-
-/**
- * pollOptedInNoImmediateRecheck Tests
- */
-TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedIn', function() {
- this.makeAndRegisterMockApis([
- 'requestAndUpdateOptedIn',
- 'instrumented.metricsPrivate.getVariationParams',
- 'optInPollAttempts.start'
- ]);
-
- this.mockApis.expects(once()).requestAndUpdateOptedIn()
- .will(returnValue(Promise.resolve(true)));
-
- this.mockApis.expects(never())
- .instrumented_metricsPrivate_getVariationParams();
-
- this.mockApis.expects(never()).optInPollAttempts_start();
-
- pollOptedInNoImmediateRecheck();
-});
-
-TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedOut', function() {
- this.makeAndRegisterMockApis([
- 'requestAndUpdateOptedIn',
- 'instrumented.metricsPrivate.getVariationParams',
- 'optInPollAttempts.start'
- ]);
-
- this.mockApis.expects(once()).requestAndUpdateOptedIn()
- .will(returnValue(Promise.resolve(false)));
-
- var getVariationParamsSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once())
- .instrumented_metricsPrivate_getVariationParams(
- getVariationParamsSavedArgs.match(eq('GoogleNow')),
- getVariationParamsSavedArgs.match(ANYTHING))
- .will(invokeCallback(getVariationParamsSavedArgs, 1, {}));
-
- this.mockApis.expects(once())
- .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
-
- pollOptedInNoImmediateRecheck();
-});
-
-TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckFailure', function() {
- this.makeAndRegisterMockApis([
- 'requestAndUpdateOptedIn',
- 'instrumented.metricsPrivate.getVariationParams',
- 'optInPollAttempts.start'
- ]);
-
- this.mockApis.expects(once()).requestAndUpdateOptedIn()
- .will(returnValue(Promise.reject()));
-
- var getVariationParamsSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once())
- .instrumented_metricsPrivate_getVariationParams(
- getVariationParamsSavedArgs.match(eq('GoogleNow')),
- getVariationParamsSavedArgs.match(ANYTHING))
- .will(invokeCallback(getVariationParamsSavedArgs, 1, {}));
-
- this.mockApis.expects(once())
- .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
-
- pollOptedInNoImmediateRecheck();
-});
-
-/**
- * getGroupsToRequest Tests
- */
-TEST_F(TEST_NAME, 'GetGroupsToRequestNone', function() {
- this.makeAndRegisterMockApis([
- 'fillFromChromeLocalStorage',
- 'Date.now'
- ]);
-
- this.mockApis.expects(once())
- .fillFromChromeLocalStorage(eqJSON({notificationGroups: {}}))
- .will(returnValue(Promise.resolve({notificationGroups: {}})));
-
- this.mockApis.expects(once()).Date_now().will(returnValue(20));
-
- getGroupsToRequest().then(function(groupsToRequest) {
- assertTrue(JSON.stringify(groupsToRequest) === '[]');
- });
-});
-
-TEST_F(TEST_NAME, 'GetGroupsToRequestWithGroups', function() {
- this.makeAndRegisterMockApis([
- 'fillFromChromeLocalStorage',
- 'Date.now'
- ]);
-
- this.mockApis.expects(once())
- .fillFromChromeLocalStorage(eqJSON({notificationGroups: {}}))
- .will(returnValue(Promise.resolve({notificationGroups: {
- TIME18: {nextPollTime: 18},
- TIME19: {nextPollTime: 19},
- TIME20: {nextPollTime: 20},
- TIME21: {nextPollTime: 21},
- TIME22: {nextPollTime: 22},
- TIMEUNDEF: {}
- }})));
-
- this.mockApis.expects(once()).Date_now().will(returnValue(20));
-
- getGroupsToRequest().then(function(groupsToRequest) {
- assertTrue(groupsToRequest.length == 3);
- assertTrue(groupsToRequest.indexOf('TIME18') >= 0);
- assertTrue(groupsToRequest.indexOf('TIME19') >= 0);
- assertTrue(groupsToRequest.indexOf('TIME20') >= 0);
- });
-});
-
-/**
- * combineGroup Tests
- */
-TEST_F(TEST_NAME, 'CombineGroup', function() {
- // Tests combineGroup function. Verifies that both notifications with and
- // without show time are handled correctly and that cards are correctly
- // added to existing cards with same ID or start a new combined card.
-
- // Setup and expectations.
- var combinedCards = {
- 'EXISTING CARD': [1]
- };
-
- var receivedNotificationNoShowTime = {
- chromeNotificationId: 'EXISTING CARD',
- trigger: {hideTimeSec: 1}
- };
- var receivedNotificationWithShowTime = {
- chromeNotificationId: 'NEW CARD',
- trigger: {showTimeSec: 2, hideTimeSec: 3}
- }
-
- var storedGroup = {
- cardsTimestamp: 10000,
- cards: [
- receivedNotificationNoShowTime,
- receivedNotificationWithShowTime
- ]
- };
-
- // Invoking the tested function.
- combineGroup(combinedCards, storedGroup);
-
- // Check the output value.
- var expectedCombinedCards = {
- 'EXISTING CARD': [
- 1,
- {
- receivedNotification: receivedNotificationNoShowTime,
- hideTime: 11000
- }
- ],
- 'NEW CARD': [
- {
- receivedNotification: receivedNotificationWithShowTime,
- showTime: 12000,
- hideTime: 13000
- }
- ]
- };
-
- assertEquals(
- JSON.stringify(expectedCombinedCards),
- JSON.stringify(combinedCards));
-});
-
-/**
- * Mocks global functions and APIs that initialize() depends upon.
- * @param {Test} fixture Test fixture.
- */
-function mockInitializeDependencies(fixture) {
- fixture.makeAndRegisterMockGlobals([
- 'pollOptedInNoImmediateRecheck',
- 'recordEvent',
- 'removeAllCards',
- 'setBackgroundEnable',
- 'startPollingCards',
- 'stopPollingCards'
- ]);
- fixture.makeAndRegisterMockApis([
- 'authenticationManager.isSignedIn',
- 'chrome.storage.local.remove',
- 'fillFromChromeLocalStorage',
- 'instrumented.metricsPrivate.getVariationParams',
- 'instrumented.notifications.getAll',
- 'instrumented.notifications.getPermissionLevel',
- 'instrumented.webstorePrivate.getBrowserLogin',
- 'optInPollAttempts.isRunning',
- 'optInPollAttempts.stop',
- 'tasks.add',
- 'updateCardsAttempts.isRunning',
- 'updateCardsAttempts.stop'
- ]);
-}
-
-/**
- * Sets up the test to expect the state machine calls and send
- * the specified state machine state. Currently used to test initialize().
- * Note that this CAN NOT be used if any of the methods below are called
- * outside of this context with the same argument matchers.
- * expects() calls cannot be chained with the same argument matchers.
- * @param {object} fixture Test fixture.
- * @param {string} testIdentityToken getAuthToken callback token.
- * @param {object} testExperimentVariationParams Response of
- * metricsPrivate.getVariationParams.
- * @param {string} testExperimentVariationParams Response of
- * notifications.getPermissionLevel.
- * @param {boolean} testGoogleNowEnabled True if the user is opted in to Google
- * Now.
- */
-function expectStateMachineCalls(
- fixture,
- testIdentityToken,
- testExperimentVariationParams,
- testNotificationPermissionLevel,
- testGoogleNowEnabled) {
- fixture.mockApis.expects(once()).
- authenticationManager_isSignedIn().
- will(returnValue(new Promise(function(resolve) {
- resolve(!!testIdentityToken);
- })));
-
- var getVariationParamsSavedArgs = new SaveMockArguments();
- fixture.mockApis.expects(once()).
- instrumented_metricsPrivate_getVariationParams(
- getVariationParamsSavedArgs.match(ANYTHING),
- getVariationParamsSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- getVariationParamsSavedArgs, 1, testExperimentVariationParams));
-
- var notificationGetPermissionLevelSavedArgs = new SaveMockArguments();
- fixture.mockApis.expects(once()).
- instrumented_notifications_getPermissionLevel(
- notificationGetPermissionLevelSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- notificationGetPermissionLevelSavedArgs,
- 0,
- testNotificationPermissionLevel))
-
- expectChromeLocalStorageGet(
- fixture,
- {googleNowEnabled: false},
- {googleNowEnabled: testGoogleNowEnabled});
-
- var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments();
- fixture.mockApis.expects(once()).
- updateCardsAttempts_isRunning(
- updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)).
- will(
- invokeCallback(
- updateCardsAttemptsIsRunningSavedArgs, 0, undefined));
-
- var optInPollAttemptsIsRunningSavedArgs = new SaveMockArguments();
- fixture.mockApis.expects(once()).
- optInPollAttempts_isRunning(
- optInPollAttemptsIsRunningSavedArgs.match(ANYTHING)).
- will(
- invokeCallback(
- optInPollAttemptsIsRunningSavedArgs, 0, undefined));
-}
-
-/**
- * Sets up the test to expect the initialization calls that
- * initialize() invokes.
- * Note that this CAN NOT be used if any of the methods below are called
- * outside of this context with the same argument matchers.
- * expects() calls cannot be chained with the same argument matchers.
- */
-function expectInitialization(fixture) {
- var tasksAddSavedArgs = new SaveMockArguments();
- fixture.mockApis.expects(once()).
- tasks_add(
- tasksAddSavedArgs.match(ANYTHING),
- tasksAddSavedArgs.match(ANYTHING)).
- will(invokeCallback(tasksAddSavedArgs, 1, function() {}));
-
- // The ordering here between stubs and expects is important.
- // We only care about the EXTENSION_START event. The other events are covered
- // by the NoCards tests below. Reversing the calls will cause all recordEvent
- // calls to be unexpected.
- fixture.mockGlobals.stubs().recordEvent(ANYTHING);
- fixture.mockGlobals.
- expects(once()).recordEvent(GoogleNowEvent.EXTENSION_START);
- fixture.mockApis.expects(once())
- .fillFromChromeLocalStorage(eqJSON({gcmNotificationKey: undefined}))
- .will(returnValue(Promise.resolve({gcmNotificationKey: 'gcmkey'})));
-
-}
-
-TEST_F(TEST_NAME,'Initialize_SignedOut', function() {
- // Tests the case when getAuthToken fails most likely because the user is
- // not signed in. In this case, the function should quietly exit after
- // finding out that getAuthToken fails.
-
- // Setup and expectations.
- var testIdentityToken = undefined;
- var testExperimentVariationParams = {};
- var testNotificationPermissionLevel = 'denied';
- var testGoogleNowEnabled = undefined;
-
- mockInitializeDependencies(this);
-
- expectInitialization(this);
-
- expectStateMachineCalls(
- this,
- testIdentityToken,
- testExperimentVariationParams,
- testNotificationPermissionLevel,
- testGoogleNowEnabled);
-
- this.mockGlobals.expects(once()).setBackgroundEnable(false);
- this.mockGlobals.expects(never()).startPollingCards();
- this.mockGlobals.expects(once()).stopPollingCards();
- this.mockGlobals.expects(once()).removeAllCards();
- this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
- this.mockApis.expects(once()).optInPollAttempts_stop();
-
- // Invoking the tested function.
- initialize();
-});
-
-TEST_F(TEST_NAME,'Initialize_NotificationDisabled', function() {
- // Tests the case when Google Now is disabled in the notifications center.
-
- // Setup and expectations.
- var testIdentityToken = 'some identity token';
- var testExperimentVariationParams = {};
- var testNotificationPermissionLevel = 'denied';
- var testGoogleNowEnabled = undefined;
-
- mockInitializeDependencies(this);
-
- expectInitialization(this);
-
- expectStateMachineCalls(
- this,
- testIdentityToken,
- testExperimentVariationParams,
- testNotificationPermissionLevel,
- testGoogleNowEnabled);
-
- this.mockGlobals.expects(once()).setBackgroundEnable(false);
- this.mockGlobals.expects(never()).startPollingCards();
- this.mockGlobals.expects(once()).stopPollingCards();
- this.mockGlobals.expects(once()).removeAllCards();
- this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
- this.mockApis.expects(once()).optInPollAttempts_stop();
-
- // Invoking the tested function.
- initialize();
-});
-
-TEST_F(TEST_NAME, 'Initialize_NoBackground', function() {
- // Tests when the no background variation is received.
-
- // Setup and expectations.
- var testIdentityToken = 'some identity token';
- var testExperimentVariationParams = {canEnableBackground: 'false'};
- var testNotificationPermissionLevel = 'granted';
- var testGoogleNowEnabled = true;
-
- mockInitializeDependencies(this);
-
- expectInitialization(this);
-
- expectStateMachineCalls(
- this,
- testIdentityToken,
- testExperimentVariationParams,
- testNotificationPermissionLevel,
- testGoogleNowEnabled);
-
- this.mockGlobals.expects(once()).setBackgroundEnable(false);
- this.mockGlobals.expects(once()).startPollingCards();
- this.mockGlobals.expects(never()).stopPollingCards();
- this.mockGlobals.expects(never()).removeAllCards();
- this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
- this.mockApis.expects(once()).optInPollAttempts_stop();
-
- // Invoking the tested function.
- initialize();
-});
-
-TEST_F(TEST_NAME, 'Initialize_GoogleNowDisabled', function() {
- // Tests when the user has Google Now disabled.
-
- // Setup and expectations.
- var testIdentityToken = 'some identity token';
- var testExperimentVariationParams = {};
- var testNotificationPermissionLevel = 'granted';
- var testGoogleNowEnabled = false;
-
- mockInitializeDependencies(this);
-
- expectInitialization(this);
-
- expectStateMachineCalls(
- this,
- testIdentityToken,
- testExperimentVariationParams,
- testNotificationPermissionLevel,
- testGoogleNowEnabled);
-
- this.mockGlobals.expects(once()).setBackgroundEnable(false);
- this.mockGlobals.expects(never()).startPollingCards();
- this.mockGlobals.expects(once()).stopPollingCards();
- this.mockGlobals.expects(once()).removeAllCards();
- this.mockGlobals.expects(once()).pollOptedInNoImmediateRecheck();
- this.mockApis.expects(never()).optInPollAttempts_stop();
-
- // Invoking the tested function.
- initialize();
-});
-
-TEST_F(TEST_NAME, 'Initialize_RunGoogleNow', function() {
- // Tests if Google Now will invoke startPollingCards when all
- // of the required state is fulfilled.
-
- // Setup and expectations.
- var testIdentityToken = 'some identity token';
- var testExperimentVariationParams = {};
- var testNotificationPermissionLevel = 'granted';
- var testGoogleNowEnabled = true;
-
- mockInitializeDependencies(this);
-
- expectInitialization(this);
-
- expectStateMachineCalls(
- this,
- testIdentityToken,
- testExperimentVariationParams,
- testNotificationPermissionLevel,
- testGoogleNowEnabled);
-
- this.mockGlobals.expects(once()).setBackgroundEnable(true);
- this.mockGlobals.expects(once()).startPollingCards();
- this.mockGlobals.expects(never()).stopPollingCards();
- this.mockGlobals.expects(never()).removeAllCards();
- this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
- this.mockApis.expects(once()).optInPollAttempts_stop();
-
- // Invoking the tested function.
- initialize();
-});
-
-/**
- * No Cards Event Recording Tests
- */
-TEST_F(TEST_NAME, 'NoCardsSignedOut', function() {
- var signedIn = false;
- var notificationEnabled = false;
- var googleNowEnabled = false;
- this.makeAndRegisterMockGlobals([
- 'recordEvent',
- 'removeAllCards',
- 'setBackgroundEnable',
- 'setShouldPollCards',
- 'setShouldPollOptInStatus']);
-
- this.mockGlobals.stubs().removeAllCards();
- this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
- this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
- this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.STOPPED);
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.SIGNED_OUT);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.NOTIFICATION_DISABLED);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.GOOGLE_NOW_DISABLED);
- updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
-});
-
-TEST_F(TEST_NAME, 'NoCardsNotificationsDisabled', function() {
- var signedIn = true;
- var notificationEnabled = false;
- var googleNowEnabled = false;
- this.makeAndRegisterMockGlobals([
- 'recordEvent',
- 'removeAllCards',
- 'setBackgroundEnable',
- 'setShouldPollCards',
- 'setShouldPollOptInStatus']);
-
- this.mockGlobals.stubs().removeAllCards();
- this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
- this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
- this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
-
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.STOPPED);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.SIGNED_OUT);
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.NOTIFICATION_DISABLED);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.GOOGLE_NOW_DISABLED);
- updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
-});
-
-TEST_F(TEST_NAME, 'NoCardsGoogleNowDisabled', function() {
- var signedIn = true;
- var notificationEnabled = true;
- var googleNowEnabled = false;
- this.makeAndRegisterMockGlobals([
- 'recordEvent',
- 'removeAllCards',
- 'setBackgroundEnable',
- 'setShouldPollCards',
- 'setShouldPollOptInStatus']);
-
- this.mockGlobals.stubs().removeAllCards();
- this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
- this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
- this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
-
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.STOPPED);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.SIGNED_OUT);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.NOTIFICATION_DISABLED);
- this.mockGlobals.expects(once()).recordEvent(
- GoogleNowEvent.GOOGLE_NOW_DISABLED);
- updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
-});
-
-TEST_F(TEST_NAME, 'NoCardsEverythingEnabled', function() {
- var signedIn = true;
- var notificationEnabled = true;
- var googleNowEnabled = true;
- this.makeAndRegisterMockGlobals([
- 'recordEvent',
- 'removeAllCards',
- 'setBackgroundEnable',
- 'setShouldPollCards',
- 'setShouldPollOptInStatus']);
-
- this.mockGlobals.stubs().removeAllCards();
- this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
- this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
- this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
-
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.STOPPED);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.SIGNED_OUT);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.NOTIFICATION_DISABLED);
- this.mockGlobals.expects(never()).recordEvent(
- GoogleNowEvent.GOOGLE_NOW_DISABLED);
- updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
-});
-
-/**
- * Mocks global functions and APIs that onNotificationClicked() depends upon.
- * @param {Test} fixture Test fixture.
- */
-function mockOnNotificationClickedDependencies(fixture) {
- fixture.makeAndRegisterMockApis([
- 'chrome.windows.create',
- 'chrome.windows.update',
- 'fillFromChromeLocalStorage',
- 'instrumented.tabs.create']);
-}
-
-TEST_F(TEST_NAME, 'OnNotificationClicked_NoData', function() {
- // Tests the case when there is no data associated with notification id.
- // In this case, the function should do nothing.
-
- // Setup and expectations.
- var testNotificationId = 'TEST_ID';
- var testNotificationDataRequest = {notificationsData: {}};
- var testNotificationData = {notificationsData: {}};
-
- mockOnNotificationClickedDependencies(this);
- this.makeMockLocalFunctions(['selector']);
-
- expectChromeLocalStorageGet(
- this, testNotificationDataRequest, testNotificationData);
-
- // Invoking the tested function.
- onNotificationClicked(
- testNotificationId, this.mockLocalFunctions.functions().selector);
-});
-
-TEST_F(TEST_NAME, 'OnNotificationClicked_ActionUrlsUndefined', function() {
- // Tests the case when the data associated with notification id is
- // 'undefined'.
- // In this case, the function should do nothing.
-
- // Setup and expectations.
- var testActionUrls = undefined;
- var testNotificationId = 'TEST_ID';
- var testNotificationDataRequest = {notificationsData: {}};
- var testNotificationData = {
- notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
- };
-
- mockOnNotificationClickedDependencies(this);
- this.makeMockLocalFunctions(['selector']);
-
- expectChromeLocalStorageGet(
- this, testNotificationDataRequest, testNotificationData);
-
- this.mockLocalFunctions.expects(once())
- .selector(eqJSON(
- testNotificationData.notificationsData[testNotificationId]))
- .will(returnValue(undefined));
-
- // Invoking the tested function.
- onNotificationClicked(
- testNotificationId, this.mockLocalFunctions.functions().selector);
-});
-
-TEST_F(TEST_NAME, 'OnNotificationClicked_TabCreateSuccess', function() {
- // Tests the selected URL is OK and crome.tabs.create suceeds.
-
- // Setup and expectations.
- var testActionUrls = {testField: 'TEST VALUE'};
- var testNotificationId = 'TEST_ID';
- var testNotificationDataRequest = {notificationsData: {}};
- var testNotificationData = {
- notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
- };
- var testActionUrl = 'http://testurl.com';
- var testCreatedTab = {windowId: 239};
-
- mockOnNotificationClickedDependencies(this);
- this.makeMockLocalFunctions(['selector']);
-
- expectChromeLocalStorageGet(
- this, testNotificationDataRequest, testNotificationData);
- this.mockLocalFunctions.expects(once())
- .selector(eqJSON(
- testNotificationData.notificationsData[testNotificationId]))
- .will(returnValue(testActionUrl));
- var chromeTabsCreateSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_tabs_create(
- chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
- chromeTabsCreateSavedArgs.match(ANYTHING)).
- will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
- this.mockApis.expects(once()).chrome_windows_update(
- testCreatedTab.windowId,
- eqJSON({focused: true}));
-
- // Invoking the tested function.
- onNotificationClicked(
- testNotificationId, this.mockLocalFunctions.functions().selector);
-});
-
-TEST_F(TEST_NAME, 'OnNotificationClicked_TabCreateFail', function() {
- // Tests the selected URL is OK and crome.tabs.create fails.
- // In this case, the function should invoke chrome.windows.create as a
- // second attempt.
-
- // Setup and expectations.
- var testActionUrls = {testField: 'TEST VALUE'};
- var testNotificationId = 'TEST_ID';
- var testNotificationDataRequest = {notificationsData: {}};
- var testNotificationData = {
- notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
- };
- var testActionUrl = 'http://testurl.com';
- var testCreatedTab = undefined; // chrome.tabs.create fails
-
- mockOnNotificationClickedDependencies(this);
- this.makeMockLocalFunctions(['selector']);
-
- expectChromeLocalStorageGet(
- this, testNotificationDataRequest, testNotificationData);
- this.mockLocalFunctions.expects(once())
- .selector(eqJSON(
- testNotificationData.notificationsData[testNotificationId]))
- .will(returnValue(testActionUrl));
- var chromeTabsCreateSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_tabs_create(
- chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
- chromeTabsCreateSavedArgs.match(ANYTHING)).
- will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
- this.mockApis.expects(once()).chrome_windows_create(
- eqJSON({url: testActionUrl, focused: true}));
-
- // Invoking the tested function.
- onNotificationClicked(
- testNotificationId, this.mockLocalFunctions.functions().selector);
-});
-
-TEST_F(TEST_NAME, 'ShowNotificationGroups', function() {
- // Tests showNotificationGroups function. Checks that the function properly
- // deletes the card that didn't get an update, updates existing card and
- // creates a new card that previously didn't exist.
-
- // Setup and expectations.
- var existingNotifications = {
- 'SHOULD BE DELETED': 'SOMETHING',
- 'SHOULD BE KEPT': 'SOMETHING'
- };
-
- var keptCard = {
- chromeNotificationId: 'SHOULD BE KEPT',
- trigger: {showTimeSec: 0, hideTimeSec: 0}
- };
-
- var keptNotification = {
- receivedNotification: keptCard,
- showTime: 0,
- hideTime: 0
- };
-
- var newCard = {
- chromeNotificationId: 'NEW CARD',
- trigger: {showTimeSec: 0, hideTimeSec: 0}
- };
-
- var newNotification = {
- receivedNotification: newCard,
- showTime: 0,
- hideTime: 0
- };
-
- var notificationGroups = {
- 'TEST GROUP 1': {cards: [keptCard], cardsTimestamp: 0},
- 'TEST GROUP 2': {cards: [newCard], cardsTimestamp: 0}
- };
-
- var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION';
-
- var expectedUpdatedNotifications = {
- 'SHOULD BE KEPT': 'KEPT CARD NOTIFICATION DATA',
- 'NEW CARD': 'NEW CARD NOTIFICATION DATA'
- };
-
- this.makeAndRegisterMockApis([
- 'cardSet.update',
- 'chrome.storage.local.set',
- 'instrumented.notifications.getAll'
- ]);
- this.makeMockLocalFunctions([
- 'onSuccess'
- ]);
-
- var notificationsGetAllSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_notifications_getAll(
- notificationsGetAllSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- notificationsGetAllSavedArgs, 0, existingNotifications));
-
- this.mockApis.expects(once()).
- cardSet_update(
- 'SHOULD BE KEPT',
- eqJSON([keptNotification]),
- eqJSON(notificationGroups),
- fakeOnCardShownFunction).
- will(returnValue('KEPT CARD NOTIFICATION DATA'));
- this.mockApis.expects(once()).
- cardSet_update(
- 'NEW CARD',
- eqJSON([newNotification]),
- eqJSON(notificationGroups),
- fakeOnCardShownFunction).
- will(returnValue('NEW CARD NOTIFICATION DATA'));
- this.mockApis.expects(once()).
- cardSet_update(
- 'SHOULD BE DELETED',
- [],
- eqJSON(notificationGroups),
- fakeOnCardShownFunction).
- will(returnValue(undefined));
-
- this.mockApis.expects(once()).
- chrome_storage_local_set(
- eqJSON({notificationsData: expectedUpdatedNotifications}));
-
- this.mockLocalFunctions.expects(once()).
- onSuccess(undefined);
-
- // Invoking the tested function.
- showNotificationGroups(notificationGroups, fakeOnCardShownFunction)
- .then(this.mockLocalFunctions.functions().onSuccess);
-});
-
-TEST_F(TEST_NAME, 'ProcessServerResponse', function() {
- // Tests processServerResponse function.
-
- // Setup and expectations.
- Date.now = function() { return 3000000; };
-
- // GROUP1 was requested and contains cards c4 and c5. For c5, there is a
- // non-expired dismissal, so it will be ignored.
- // GROUP2 was not requested, but is contained in server response to
- // indicate that the group still exists. Stored group GROUP2 won't change.
- // GROUP3 is stored, but is not present in server's response, which means
- // it doesn't exist anymore. This group will be deleted.
- // GROUP4 doesn't contain cards, but it was requested. This is treated as
- // if it had an empty array of cards. Cards in the stored group will be
- // replaced with an empty array.
- // GROUP5 doesn't have next poll time, and it will be stored without next
- // poll time.
- var serverResponse = {
- groups: {
- GROUP1: {requested: true, nextPollSeconds: 46},
- GROUP2: {requested: false},
- GROUP4: {requested: true, nextPollSeconds: 45},
- GROUP5: {requested: true}
- },
- notifications: [
- {notificationId: 'c4', groupName: 'GROUP1'},
- {notificationId: 'c5', groupName: 'GROUP1'}
- ]
- };
-
- var recentDismissals = {
- c4: 1800000, // expired dismissal
- c5: 1800001 // non-expired dismissal
- };
-
- var storedGroups = {
- GROUP2: {
- cards: [{notificationId: 'c2'}],
- cardsTimestamp: 239,
- nextPollTime: 10000
- },
- GROUP3: {
- cards: [{notificationId: 'c3'}],
- cardsTimestamp: 240,
- nextPollTime: 10001
- },
- GROUP4: {
- cards: [{notificationId: 'c6'}],
- cardsTimestamp: 241,
- nextPollTime: 10002
- }
- };
-
- var expectedUpdatedGroups = {
- GROUP1: {
- cards: [{notificationId: 'c4', groupName: 'GROUP1'}],
- cardsTimestamp: 3000000,
- nextPollTime: 3046000
- },
- GROUP2: {
- cards: [{notificationId: 'c2'}],
- cardsTimestamp: 239,
- nextPollTime: 10000
- },
- GROUP4: {
- cards: [],
- cardsTimestamp: 3000000,
- nextPollTime: 3045000
- },
- GROUP5: {
- cards: [],
- cardsTimestamp: 3000000
- }
- };
-
- var expectedUpdatedRecentDismissals = {
- c5: 1800001
- };
-
- this.makeAndRegisterMockGlobals([
- 'scheduleNextCardsPoll'
- ]);
-
- this.makeAndRegisterMockApis([
- 'fillFromChromeLocalStorage',
- ]);
-
- expectChromeLocalStorageGet(
- this,
- {
- notificationGroups: {},
- recentDismissals: {}
- },
- {
- notificationGroups: storedGroups,
- recentDismissals: recentDismissals
- });
-
- this.mockGlobals.expects(once())
- .scheduleNextCardsPoll(eqJSON(expectedUpdatedGroups));
-
- // Invoking the tested function.
- processServerResponse(serverResponse);
-});
-
-TEST_F(TEST_NAME, 'ProcessServerResponseGoogleNowDisabled', function() {
- // Tests processServerResponse function for the case when the response
- // indicates that Google Now is disabled.
-
- // Setup and expectations.
- var serverResponse = {
- googleNowDisabled: true,
- groups: {}
- };
-
- this.makeAndRegisterMockGlobals([
- 'scheduleNextCardsPoll'
- ]);
-
- this.makeAndRegisterMockApis([
- 'chrome.storage.local.set',
- 'fillFromChromeLocalStorage'
- ]);
-
- this.mockApis.expects(once()).
- chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
-
- this.mockGlobals.expects(never()).scheduleNextCardsPoll();
-
- // Invoking the tested function.
- processServerResponse(serverResponse);
-});
-
diff --git a/chromium/chrome/browser/resources/google_now/cards.js b/chromium/chrome/browser/resources/google_now/cards.js
deleted file mode 100644
index 5c7d64fd11c..00000000000
--- a/chromium/chrome/browser/resources/google_now/cards.js
+++ /dev/null
@@ -1,387 +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.
-
-'use strict';
-
-/**
- * Show/hide trigger in a card.
- *
- * @typedef {{
- * showTimeSec: (string|undefined),
- * hideTimeSec: string
- * }}
- */
-var Trigger;
-
-/**
- * ID of an individual (uncombined) notification.
- * This ID comes directly from the server.
- *
- * @typedef {string}
- */
-var ServerNotificationId;
-
-/**
- * Data to build a dismissal request for a card from a specific group.
- *
- * @typedef {{
- * notificationId: ServerNotificationId,
- * parameters: Object
- * }}
- */
-var DismissalData;
-
-/**
- * Urls that need to be opened when clicking a notification or its buttons.
- *
- * @typedef {{
- * messageUrl: (string|undefined),
- * buttonUrls: (Array<string>|undefined)
- * }}
- */
-var ActionUrls;
-
-/**
- * ID of a combined notification.
- * This is the ID used with chrome.notifications API.
- *
- * @typedef {string}
- */
-var ChromeNotificationId;
-
-/**
- * Notification as sent by the server.
- *
- * @typedef {{
- * notificationId: ServerNotificationId,
- * chromeNotificationId: ChromeNotificationId,
- * trigger: Trigger,
- * chromeNotificationOptions: Object,
- * actionUrls: (ActionUrls|undefined),
- * dismissal: Object,
- * locationBased: (boolean|undefined),
- * groupName: string,
- * cardTypeId: (number|undefined)
- * }}
- */
-var ReceivedNotification;
-
-/**
- * Received notification in a self-sufficient form that doesn't require group's
- * timestamp to calculate show and hide times.
- *
- * @typedef {{
- * receivedNotification: ReceivedNotification,
- * showTime: (number|undefined),
- * hideTime: number
- * }}
- */
-var UncombinedNotification;
-
-/**
- * Card combined from potentially multiple groups.
- *
- * @typedef {Array<UncombinedNotification>}
- */
-var CombinedCard;
-
-/**
- * Data entry that we store for every Chrome notification.
- * |timestamp| is the time when corresponding Chrome notification was created or
- * updated last time by cardSet.update().
- *
- * @typedef {{
- * actionUrls: (ActionUrls|undefined),
- * cardTypeId: (number|undefined),
- * timestamp: number,
- * combinedCard: CombinedCard
- * }}
- *
- */
-var NotificationDataEntry;
-
-/**
- * Names for tasks that can be created by the this file.
- */
-var UPDATE_CARD_TASK_NAME = 'update-card';
-
-/**
- * Builds an object to manage notification card set.
- * @return {Object} Card set interface.
- */
-function buildCardSet() {
- var alarmPrefix = 'card-';
-
- /**
- * Creates/updates/deletes a Chrome notification.
- * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID
- * of the card.
- * @param {(ReceivedNotification|undefined)} receivedNotification Google Now
- * card represented as a set of parameters for showing a Chrome
- * notification, or null if the notification needs to be deleted.
- * @param {function(ReceivedNotification)=} onCardShown Optional parameter
- * called when each card is shown.
- */
- function updateNotification(
- chromeNotificationId, receivedNotification, onCardShown) {
- console.log(
- 'cardManager.updateNotification ' + chromeNotificationId + ' ' +
- JSON.stringify(receivedNotification));
-
- if (!receivedNotification) {
- instrumented.notifications.clear(chromeNotificationId, function() {});
- return;
- }
-
- // Try updating the notification.
- instrumented.notifications.update(
- chromeNotificationId,
- receivedNotification.chromeNotificationOptions,
- function(wasUpdated) {
- if (!wasUpdated) {
- // If the notification wasn't updated, it probably didn't exist.
- // Create it.
- console.log(
- 'cardManager.updateNotification ' + chromeNotificationId +
- ' not updated, creating instead');
- instrumented.notifications.create(
- chromeNotificationId,
- receivedNotification.chromeNotificationOptions,
- function(newChromeNotificationId) {
- if (!newChromeNotificationId || chrome.runtime.lastError) {
- var errorMessage = chrome.runtime.lastError &&
- chrome.runtime.lastError.message;
- console.error('notifications.create: ID=' +
- newChromeNotificationId + ', ERROR=' + errorMessage);
- return;
- }
-
- if (onCardShown !== undefined)
- onCardShown(receivedNotification);
- });
- }
- });
- }
-
- /**
- * Iterates uncombined notifications in a combined card, determining for
- * each whether it's visible at the specified moment.
- * @param {CombinedCard} combinedCard The combined card in question.
- * @param {number} timestamp Time for which to calculate visibility.
- * @param {function(UncombinedNotification, boolean)} callback Function
- * invoked for every uncombined notification in |combinedCard|.
- * The boolean parameter indicates whether the uncombined notification is
- * visible at |timestamp|.
- */
- function iterateUncombinedNotifications(combinedCard, timestamp, callback) {
- for (var i = 0; i != combinedCard.length; ++i) {
- var uncombinedNotification = combinedCard[i];
- var shouldShow = !uncombinedNotification.showTime ||
- uncombinedNotification.showTime <= timestamp;
- var shouldHide = uncombinedNotification.hideTime <= timestamp;
-
- callback(uncombinedNotification, shouldShow && !shouldHide);
- }
- }
-
- /**
- * Refreshes (shows/hides) the notification corresponding to the combined card
- * based on the current time and show-hide intervals in the combined card.
- * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID
- * of the card.
- * @param {CombinedCard} combinedCard Combined cards with
- * |chromeNotificationId|.
- * @param {Object<StoredNotificationGroup>} notificationGroups Map from group
- * name to group information.
- * @param {function(ReceivedNotification)=} onCardShown Optional parameter
- * called when each card is shown.
- * @return {(NotificationDataEntry|undefined)} Notification data entry for
- * this card. It's 'undefined' if the card's life is over.
- */
- function update(
- chromeNotificationId, combinedCard, notificationGroups, onCardShown) {
- console.log('cardManager.update ' + JSON.stringify(combinedCard));
-
- chrome.alarms.clear(alarmPrefix + chromeNotificationId);
- var now = Date.now();
- /** @type {(UncombinedNotification|undefined)} */
- var winningCard = undefined;
- // Next moment of time when winning notification selection algotithm can
- // potentially return a different notification.
- /** @type {?number} */
- var nextEventTime = null;
-
- // Find a winning uncombined notification: a highest-priority notification
- // that needs to be shown now.
- iterateUncombinedNotifications(
- combinedCard,
- now,
- function(uncombinedCard, visible) {
- // If the uncombined notification is visible now and set the winning
- // card to it if its priority is higher.
- if (visible) {
- if (!winningCard ||
- uncombinedCard.receivedNotification.chromeNotificationOptions.
- priority >
- winningCard.receivedNotification.chromeNotificationOptions.
- priority) {
- winningCard = uncombinedCard;
- }
- }
-
- // Next event time is the closest hide or show event.
- if (uncombinedCard.showTime && uncombinedCard.showTime > now) {
- if (!nextEventTime || nextEventTime > uncombinedCard.showTime)
- nextEventTime = uncombinedCard.showTime;
- }
- if (uncombinedCard.hideTime > now) {
- if (!nextEventTime || nextEventTime > uncombinedCard.hideTime)
- nextEventTime = uncombinedCard.hideTime;
- }
- });
-
- // Show/hide the winning card.
- updateNotification(
- chromeNotificationId,
- winningCard && winningCard.receivedNotification,
- onCardShown);
-
- if (nextEventTime) {
- // If we expect more events, create an alarm for the next one.
- chrome.alarms.create(
- alarmPrefix + chromeNotificationId, {when: nextEventTime});
-
- // The trick with stringify/parse is to create a copy of action URLs,
- // otherwise notifications data with 2 pointers to the same object won't
- // be stored correctly to chrome.storage.
- var winningActionUrls = winningCard &&
- winningCard.receivedNotification.actionUrls &&
- JSON.parse(JSON.stringify(
- winningCard.receivedNotification.actionUrls));
- var winningCardTypeId = winningCard &&
- winningCard.receivedNotification.cardTypeId;
- return {
- actionUrls: winningActionUrls,
- cardTypeId: winningCardTypeId,
- timestamp: now,
- combinedCard: combinedCard
- };
- } else {
- // If there are no more events, we are done with this card. Note that all
- // received notifications have hideTime.
- verify(!winningCard, 'No events left, but card is shown.');
- clearCardFromGroups(chromeNotificationId, notificationGroups);
- return undefined;
- }
- }
-
- /**
- * Removes dismissed part of a card and refreshes the card. Returns remaining
- * dismissals for the combined card and updated notification data.
- * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID
- * of the card.
- * @param {NotificationDataEntry} notificationData Stored notification entry
- * for this card.
- * @param {Object<StoredNotificationGroup>} notificationGroups Map from group
- * name to group information.
- * @return {{
- * dismissals: Array<DismissalData>,
- * notificationData: (NotificationDataEntry|undefined)
- * }}
- */
- function onDismissal(
- chromeNotificationId, notificationData, notificationGroups) {
- /** @type {Array<DismissalData>} */
- var dismissals = [];
- /** @type {Array<UncombinedNotification>} */
- var newCombinedCard = [];
-
- // Determine which parts of the combined card need to be dismissed or to be
- // preserved. We dismiss parts that were visible at the moment when the card
- // was last updated.
- iterateUncombinedNotifications(
- notificationData.combinedCard,
- notificationData.timestamp,
- function(uncombinedCard, visible) {
- if (visible) {
- dismissals.push({
- notificationId: uncombinedCard.receivedNotification.notificationId,
- parameters: uncombinedCard.receivedNotification.dismissal
- });
- } else {
- newCombinedCard.push(uncombinedCard);
- }
- });
-
- return {
- dismissals: dismissals,
- notificationData: update(
- chromeNotificationId, newCombinedCard, notificationGroups)
- };
- }
-
- /**
- * Removes card information from |notificationGroups|.
- * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID
- * of the card.
- * @param {Object<StoredNotificationGroup>} notificationGroups Map from group
- * name to group information.
- */
- function clearCardFromGroups(chromeNotificationId, notificationGroups) {
- console.log('cardManager.clearCardFromGroups ' + chromeNotificationId);
- for (var groupName in notificationGroups) {
- var group = notificationGroups[groupName];
- for (var i = 0; i != group.cards.length; ++i) {
- if (group.cards[i].chromeNotificationId == chromeNotificationId) {
- group.cards.splice(i, 1);
- break;
- }
- }
- }
- }
-
- instrumented.alarms.onAlarm.addListener(function(alarm) {
- console.log('cardManager.onAlarm ' + JSON.stringify(alarm));
-
- if (alarm.name.startsWith(alarmPrefix)) {
- // Alarm to show the card.
- tasks.add(UPDATE_CARD_TASK_NAME, function() {
- /** @type {ChromeNotificationId} */
- var chromeNotificationId = alarm.name.substring(alarmPrefix.length);
- fillFromChromeLocalStorage({
- /** @type {Object<ChromeNotificationId, NotificationDataEntry>} */
- notificationsData: {},
- /** @type {Object<StoredNotificationGroup>} */
- notificationGroups: {}
- }).then(function(items) {
- console.log('cardManager.onAlarm.get ' + JSON.stringify(items));
-
- var combinedCard =
- (items.notificationsData[chromeNotificationId] &&
- items.notificationsData[chromeNotificationId].combinedCard) || [];
-
- var cardShownCallback = undefined;
- if (localStorage['explanatoryCardsShown'] <
- EXPLANATORY_CARDS_LINK_THRESHOLD) {
- cardShownCallback = countExplanatoryCard;
- }
-
- items.notificationsData[chromeNotificationId] =
- update(
- chromeNotificationId,
- combinedCard,
- items.notificationGroups,
- cardShownCallback);
-
- chrome.storage.local.set(items);
- });
- });
- }
- });
-
- return {
- update: update,
- onDismissal: onDismissal
- };
-}
diff --git a/chromium/chrome/browser/resources/google_now/cards_unittest.gtestjs b/chromium/chrome/browser/resources/google_now/cards_unittest.gtestjs
deleted file mode 100644
index 7dd5c9943b1..00000000000
--- a/chromium/chrome/browser/resources/google_now/cards_unittest.gtestjs
+++ /dev/null
@@ -1,646 +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.
-
-/**
- * Test fixture for cards.js.
- * @constructor
- * @extends {testing.Test}
- */
-function GoogleNowCardsUnitTest () {
- testing.Test.call(this);
-}
-
-GoogleNowCardsUnitTest.prototype = {
- __proto__: testing.Test.prototype,
-
- /** @override */
- extraLibraries: [
- 'common_test_util.js',
- 'cards.js'
- ]
-};
-
-// Test implementation of a function provided by utility.js.
-function verify(condition, message) {
- assertTrue(condition, message);
-}
-
-var testChromeNotificationId = 'TEST CHROME NOTIFICATION ID';
-var testServerNotificationIdA = 'TEST SERVER NOTIFICATION ID-A';
-var testServerNotificationIdB = 'TEST SERVER NOTIFICATION ID-B';
-var testNotificationA = {
- testNotificationField: 'TEST NOTIFICATION VALUE A',
- priority: 1
-};
-var testNotificationB = {
- testNotificationField: 'TEST NOTIFICATION VALUE B',
- priority: 2
-};
-var groupNameA = 'A';
-var groupNameB = 'B';
-var expectedAlarmId = 'card-TEST CHROME NOTIFICATION ID';
-var testActionUrlsA = {testField: 'TEST VALUE A'};
-var testActionUrlsB = {testField: 'TEST VALUE B'};
-var testDismissalA = {testDismissalField: 'TEST DISMISSAL VALUE A'};
-var testDismissalB = {testDismissalField: 'TEST DISMISSAL VALUE B'};
-var EXPLANATORY_CARDS_LINK_THRESHOLD = 4;
-var localStorage = {explanatoryCardsShown: 0};
-var notificationUpdateSuccessful = true;
-var notificationUpdateFailed = false;
-
-function setUpCardManagerTest(fixture) {
- fixture.makeAndRegisterMockApis([
- 'chrome.alarms.clear',
- 'chrome.alarms.create',
- 'chrome.storage.local.set',
- 'countExplanatoryCard',
- 'fillFromChromeLocalStorage',
- 'instrumented.alarms.onAlarm.addListener',
- 'instrumented.notifications.clear',
- 'instrumented.notifications.create',
- 'instrumented.notifications.update',
- 'tasks.add'
- ]);
-
- chrome.runtime = {}; // No error.
-
- var onAlarmSavedArgs = new SaveMockArguments();
- fixture.mockApis.expects(once()).
- instrumented_alarms_onAlarm_addListener(
- onAlarmSavedArgs.match(ANYTHING));
-
- var cardSet = buildCardSet();
-
- Mock4JS.verifyAllMocks();
-
- Date.now = function() { return 300000; };
-
- var test = {
- cardSet: cardSet,
- alarmCallback: onAlarmSavedArgs.arguments [0]
- };
-
- return test;
-}
-
-TEST_F('GoogleNowCardsUnitTest', 'BuildCardManager', function() {
- // Tests that buildCardSet() call completes with no problems.
- var test = setUpCardManagerTest(this);
-
- assertEquals('object', typeof test.cardSet);
- assertEquals('function', typeof test.alarmCallback);
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'UpdateSimpleHideFuture', function() {
- // Update a simple card with the hide event in future.
-
- var testUncombinedNotification = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- hideTime: 300001
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- var chromeNotificationsUpdateSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_notifications_update(
- chromeNotificationsUpdateSavedArgs.match(
- eq(testChromeNotificationId)),
- chromeNotificationsUpdateSavedArgs.match(eqJSON(testNotificationA)),
- chromeNotificationsUpdateSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- chromeNotificationsUpdateSavedArgs, 2, notificationUpdateSuccessful));
- this.mockApis.expects(once()).
- chrome_alarms_create(expectedAlarmId, eqJSON({when: 300001}));
-
- // Call tested method.
- var notificationData = test.cardSet.update(
- testChromeNotificationId, [testUncombinedNotification], {});
-
- // Check the return value.
- assertEquals(
- JSON.stringify({
- actionUrls: testActionUrlsA,
- timestamp: 300000,
- combinedCard: [testUncombinedNotification]
- }),
- JSON.stringify(notificationData));
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'CreateSimpleHideFuture', function() {
- // Create a simple card with the hide event in future.
-
- var testUncombinedNotification = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- hideTime: 300001
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- this.makeMockLocalFunctions(['onCardShown']);
-
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
-
- // notifications.update will return false, which will trigger
- // notifications.create.
- var chromeNotificationsUpdateSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_notifications_update(
- chromeNotificationsUpdateSavedArgs.match(
- eq(testChromeNotificationId)),
- chromeNotificationsUpdateSavedArgs.match(eqJSON(testNotificationA)),
- chromeNotificationsUpdateSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- chromeNotificationsUpdateSavedArgs, 2, notificationUpdateFailed));
- var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_notifications_create(
- chromeNotificationsCreateSavedArgs.match(
- eq(testChromeNotificationId)),
- chromeNotificationsCreateSavedArgs.match(eqJSON(testNotificationA)),
- chromeNotificationsCreateSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- chromeNotificationsCreateSavedArgs, 2, testChromeNotificationId));
-
- this.mockLocalFunctions.expects(once()).
- onCardShown(eqJSON(testUncombinedNotification.receivedNotification));
-
- this.mockApis.expects(once()).
- chrome_alarms_create(expectedAlarmId, eqJSON({when: 300001}));
-
- // Call tested method.
- var notificationData = test.cardSet.update(
- testChromeNotificationId,
- [testUncombinedNotification],
- {},
- this.mockLocalFunctions.functions().onCardShown);
-
- // Check the return value.
- assertEquals(
- JSON.stringify({
- actionUrls: testActionUrlsA,
- timestamp: 300000,
- combinedCard: [testUncombinedNotification]
- }),
- JSON.stringify(notificationData));
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'CreateSimpleShowFuture', function() {
- // Create a simple card with the show event in future. Should create an alarm
- // to fire at the show time.
-
- var testUncombinedNotification = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- showTime: 300001,
- hideTime: 300002
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
-
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- this.mockApis.expects(once()).
- instrumented_notifications_clear(testChromeNotificationId, ANYTHING);
- this.mockApis.expects(once()).
- chrome_alarms_create(expectedAlarmId, eqJSON({when: 300001}));
-
- // Call tested method.
- var notificationData = test.cardSet.update(
- testChromeNotificationId, [testUncombinedNotification], {});
-
- // Check the return value.
- assertEquals(
- JSON.stringify({
- timestamp: 300000,
- combinedCard: [testUncombinedNotification]
- }),
- JSON.stringify(notificationData));
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'UpdateSimpleHidePast', function() {
- // Update a simple card with the hide event in the past (actually, present).
- // Should clear the notification.
-
- var testUncombinedNotification = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- hideTime: 300000
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- this.mockApis.expects(once()).
- instrumented_notifications_clear(testChromeNotificationId, ANYTHING);
-
- var groups = {
- A: {
- cards: [
- {chromeNotificationId: 'ID1'},
- {chromeNotificationId: testChromeNotificationId}
- ]
- },
- B: {
- cards: [
- {chromeNotificationId: testChromeNotificationId},
- {chromeNotificationId: 'ID2'}
- ]
- }
- };
-
- // Call tested method.
- var notificationData = test.cardSet.update(
- testChromeNotificationId, [testUncombinedNotification], groups);
-
- // Check the return value.
- assertEquals(undefined, notificationData);
-
- // Check that groups were cleaned up.
- var expectedCleanedGroups = {
- A: {
- cards: [{chromeNotificationId: 'ID1'}]
- },
- B: {
- cards: [{chromeNotificationId: 'ID2'}]
- }
- };
-
- assertEquals(JSON.stringify(expectedCleanedGroups), JSON.stringify(groups));
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'UpdateComplex', function() {
- // Update a combined card that contains 2 uncombined cards. The card from
- // group B has higher priority and wins.
-
- var testUncombinedNotificationA = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- hideTime: 300001
- };
-
- var testUncombinedNotificationB = {
- receivedNotification: {
- notificationId: testServerNotificationIdB,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationB,
- actionUrls: testActionUrlsB,
- dismissal: testDismissalB,
- groupName: groupNameB
- },
- hideTime: 300002
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- var chromeNotificationsUpdateSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_notifications_update(
- chromeNotificationsUpdateSavedArgs.match(
- eq(testChromeNotificationId)),
- chromeNotificationsUpdateSavedArgs.match(eqJSON(testNotificationB)),
- chromeNotificationsUpdateSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- chromeNotificationsUpdateSavedArgs, 2, notificationUpdateSuccessful));
- this.mockApis.expects(once()).
- chrome_alarms_create(expectedAlarmId, eqJSON({when: 300001}));
-
- // Call tested method.
- var notificationData = test.cardSet.update(
- testChromeNotificationId,
- [testUncombinedNotificationA, testUncombinedNotificationB],
- {});
-
- // Check the return value.
- assertEquals(
- JSON.stringify({
- actionUrls: testActionUrlsB,
- timestamp: 300000,
- combinedCard: [testUncombinedNotificationA, testUncombinedNotificationB]
- }),
- JSON.stringify(notificationData));
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'DismissSimple', function() {
- // Dismiss a combined card that contains 1 uncombined currently visible card.
- // The notification should be deleted, and the card data should be cleared.
-
- var testUncombinedNotificationA = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- showTime: 299995,
- hideTime: 300005
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- this.mockApis.expects(once()).
- instrumented_notifications_clear(testChromeNotificationId, ANYTHING);
-
- var groups = {
- A: {
- cards: [
- {chromeNotificationId: 'ID1'},
- {chromeNotificationId: testChromeNotificationId}
- ]
- },
- B: {
- cards: [
- {chromeNotificationId: testChromeNotificationId},
- {chromeNotificationId: 'ID2'}
- ]
- }
- };
-
- // Call tested method.
- var dismissalResult = test.cardSet.onDismissal(
- testChromeNotificationId,
- {
- actionUrls: testActionUrlsA,
- timestamp: 299999,
- combinedCard: [testUncombinedNotificationA]
- },
- groups);
-
- // Check the return value.
- assertEquals(
- JSON.stringify({
- dismissals: [{
- notificationId: testServerNotificationIdA,
- parameters: testDismissalA
- }],
- notificationData: undefined
- }),
- JSON.stringify(dismissalResult));
-
- // Check that groups were cleaned up.
- var expectedCleanedGroups = {
- A: {
- cards: [{chromeNotificationId: 'ID1'}]
- },
- B: {
- cards: [{chromeNotificationId: 'ID2'}]
- }
- };
-
- assertEquals(JSON.stringify(expectedCleanedGroups), JSON.stringify(groups));
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'DismissComplex', function() {
- // Dismiss a combined card that contains 2 uncombined cards. One of them (B),
- // is currently shown, and it should be dismissed. The other one (A) has
- // showTime in future, and it should not be dismissed.
-
- var testUncombinedNotificationA = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- showTime: 300010,
- hideTime: 300011
- };
-
- var testUncombinedNotificationB = {
- receivedNotification: {
- notificationId: testServerNotificationIdB,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationB,
- actionUrls: testActionUrlsB,
- dismissal: testDismissalB,
- groupName: groupNameB
- },
- showTime: 299995,
- hideTime: 300005
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- this.mockApis.expects(once()).
- instrumented_notifications_clear(testChromeNotificationId, ANYTHING);
- this.mockApis.expects(once()).
- chrome_alarms_create(expectedAlarmId, eqJSON({when: 300010}));
-
- // Call tested method.
- var dismissalResult = test.cardSet.onDismissal(
- testChromeNotificationId,
- {
- actionUrls: testActionUrlsB,
- timestamp: 299999,
- combinedCard: [testUncombinedNotificationA, testUncombinedNotificationB]
- },
- {});
-
- // Check the return value.
- assertEquals(
- JSON.stringify({
- dismissals: [{
- notificationId: testServerNotificationIdB,
- parameters: testDismissalB
- }],
- notificationData: {
- timestamp: 300000,
- combinedCard: [testUncombinedNotificationA]
- }}),
- JSON.stringify(dismissalResult));
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'onAlarmUnrecognized', function() {
- // Tests onAlarm does nothing on an unrelated alarm.
- var test = setUpCardManagerTest(this);
-
- // Call tested method.
- test.alarmCallback({name: 'unrelated'});
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'onAlarmClear', function() {
- // Tests onAlarm fired at a moment past all card's events. The card should be
- // cleaned.
- var testUncombinedNotification = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- hideTime: 299999
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- var tasksAddSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- tasks_add(
- tasksAddSavedArgs.match(eq(UPDATE_CARD_TASK_NAME)),
- tasksAddSavedArgs.match(ANYTHING)).
- will(invokeCallback(tasksAddSavedArgs,1));
- expectChromeLocalStorageGet(
- this,
- {
- notificationsData: {},
- notificationGroups: {}
- },
- {
- notificationsData: {
- 'TEST CHROME NOTIFICATION ID': {
- actionUrls: testActionUrlsA,
- timestamp: 299998,
- combinedCard: [testUncombinedNotification]
- },
- 'TEST CARD ID 1': {testField: 'TEST VALUE 1'}
- },
- notificationGroups: {
- A: {
- cards: [
- {chromeNotificationId: 'ID1'},
- {chromeNotificationId: testChromeNotificationId}
- ]
- },
- B: {
- cards: [
- {chromeNotificationId: testChromeNotificationId},
- {chromeNotificationId: 'ID2'}
- ]
- }}});
- this.mockApis.expects(once()).
- instrumented_notifications_clear(testChromeNotificationId, ANYTHING);
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- this.mockApis.expects(once()).
- chrome_storage_local_set(eqJSON({
- notificationsData: {
- 'TEST CARD ID 1': {testField: 'TEST VALUE 1'}
- },
- notificationGroups: {
- A: {
- cards: [{chromeNotificationId: 'ID1'}]
- },
- B: {
- cards: [{chromeNotificationId: 'ID2'}]
- }}}));
-
- // Call tested method.
- test.alarmCallback({name: expectedAlarmId});
-});
-
-TEST_F('GoogleNowCardsUnitTest', 'onAlarmUpdate', function() {
- // Tests onAlarm fired at a moment when there are future card's events. The
- // card needs to be updated.
- var testUncombinedNotification = {
- receivedNotification: {
- notificationId: testServerNotificationIdA,
- chromeNotificationId: testChromeNotificationId,
- chromeNotificationOptions: testNotificationA,
- actionUrls: testActionUrlsA,
- dismissal: testDismissalA,
- groupName: groupNameA
- },
- hideTime: 300001
- };
-
- // Setup and expectations.
- var test = setUpCardManagerTest(this);
- var tasksAddSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- tasks_add(
- tasksAddSavedArgs.match(eq(UPDATE_CARD_TASK_NAME)),
- tasksAddSavedArgs.match(ANYTHING)).
- will(invokeCallback(tasksAddSavedArgs,1));
- expectChromeLocalStorageGet(
- this,
- {
- notificationsData: {},
- notificationGroups: {}
- },
- {
- notificationsData: {
- 'TEST CHROME NOTIFICATION ID': {
- actionUrls: testActionUrlsA,
- timestamp: 299998,
- combinedCard: [testUncombinedNotification]
- }},
- notificationGroups: {}
- });
- this.mockApis.expects(once()).
- chrome_alarms_clear(expectedAlarmId);
- var chromeNotificationsUpdateSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_notifications_update(
- chromeNotificationsUpdateSavedArgs.match(
- eq(testChromeNotificationId)),
- chromeNotificationsUpdateSavedArgs.match(eqJSON(testNotificationA)),
- chromeNotificationsUpdateSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- chromeNotificationsUpdateSavedArgs, 2, notificationUpdateSuccessful));
- this.mockApis.expects(once()).
- chrome_alarms_create(expectedAlarmId, eqJSON({when: 300001}));
- this.mockApis.expects(once()).
- chrome_storage_local_set(eqJSON({
- notificationsData: {
- 'TEST CHROME NOTIFICATION ID': {
- actionUrls: testActionUrlsA,
- timestamp: 300000,
- combinedCard: [testUncombinedNotification]
- }
- },
- notificationGroups: {
- }}));
-
- // Call tested method.
- test.alarmCallback({name: expectedAlarmId});
-});
diff --git a/chromium/chrome/browser/resources/google_now/common_test_util.js b/chromium/chrome/browser/resources/google_now/common_test_util.js
deleted file mode 100644
index fe5708234b6..00000000000
--- a/chromium/chrome/browser/resources/google_now/common_test_util.js
+++ /dev/null
@@ -1,205 +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.
-
-// Common test utilities.
-
-/**
- * Allows console.log output.
- */
-var showConsoleLogOutput = false;
-
-/**
- * Conditionally allow console.log output based off of showConsoleLogOutput.
- */
-console.log = function() {
- var originalConsoleLog = console.log;
- return function() {
- if (showConsoleLogOutput) {
- originalConsoleLog.apply(console, arguments);
- }
- };
-}();
-
-function emptyMock() {}
-
-// Container for event handlers added by mocked 'addListener' functions.
-var mockEventHandlers = {};
-
-/**
- * Mocks 'addListener' function of an API event. The mocked function will keep
- * track of handlers.
- * @param {Object} topLevelContainer Top-level container of the original
- * function. Can be either 'chrome' or 'instrumented'.
- * @param {string} eventIdentifier Event identifier, such as
- * 'runtime.onSuspend'.
- */
-function mockChromeEvent(topLevelContainer, eventIdentifier) {
- var eventIdentifierParts = eventIdentifier.split('.');
- var eventName = eventIdentifierParts.pop();
- var originalMethodContainer = topLevelContainer;
- var mockEventContainer = mockEventHandlers;
- eventIdentifierParts.forEach(function(fragment) {
- originalMethodContainer =
- originalMethodContainer[fragment] =
- originalMethodContainer[fragment] || {};
- mockEventContainer =
- mockEventContainer[fragment] =
- mockEventContainer[fragment] || {};
- });
-
- mockEventContainer[eventName] = [];
- originalMethodContainer[eventName] = {
- addListener: function(callback) {
- mockEventContainer[eventName].push(callback);
- }
- };
-}
-
-/**
- * Gets the array of event handlers added by a mocked 'addListener' function.
- * @param {string} eventIdentifier Event identifier, such as
- * 'runtime.onSuspend'.
- * @return {Array<Function>} Array of handlers.
- */
-function getMockHandlerContainer(eventIdentifier) {
- var eventIdentifierParts = eventIdentifier.split('.');
- var mockEventContainer = mockEventHandlers;
- eventIdentifierParts.forEach(function(fragment) {
- mockEventContainer = mockEventContainer[fragment];
- });
-
- return mockEventContainer;
-}
-
-/**
- * MockPromise
- * The JS test harness expects all calls to complete synchronously.
- * As a result, we can't use built-in JS promises since they run asynchronously.
- * Instead of mocking all possible calls to promises, a skeleton
- * implementation is provided to get the tests to pass.
- *
- * This functionality and logic originates from ECMAScript 6's spec of promises.
- */
-var Promise = function() {
- function PromisePrototypeObject(asyncTask) {
- function isThenable(value) {
- return (typeof value === 'object') && isCallable(value.then);
- }
-
- function isCallable(value) {
- return typeof value === 'function';
- }
-
- function callResolveRejectFunc(func) {
- var funcResult;
- var funcResolved = false;
- func(
- function(resolveResult) {
- funcResult = resolveResult;
- funcResolved = true;
- },
- function(rejectResult) {
- funcResult = rejectResult;
- funcResolved = false;
- });
- return { result: funcResult, resolved: funcResolved };
- }
-
- function then(onResolve, onReject) {
- var resolutionHandler =
- isCallable(onResolve) ? onResolve : function() { return result; };
- var rejectionHandler =
- isCallable(onReject) ? onReject : function() { return result; };
- var handlerResult =
- resolved ? resolutionHandler(result) : rejectionHandler(result);
- var promiseResolved = resolved;
- if (isThenable(handlerResult)) {
- var resolveReject = callResolveRejectFunc(handlerResult.then);
- handlerResult = resolveReject.result;
- promiseResolved = resolveReject.resolved;
- }
-
- if (promiseResolved) {
- return Promise.resolve(handlerResult);
- } else {
- return Promise.reject(handlerResult);
- }
- }
-
- // Promises use the function name "catch" to call back error handlers.
- // We can't use "catch" since function or variable names cannot use the word
- // "catch".
- function catchFunc(onRejected) {
- return this.then(undefined, onRejected);
- }
-
- var resolveReject = callResolveRejectFunc(asyncTask);
- var result = resolveReject.result;
- var resolved = resolveReject.resolved;
-
- if (isThenable(result)) {
- var thenResolveReject = callResolveRejectFunc(result.then);
- result = thenResolveReject.result;
- resolved = thenResolveReject.resolved;
- }
-
- return {then: then, catch: catchFunc, isPromise: true};
- }
-
- function all(arrayOfPromises) {
- var results = [];
- for (i = 0; i < arrayOfPromises.length; i++) {
- if (arrayOfPromises[i].isPromise) {
- arrayOfPromises[i].then(function(result) {
- results[i] = result;
- });
- } else {
- results[i] = arrayOfPromises[i];
- }
- }
- var promise = new PromisePrototypeObject(function(resolve) {
- resolve(results);
- });
- return promise;
- }
-
- function resolve(value) {
- var promise = new PromisePrototypeObject(function(resolve) {
- resolve(value);
- });
- return promise;
- }
-
- function reject(value) {
- var promise = new PromisePrototypeObject(function(resolve, reject) {
- reject(value);
- });
- return promise;
- }
-
- PromisePrototypeObject.all = all;
- PromisePrototypeObject.resolve = resolve;
- PromisePrototypeObject.reject = reject;
- return PromisePrototypeObject;
-}();
-
-/**
- * Sets up the test to expect a Chrome Local Storage call.
- * @param {Object} fixture Mock JS Test Object.
- * @param {Object} defaultObject Storage request default object.
- * @param {Object} result Storage result.
- * @param {boolean=} opt_AllowRejection Allow Promise Rejection
- */
-function expectChromeLocalStorageGet(
- fixture, defaultObject, result, opt_AllowRejection) {
- if (opt_AllowRejection === undefined) {
- fixture.mockApis.expects(once()).
- fillFromChromeLocalStorage(eqJSON(defaultObject)).
- will(returnValue(Promise.resolve(result)));
- } else {
- fixture.mockApis.expects(once()).
- fillFromChromeLocalStorage(eqJSON(defaultObject), opt_AllowRejection).
- will(returnValue(Promise.resolve(result)));
- }
-}
diff --git a/chromium/chrome/browser/resources/google_now/images/icon128.png b/chromium/chrome/browser/resources/google_now/images/icon128.png
deleted file mode 100644
index 568cc9f3a09..00000000000
--- a/chromium/chrome/browser/resources/google_now/images/icon128.png
+++ /dev/null
Binary files differ
diff --git a/chromium/chrome/browser/resources/google_now/images/icon16.png b/chromium/chrome/browser/resources/google_now/images/icon16.png
deleted file mode 100644
index 96c52ad712e..00000000000
--- a/chromium/chrome/browser/resources/google_now/images/icon16.png
+++ /dev/null
Binary files differ
diff --git a/chromium/chrome/browser/resources/google_now/images/icon48.png b/chromium/chrome/browser/resources/google_now/images/icon48.png
deleted file mode 100644
index 3d9a8529aae..00000000000
--- a/chromium/chrome/browser/resources/google_now/images/icon48.png
+++ /dev/null
Binary files differ
diff --git a/chromium/chrome/browser/resources/google_now/manifest.json b/chromium/chrome/browser/resources/google_now/manifest.json
deleted file mode 100644
index bdca32298b8..00000000000
--- a/chromium/chrome/browser/resources/google_now/manifest.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- //chrome-extension://pafkbggdmjlpgkdkcbjmhmfcdpncadgh
- "name": "Google Now",
- "version": "1.2.0.1",
- "description": "Integrates Google Now into Chrome.",
- "icons": {
- "16": "images/icon16.png",
- "48": "images/icon48.png",
- "128": "images/icon128.png"
- },
- "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkhqJr32OFD/bMXW4Md7jMfd7LbwHXVc6x5bBQG5U+dloofoxrICDR20yur/40mQ8O//0sS1b8srvbab1CRlSrxoNCr9T80NAkfzx0gHyVS+p1Zow+1FzLMu9PiGwwFyN80HIB7GI/dIa0wC9K/2OrrzcHEhVH96DacTtWQqjfDVtZPjT7Xwv23dgoWcpbkRC86jMJot3dmX9xnn0KzoVc9gDOHSIkBLbkkr6Sp3LGXCCM4L0DJgxdFwaLr5WBzgC3y5x0/wwPIwN4PtIaK3BhH6njlksfnKwwIJ9iRT41V4BqbWu4mszO/7VJ3HJyw2DBpIc2grU9ZRRxrV3fRQG4wIDAQAB",
- "permissions": [
- "alarms",
- "gcm",
- "identity",
- "metricsPrivate",
- "notifications",
- "storage",
- "tabs",
- "webstorePrivate",
- "*://*.google.com/*",
- "*://*.gstatic.com/*",
- "https://*.googleapis.com/chromenow/v1/*",
- "https://*.googleapis.com/gcm/*",
- "https://*.googleusercontent.com/*"
- ],
- "optional_permissions": ["background"],
- "manifest_version": 2,
- "background": {
- "scripts": ["utility.js", "cards.js", "background.js"],
- "persistent": false
- },
- "oauth2": {
- "auto_approve": true,
- "scopes": [
- "https://www.googleapis.com/auth/gcm",
- "https://www.googleapis.com/auth/googlenow"
- ]
- }
-}
diff --git a/chromium/chrome/browser/resources/google_now/utility.js b/chromium/chrome/browser/resources/google_now/utility.js
deleted file mode 100644
index ee34219868a..00000000000
--- a/chromium/chrome/browser/resources/google_now/utility.js
+++ /dev/null
@@ -1,1072 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-/**
- * @fileoverview Utility objects and functions for Google Now extension.
- * Most important entities here:
- * (1) 'wrapper' is a module used to add error handling and other services to
- * callbacks for HTML and Chrome functions and Chrome event listeners.
- * Chrome invokes extension code through event listeners. Once entered via
- * an event listener, the extension may call a Chrome/HTML API method
- * passing a callback (and so forth), and that callback must occur later,
- * otherwise, we generate an error. Chrome may unload event pages waiting
- * for an event. When the event fires, Chrome will reload the event page. We
- * don't require event listeners to fire because they are generally not
- * predictable (like a button clicked event).
- * (2) Task Manager (built with buildTaskManager() call) provides controlling
- * mutually excluding chains of callbacks called tasks. Task Manager uses
- * WrapperPlugins to add instrumentation code to 'wrapper' to determine
- * when a task completes.
- */
-
-// TODO(vadimt): Use server name in the manifest.
-
-/**
- * Notification server URL.
- */
-var NOTIFICATION_CARDS_URL = 'https://www.googleapis.com/chromenow/v1';
-
-/**
- * Returns true if debug mode is enabled.
- * localStorage returns items as strings, which means if we store a boolean,
- * it returns a string. Use this function to compare against true.
- * @return {boolean} Whether debug mode is enabled.
- */
-function isInDebugMode() {
- return localStorage.debug_mode === 'true';
-}
-
-/**
- * Initializes for debug or release modes of operation.
- */
-function initializeDebug() {
- if (isInDebugMode()) {
- NOTIFICATION_CARDS_URL =
- localStorage['server_url'] || NOTIFICATION_CARDS_URL;
- }
-}
-
-initializeDebug();
-
-/**
- * Conditionally allow console.log output based off of the debug mode.
- */
-console.log = function() {
- var originalConsoleLog = console.log;
- return function() {
- if (isInDebugMode()) {
- originalConsoleLog.apply(console, arguments);
- }
- };
-}();
-
-/**
- * Explanation Card Storage.
- */
-if (localStorage['explanatoryCardsShown'] === undefined)
- localStorage['explanatoryCardsShown'] = 0;
-
-/**
- * Location Card Count Cleanup.
- */
-if (localStorage.locationCardsShown !== undefined)
- localStorage.removeItem('locationCardsShown');
-
-/**
- * Builds an error object with a message that may be sent to the server.
- * @param {string} message Error message. This message may be sent to the
- * server.
- * @return {Error} Error object.
- */
-function buildErrorWithMessageForServer(message) {
- var error = new Error(message);
- error.canSendMessageToServer = true;
- return error;
-}
-
-/**
- * Checks for internal errors.
- * @param {boolean} condition Condition that must be true.
- * @param {string} message Diagnostic message for the case when the condition is
- * false.
- */
-function verify(condition, message) {
- if (!condition)
- throw buildErrorWithMessageForServer('ASSERT: ' + message);
-}
-
-/**
- * Builds a request to the notification server.
- * @param {string} method Request method.
- * @param {string} handlerName Server handler to send the request to.
- * @param {string=} opt_contentType Value for the Content-type header.
- * @return {XMLHttpRequest} Server request.
- */
-function buildServerRequest(method, handlerName, opt_contentType) {
- var request = new XMLHttpRequest();
-
- request.responseType = 'text';
- request.open(method, NOTIFICATION_CARDS_URL + '/' + handlerName, true);
- if (opt_contentType)
- request.setRequestHeader('Content-type', opt_contentType);
-
- return request;
-}
-
-/**
- * Sends an error report to the server.
- * @param {Error} error Error to send.
- */
-function sendErrorReport(error) {
- // Don't remove 'error.stack.replace' below!
- var filteredStack = error.canSendMessageToServer ?
- error.stack : error.stack.replace(/.*\n/, '(message removed)\n');
- var file;
- var line;
- var topFrameLineMatch = filteredStack.match(/\n at .*\n/);
- var topFrame = topFrameLineMatch && topFrameLineMatch[0];
- if (topFrame) {
- // Examples of a frame:
- // 1. '\n at someFunction (chrome-extension://
- // pafkbggdmjlpgkdkcbjmhmfcdpncadgh/background.js:915:15)\n'
- // 2. '\n at chrome-extension://pafkbggdmjlpgkdkcbjmhmfcdpncadgh/
- // utility.js:269:18\n'
- // 3. '\n at Function.target.(anonymous function) (extensions::
- // SafeBuiltins:19:14)\n'
- // 4. '\n at Event.dispatchToListener (event_bindings:382:22)\n'
- var errorLocation;
- // Find the the parentheses at the end of the line, if any.
- var parenthesesMatch = topFrame.match(/\(.*\)\n/);
- if (parenthesesMatch && parenthesesMatch[0]) {
- errorLocation =
- parenthesesMatch[0].substring(1, parenthesesMatch[0].length - 2);
- } else {
- errorLocation = topFrame;
- }
-
- var topFrameElements = errorLocation.split(':');
- // topFrameElements is an array that ends like:
- // [N-3] //pafkbggdmjlpgkdkcbjmhmfcdpncadgh/utility.js
- // [N-2] 308
- // [N-1] 19
- if (topFrameElements.length >= 3) {
- file = topFrameElements[topFrameElements.length - 3];
- line = topFrameElements[topFrameElements.length - 2];
- }
- }
-
- var errorText = error.name;
- if (error.canSendMessageToServer)
- errorText = errorText + ': ' + error.message;
-
- var errorObject = {
- message: errorText,
- file: file,
- line: line,
- trace: filteredStack
- };
-
- // We use relatively direct calls here because the instrumentation may be in
- // a bad state. Wrappers and promises should not be involved in the reporting.
- var request = buildServerRequest('POST', 'jserrors', 'application/json');
- request.onloadend = function(event) {
- console.log('sendErrorReport status: ' + request.status);
- };
-
- chrome.identity.getAuthToken({interactive: false}, function(token) {
- if (token) {
- request.setRequestHeader('Authorization', 'Bearer ' + token);
- request.send(JSON.stringify(errorObject));
- }
- });
-}
-
-// Limiting 1 error report per background page load.
-var errorReported = false;
-
-/**
- * Reports an error to the server and the user, as appropriate.
- * @param {Error} error Error to report.
- */
-function reportError(error) {
- var message = 'Critical error:\n' + error.stack;
- if (isInDebugMode())
- console.error(message);
-
- if (!errorReported) {
- errorReported = true;
- chrome.metricsPrivate.getIsCrashReportingEnabled(function(isEnabled) {
- if (isEnabled)
- sendErrorReport(error);
- if (isInDebugMode())
- alert(message);
- });
- }
-}
-
-// Partial mirror of chrome.* for all instrumented functions.
-var instrumented = {};
-
-/**
- * Wrapper plugin. These plugins extend instrumentation added by
- * wrapper.wrapCallback by adding code that executes before and after the call
- * to the original callback provided by the extension.
- *
- * @typedef {{
- * prologue: function (),
- * epilogue: function ()
- * }}
- */
-var WrapperPlugin;
-
-/**
- * Wrapper for callbacks. Used to add error handling and other services to
- * callbacks for HTML and Chrome functions and events.
- */
-var wrapper = (function() {
- /**
- * Factory for wrapper plugins. If specified, it's used to generate an
- * instance of WrapperPlugin each time we wrap a callback (which corresponds
- * to addListener call for Chrome events, and to every API call that specifies
- * a callback). WrapperPlugin's lifetime ends when the callback for which it
- * was generated, exits. It's possible to have several instances of
- * WrapperPlugin at the same time.
- * An instance of WrapperPlugin can have state that can be shared by its
- * constructor, prologue() and epilogue(). Also WrapperPlugins can change
- * state of other objects, for example, to do refcounting.
- * @type {?function(): WrapperPlugin}
- */
- var wrapperPluginFactory = null;
-
- /**
- * Registers a wrapper plugin factory.
- * @param {function(): WrapperPlugin} factory Wrapper plugin factory.
- */
- function registerWrapperPluginFactory(factory) {
- if (wrapperPluginFactory) {
- reportError(buildErrorWithMessageForServer(
- 'registerWrapperPluginFactory: factory is already registered.'));
- }
-
- wrapperPluginFactory = factory;
- }
-
- /**
- * True if currently executed code runs in a callback or event handler that
- * was instrumented by wrapper.wrapCallback() call.
- * @type {boolean}
- */
- var isInWrappedCallback = false;
-
- /**
- * Required callbacks that are not yet called. Includes both task and non-task
- * callbacks. This is a map from unique callback id to the stack at the moment
- * when the callback was wrapped. This stack identifies the callback.
- * Used only for diagnostics.
- * @type {Object<number, string>}
- */
- var pendingCallbacks = {};
-
- /**
- * Unique ID of the next callback.
- * @type {number}
- */
- var nextCallbackId = 0;
-
- /**
- * Gets diagnostic string with the status of the wrapper.
- * @return {string} Diagnostic string.
- */
- function debugGetStateString() {
- return 'pendingCallbacks @' + Date.now() + ' = ' +
- JSON.stringify(pendingCallbacks);
- }
-
- /**
- * Checks that we run in a wrapped callback.
- */
- function checkInWrappedCallback() {
- if (!isInWrappedCallback) {
- reportError(buildErrorWithMessageForServer(
- 'Not in instrumented callback'));
- }
- }
-
- /**
- * Adds error processing to an API callback.
- * @param {Function} callback Callback to instrument.
- * @param {boolean=} opt_isEventListener True if the callback is a listener to
- * a Chrome API event.
- * @return {Function} Instrumented callback.
- */
- function wrapCallback(callback, opt_isEventListener) {
- var callbackId = nextCallbackId++;
-
- if (!opt_isEventListener) {
- checkInWrappedCallback();
- pendingCallbacks[callbackId] = new Error().stack + ' @' + Date.now();
- }
-
- // wrapperPluginFactory may be null before task manager is built, and in
- // tests.
- var wrapperPluginInstance = wrapperPluginFactory && wrapperPluginFactory();
-
- return function() {
- // This is the wrapper for the callback.
- try {
- verify(!isInWrappedCallback, 'Re-entering instrumented callback');
- isInWrappedCallback = true;
-
- if (!opt_isEventListener)
- delete pendingCallbacks[callbackId];
-
- if (wrapperPluginInstance)
- wrapperPluginInstance.prologue();
-
- // Call the original callback.
- var returnValue = callback.apply(null, arguments);
-
- if (wrapperPluginInstance)
- wrapperPluginInstance.epilogue();
-
- verify(isInWrappedCallback,
- 'Instrumented callback is not instrumented upon exit');
- isInWrappedCallback = false;
-
- return returnValue;
- } catch (error) {
- reportError(error);
- }
- };
- }
-
- /**
- * Returns an instrumented function.
- * @param {!Array<string>} functionIdentifierParts Path to the chrome.*
- * function.
- * @param {string} functionName Name of the chrome API function.
- * @param {number} callbackParameter Index of the callback parameter to this
- * API function.
- * @return {Function} An instrumented function.
- */
- function createInstrumentedFunction(
- functionIdentifierParts,
- functionName,
- callbackParameter) {
- return function() {
- // This is the wrapper for the API function. Pass the wrapped callback to
- // the original function.
- var callback = arguments[callbackParameter];
- if (typeof callback != 'function') {
- reportError(buildErrorWithMessageForServer(
- 'Argument ' + callbackParameter + ' of ' +
- functionIdentifierParts.join('.') + '.' + functionName +
- ' is not a function'));
- }
- arguments[callbackParameter] = wrapCallback(
- callback, functionName == 'addListener');
-
- var chromeContainer = chrome;
- functionIdentifierParts.forEach(function(fragment) {
- chromeContainer = chromeContainer[fragment];
- });
- return chromeContainer[functionName].
- apply(chromeContainer, arguments);
- };
- }
-
- /**
- * Instruments an API function to add error processing to its user
- * code-provided callback.
- * @param {string} functionIdentifier Full identifier of the function without
- * the 'chrome.' portion.
- * @param {number} callbackParameter Index of the callback parameter to this
- * API function.
- */
- function instrumentChromeApiFunction(functionIdentifier, callbackParameter) {
- var functionIdentifierParts = functionIdentifier.split('.');
- var functionName = functionIdentifierParts.pop();
- var chromeContainer = chrome;
- var instrumentedContainer = instrumented;
- functionIdentifierParts.forEach(function(fragment) {
- chromeContainer = chromeContainer[fragment];
- if (!chromeContainer) {
- reportError(buildErrorWithMessageForServer(
- 'Cannot instrument ' + functionIdentifier));
- }
-
- if (!(fragment in instrumentedContainer))
- instrumentedContainer[fragment] = {};
-
- instrumentedContainer = instrumentedContainer[fragment];
- });
-
- var targetFunction = chromeContainer[functionName];
- if (!targetFunction) {
- reportError(buildErrorWithMessageForServer(
- 'Cannot instrument ' + functionIdentifier));
- }
-
- instrumentedContainer[functionName] = createInstrumentedFunction(
- functionIdentifierParts,
- functionName,
- callbackParameter);
- }
-
- instrumentChromeApiFunction('runtime.onSuspend.addListener', 0);
-
- instrumented.runtime.onSuspend.addListener(function() {
- var stringifiedPendingCallbacks = JSON.stringify(pendingCallbacks);
- verify(
- stringifiedPendingCallbacks == '{}',
- 'Pending callbacks when unloading event page @' + Date.now() + ':' +
- stringifiedPendingCallbacks);
- });
-
- return {
- wrapCallback: wrapCallback,
- instrumentChromeApiFunction: instrumentChromeApiFunction,
- registerWrapperPluginFactory: registerWrapperPluginFactory,
- checkInWrappedCallback: checkInWrappedCallback,
- debugGetStateString: debugGetStateString
- };
-})();
-
-wrapper.instrumentChromeApiFunction('alarms.get', 1);
-wrapper.instrumentChromeApiFunction('alarms.onAlarm.addListener', 0);
-wrapper.instrumentChromeApiFunction('identity.getAuthToken', 1);
-wrapper.instrumentChromeApiFunction('identity.onSignInChanged.addListener', 0);
-wrapper.instrumentChromeApiFunction('identity.removeCachedAuthToken', 1);
-wrapper.instrumentChromeApiFunction('storage.local.get', 1);
-wrapper.instrumentChromeApiFunction('webstorePrivate.getBrowserLogin', 0);
-
-/**
- * Promise adapter for all JS promises to the task manager.
- */
-function registerPromiseAdapter() {
- var originalThen = Promise.prototype.then;
- var originalCatch = Promise.prototype.catch;
-
- /**
- * Takes a promise and adds the callback tracker to it.
- * @param {object} promise Promise that receives the callback tracker.
- */
- function instrumentPromise(promise) {
- if (promise.__tracker === undefined) {
- promise.__tracker = createPromiseCallbackTracker(promise);
- }
- }
-
- Promise.prototype.then = function(onResolved, onRejected) {
- instrumentPromise(this);
- return this.__tracker.handleThen(onResolved, onRejected);
- };
-
- Promise.prototype.catch = function(onRejected) {
- instrumentPromise(this);
- return this.__tracker.handleCatch(onRejected);
- };
-
- /**
- * Promise Callback Tracker.
- * Handles coordination of 'then' and 'catch' callbacks in a task
- * manager compatible way. For an individual promise, either the 'then'
- * arguments or the 'catch' arguments will be processed, never both.
- *
- * Example:
- * var p = new Promise([Function]);
- * p.then([ThenA]);
- * p.then([ThenB]);
- * p.catch([CatchA]);
- * On resolution, [ThenA] and [ThenB] will be used. [CatchA] is discarded.
- * On rejection, vice versa.
- *
- * Clarification:
- * Chained promises create a new promise that is tracked separately from
- * the originaing promise, as the example below demonstrates:
- *
- * var p = new Promise([Function]));
- * p.then([ThenA]).then([ThenB]).catch([CatchA]);
- * ^ ^ ^
- * | | + Returns a new promise.
- * | + Returns a new promise.
- * + Returns a new promise.
- *
- * Four promises exist in the above statement, each with its own
- * resolution and rejection state. However, by default, this state is
- * chained to the previous promise's resolution or rejection
- * state.
- *
- * If p resolves, then the 'then' calls will execute until all the 'then'
- * clauses are executed. If the result of either [ThenA] or [ThenB] is a
- * promise, then that execution state will guide the remaining chain.
- * Similarly, if [CatchA] returns a promise, it can also guide the
- * remaining chain. In this specific case, the chain ends, so there
- * is nothing left to do.
- * @param {object} promise Promise being tracked.
- * @return {object} A promise callback tracker.
- */
- function createPromiseCallbackTracker(promise) {
- /**
- * Callback Tracker. Holds an array of callbacks created for this promise.
- * The indirection allows quick checks against the array and clearing the
- * array without ugly splicing and copying.
- * @typedef {{
- * callback: array<Function>=
- * }}
- */
- var CallbackTracker;
-
- /** @type {CallbackTracker} */
- var thenTracker = {callbacks: []};
- /** @type {CallbackTracker} */
- var catchTracker = {callbacks: []};
-
- /**
- * Returns true if the specified value is callable.
- * @param {*} value Value to check.
- * @return {boolean} True if the value is a callable.
- */
- function isCallable(value) {
- return typeof value === 'function';
- }
-
- /**
- * Takes a tracker and clears its callbacks in a manner consistent with
- * the task manager. For the task manager, it also calls all callbacks
- * by no-oping them first and then calling them.
- * @param {CallbackTracker} tracker Tracker to clear.
- */
- function clearTracker(tracker) {
- if (tracker.callbacks) {
- var callbacksToClear = tracker.callbacks;
- // No-ops all callbacks of this type.
- tracker.callbacks = undefined;
- // Do not wrap the promise then argument!
- // It will call wrapped callbacks.
- originalThen.call(Promise.resolve(), function() {
- for (var i = 0; i < callbacksToClear.length; i++) {
- callbacksToClear[i]();
- }
- });
- }
- }
-
- /**
- * Takes the argument to a 'then' or 'catch' function and applies
- * a wrapping to callables consistent to ECMA promises.
- * @param {*} maybeCallback Argument to 'then' or 'catch'.
- * @param {CallbackTracker} sameTracker Tracker for the call type.
- * Example: If the argument is from a 'then' call, use thenTracker.
- * @param {CallbackTracker} otherTracker Tracker for the opposing call type.
- * Example: If the argument is from a 'then' call, use catchTracker.
- * @return {*} Consumable argument with necessary wrapping applied.
- */
- function registerAndWrapMaybeCallback(
- maybeCallback, sameTracker, otherTracker) {
- // If sameTracker.callbacks is undefined, we've reached an ending state
- // that means this callback will never be called back.
- // We will still forward this call on to let the promise system
- // handle further processing, but since this promise is in an ending state
- // we can be confident it will never be called back.
- if (isCallable(maybeCallback) &&
- !maybeCallback.wrappedByPromiseTracker &&
- sameTracker.callbacks) {
- var handler = wrapper.wrapCallback(function() {
- if (sameTracker.callbacks) {
- clearTracker(otherTracker);
- return maybeCallback.apply(null, arguments);
- }
- }, false);
- // Harmony promises' catch calls will call into handleThen,
- // double-wrapping all catch callbacks. Regular promise catch calls do
- // not call into handleThen. Setting an attribute on the wrapped
- // function is compatible with both promise implementations.
- handler.wrappedByPromiseTracker = true;
- sameTracker.callbacks.push(handler);
- return handler;
- } else {
- return maybeCallback;
- }
- }
-
- /**
- * Tracks then calls equivalent to Promise.prototype.then.
- * @param {*} onResolved Argument to use if the promise is resolved.
- * @param {*} onRejected Argument to use if the promise is rejected.
- * @return {object} Promise resulting from the 'then' call.
- */
- function handleThen(onResolved, onRejected) {
- var resolutionHandler =
- registerAndWrapMaybeCallback(onResolved, thenTracker, catchTracker);
- var rejectionHandler =
- registerAndWrapMaybeCallback(onRejected, catchTracker, thenTracker);
- return originalThen.call(promise, resolutionHandler, rejectionHandler);
- }
-
- /**
- * Tracks then calls equivalent to Promise.prototype.catch.
- * @param {*} onRejected Argument to use if the promise is rejected.
- * @return {object} Promise resulting from the 'catch' call.
- */
- function handleCatch(onRejected) {
- var rejectionHandler =
- registerAndWrapMaybeCallback(onRejected, catchTracker, thenTracker);
- return originalCatch.call(promise, rejectionHandler);
- }
-
- // Register at least one resolve and reject callback so we always receive
- // a callback to update the task manager and clear the callbacks
- // that will never occur.
- //
- // The then form is used to avoid reentrancy by handleCatch,
- // which ends up calling handleThen.
- handleThen(function() {}, function() {});
-
- return {
- handleThen: handleThen,
- handleCatch: handleCatch
- };
- }
-}
-
-registerPromiseAdapter();
-
-/**
- * Control promise rejection.
- * @enum {number}
- */
-var PromiseRejection = {
- /** Disallow promise rejection */
- DISALLOW: 0,
- /** Allow promise rejection */
- ALLOW: 1
-};
-
-/**
- * Provides the promise equivalent of instrumented.storage.local.get.
- * @param {Object} defaultStorageObject Default storage object to fill.
- * @param {PromiseRejection=} opt_allowPromiseRejection If
- * PromiseRejection.ALLOW, allow promise rejection on errors, otherwise the
- * default storage object is resolved.
- * @return {Promise} A promise that fills the default storage object. On
- * failure, if promise rejection is allowed, the promise is rejected,
- * otherwise it is resolved to the default storage object.
- */
-function fillFromChromeLocalStorage(
- defaultStorageObject,
- opt_allowPromiseRejection) {
- return new Promise(function(resolve, reject) {
- // We have to create a keys array because keys with a default value
- // of undefined will cause that key to not be looked up!
- var keysToGet = [];
- for (var key in defaultStorageObject) {
- keysToGet.push(key);
- }
- instrumented.storage.local.get(keysToGet, function(items) {
- if (items) {
- // Merge the result with the default storage object to ensure all keys
- // requested have either the default value or the retrieved storage
- // value.
- var result = {};
- for (var key in defaultStorageObject) {
- result[key] = (key in items) ? items[key] : defaultStorageObject[key];
- }
- resolve(result);
- } else if (opt_allowPromiseRejection === PromiseRejection.ALLOW) {
- reject();
- } else {
- resolve(defaultStorageObject);
- }
- });
- });
-}
-
-/**
- * Builds the object to manage tasks (mutually exclusive chains of events).
- * @param {function(string, string): boolean} areConflicting Function that
- * checks if a new task can't be added to a task queue that contains an
- * existing task.
- * @return {Object} Task manager interface.
- */
-function buildTaskManager(areConflicting) {
- /**
- * Queue of scheduled tasks. The first element, if present, corresponds to the
- * currently running task.
- * @type {Array<Object<function()>>}
- */
- var queue = [];
-
- /**
- * Count of unfinished callbacks of the current task.
- * @type {number}
- */
- var taskPendingCallbackCount = 0;
-
- /**
- * True if currently executed code is a part of a task.
- * @type {boolean}
- */
- var isInTask = false;
-
- /**
- * Starts the first queued task.
- */
- function startFirst() {
- verify(queue.length >= 1, 'startFirst: queue is empty');
- verify(!isInTask, 'startFirst: already in task');
- isInTask = true;
-
- // Start the oldest queued task, but don't remove it from the queue.
- verify(
- taskPendingCallbackCount == 0,
- 'tasks.startFirst: still have pending task callbacks: ' +
- taskPendingCallbackCount +
- ', queue = ' + JSON.stringify(queue) + ', ' +
- wrapper.debugGetStateString());
- var entry = queue[0];
- console.log('Starting task ' + entry.name);
-
- entry.task();
-
- verify(isInTask, 'startFirst: not in task at exit');
- isInTask = false;
- if (taskPendingCallbackCount == 0)
- finish();
- }
-
- /**
- * Checks if a new task can be added to the task queue.
- * @param {string} taskName Name of the new task.
- * @return {boolean} Whether the new task can be added.
- */
- function canQueue(taskName) {
- for (var i = 0; i < queue.length; ++i) {
- if (areConflicting(taskName, queue[i].name)) {
- console.log('Conflict: new=' + taskName +
- ', scheduled=' + queue[i].name);
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Adds a new task. If another task is not running, runs the task immediately.
- * If any task in the queue is not compatible with the task, ignores the new
- * task. Otherwise, stores the task for future execution.
- * @param {string} taskName Name of the task.
- * @param {function()} task Function to run.
- */
- function add(taskName, task) {
- wrapper.checkInWrappedCallback();
- console.log('Adding task ' + taskName);
- if (!canQueue(taskName))
- return;
-
- queue.push({name: taskName, task: task});
-
- if (queue.length == 1) {
- startFirst();
- }
- }
-
- /**
- * Completes the current task and starts the next queued task if available.
- */
- function finish() {
- verify(queue.length >= 1,
- 'tasks.finish: The task queue is empty');
- console.log('Finishing task ' + queue[0].name);
- queue.shift();
-
- if (queue.length >= 1)
- startFirst();
- }
-
- instrumented.runtime.onSuspend.addListener(function() {
- verify(
- queue.length == 0,
- 'Incomplete task when unloading event page,' +
- ' queue = ' + JSON.stringify(queue) + ', ' +
- wrapper.debugGetStateString());
- });
-
-
- /**
- * Wrapper plugin for tasks.
- * @constructor
- */
- function TasksWrapperPlugin() {
- this.isTaskCallback = isInTask;
- if (this.isTaskCallback)
- ++taskPendingCallbackCount;
- }
-
- TasksWrapperPlugin.prototype = {
- /**
- * Plugin code to be executed before invoking the original callback.
- */
- prologue: function() {
- if (this.isTaskCallback) {
- verify(!isInTask, 'TasksWrapperPlugin.prologue: already in task');
- isInTask = true;
- }
- },
-
- /**
- * Plugin code to be executed after invoking the original callback.
- */
- epilogue: function() {
- if (this.isTaskCallback) {
- verify(isInTask, 'TasksWrapperPlugin.epilogue: not in task at exit');
- isInTask = false;
- if (--taskPendingCallbackCount == 0)
- finish();
- }
- }
- };
-
- wrapper.registerWrapperPluginFactory(function() {
- return new TasksWrapperPlugin();
- });
-
- return {
- add: add
- };
-}
-
-/**
- * Builds an object to manage retrying activities with exponential backoff.
- * @param {string} name Name of this attempt manager.
- * @param {function()} attempt Activity that the manager retries until it
- * calls 'stop' method.
- * @param {number} initialDelaySeconds Default first delay until first retry.
- * @param {number} maximumDelaySeconds Maximum delay between retries.
- * @return {Object} Attempt manager interface.
- */
-function buildAttemptManager(
- name, attempt, initialDelaySeconds, maximumDelaySeconds) {
- var alarmName = 'attempt-scheduler-' + name;
- var currentDelayStorageKey = 'current-delay-' + name;
-
- /**
- * Creates an alarm for the next attempt. The alarm is repeating for the case
- * when the next attempt crashes before registering next alarm.
- * @param {number} delaySeconds Delay until next retry.
- */
- function createAlarm(delaySeconds) {
- var alarmInfo = {
- delayInMinutes: delaySeconds / 60,
- periodInMinutes: maximumDelaySeconds / 60
- };
- chrome.alarms.create(alarmName, alarmInfo);
- }
-
- /**
- * Indicates if this attempt manager has started.
- * @param {function(boolean)} callback The function's boolean parameter is
- * true if the attempt manager has started, false otherwise.
- */
- function isRunning(callback) {
- instrumented.alarms.get(alarmName, function(alarmInfo) {
- callback(!!alarmInfo);
- });
- }
-
- /**
- * Schedules the alarm with a random factor to reduce the chance that all
- * clients will fire their timers at the same time.
- * @param {number} durationSeconds Number of seconds before firing the alarm.
- */
- function scheduleAlarm(durationSeconds) {
- durationSeconds = Math.min(durationSeconds, maximumDelaySeconds);
- var randomizedRetryDuration = durationSeconds * (1 + 0.2 * Math.random());
-
- createAlarm(randomizedRetryDuration);
-
- var items = {};
- items[currentDelayStorageKey] = randomizedRetryDuration;
- chrome.storage.local.set(items);
- }
-
- /**
- * Starts repeated attempts.
- * @param {number=} opt_firstDelaySeconds Time until the first attempt, if
- * specified. Otherwise, initialDelaySeconds will be used for the first
- * attempt.
- */
- function start(opt_firstDelaySeconds) {
- if (opt_firstDelaySeconds) {
- createAlarm(opt_firstDelaySeconds);
- chrome.storage.local.remove(currentDelayStorageKey);
- } else {
- scheduleAlarm(initialDelaySeconds);
- }
- }
-
- /**
- * Stops repeated attempts.
- */
- function stop() {
- chrome.alarms.clear(alarmName);
- chrome.storage.local.remove(currentDelayStorageKey);
- }
-
- /**
- * Schedules an exponential backoff retry.
- * @return {Promise} A promise to schedule the retry.
- */
- function scheduleRetry() {
- var request = {};
- request[currentDelayStorageKey] = undefined;
- return fillFromChromeLocalStorage(request, PromiseRejection.ALLOW)
- .catch(function() {
- request[currentDelayStorageKey] = maximumDelaySeconds;
- return Promise.resolve(request);
- })
- .then(function(items) {
- console.log('scheduleRetry-get-storage ' + JSON.stringify(items));
- var retrySeconds = initialDelaySeconds;
- if (items[currentDelayStorageKey]) {
- retrySeconds = items[currentDelayStorageKey] * 2;
- }
- scheduleAlarm(retrySeconds);
- });
- }
-
- instrumented.alarms.onAlarm.addListener(function(alarm) {
- if (alarm.name == alarmName)
- isRunning(function(running) {
- if (running)
- attempt();
- });
- });
-
- return {
- start: start,
- scheduleRetry: scheduleRetry,
- stop: stop,
- isRunning: isRunning
- };
-}
-
-// TODO(robliao): Use signed-in state change watch API when it's available.
-/**
- * Wraps chrome.identity to provide limited listening support for
- * the sign in state by polling periodically for the auth token.
- * @return {Object} The Authentication Manager interface.
- */
-function buildAuthenticationManager() {
- var alarmName = 'sign-in-alarm';
-
- /**
- * Gets an OAuth2 access token.
- * @return {Promise} A promise to get the authentication token. If there is
- * no token, the request is rejected.
- */
- function getAuthToken() {
- return new Promise(function(resolve, reject) {
- instrumented.identity.getAuthToken({interactive: false}, function(token) {
- if (chrome.runtime.lastError || !token) {
- reject();
- } else {
- resolve(token);
- }
- });
- });
- }
-
- /**
- * Determines the active account's login (username).
- * @return {Promise} A promise to determine the current account's login.
- */
- function getLogin() {
- return new Promise(function(resolve) {
- instrumented.webstorePrivate.getBrowserLogin(function(accountInfo) {
- resolve(accountInfo.login);
- });
- });
- }
-
- /**
- * Determines whether there is an account attached to the profile.
- * @return {Promise} A promise to determine if there is an account attached
- * to the profile.
- */
- function isSignedIn() {
- return getLogin().then(function(login) {
- return Promise.resolve(!!login);
- });
- }
-
- /**
- * Removes the specified cached token.
- * @param {string} token Authentication Token to remove from the cache.
- * @return {Promise} A promise that resolves on completion.
- */
- function removeToken(token) {
- return new Promise(function(resolve) {
- instrumented.identity.removeCachedAuthToken({token: token}, function() {
- // Let Chrome know about a possible problem with the token.
- getAuthToken();
- resolve();
- });
- });
- }
-
- var listeners = [];
-
- /**
- * Registers a listener that gets called back when the signed in state
- * is found to be changed.
- * @param {function()} callback Called when the answer to isSignedIn changes.
- */
- function addListener(callback) {
- listeners.push(callback);
- }
-
- /**
- * Checks if the last signed in state matches the current one.
- * If it doesn't, it notifies the listeners of the change.
- */
- function checkAndNotifyListeners() {
- isSignedIn().then(function(signedIn) {
- fillFromChromeLocalStorage({lastSignedInState: undefined})
- .then(function(items) {
- if (items.lastSignedInState != signedIn) {
- chrome.storage.local.set(
- {lastSignedInState: signedIn});
- listeners.forEach(function(callback) {
- callback();
- });
- }
- });
- });
- }
-
- instrumented.identity.onSignInChanged.addListener(function() {
- checkAndNotifyListeners();
- });
-
- instrumented.alarms.onAlarm.addListener(function(alarm) {
- if (alarm.name == alarmName)
- checkAndNotifyListeners();
- });
-
- // Poll for the sign in state every hour.
- // One hour is just an arbitrary amount of time chosen.
- chrome.alarms.create(alarmName, {periodInMinutes: 60});
-
- return {
- addListener: addListener,
- getAuthToken: getAuthToken,
- getLogin: getLogin,
- isSignedIn: isSignedIn,
- removeToken: removeToken
- };
-}
diff --git a/chromium/chrome/browser/resources/google_now/utility_test_util.js b/chromium/chrome/browser/resources/google_now/utility_test_util.js
deleted file mode 100644
index 741d84dc856..00000000000
--- a/chromium/chrome/browser/resources/google_now/utility_test_util.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Mocks for globals needed for loading utility.js.
-
-var localStorage = {};
-
-chrome['alarms'] = {
- get: emptyMock
-};
-chrome['identity'] = {
- getAuthToken: emptyMock,
- removeCachedAuthToken: emptyMock
-};
-chrome['storage'] = {
- local: {
- get: emptyMock
- }
-};
-chrome['webstorePrivate'] = {
- getBrowserLogin: emptyMock
-};
-
-mockChromeEvent(chrome, 'alarms.onAlarm');
-mockChromeEvent(chrome, 'identity.onSignInChanged');
-mockChromeEvent(chrome, 'runtime.onSuspend');
diff --git a/chromium/chrome/browser/resources/google_now/utility_unittest.gtestjs b/chromium/chrome/browser/resources/google_now/utility_unittest.gtestjs
deleted file mode 100644
index bbf3a6d2196..00000000000
--- a/chromium/chrome/browser/resources/google_now/utility_unittest.gtestjs
+++ /dev/null
@@ -1,995 +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.
-
-/**
- * Test fixture for utility.js.
- * @constructor
- * @extends {testing.Test}
- */
-function GoogleNowUtilityUnitTest () {
- testing.Test.call(this);
-}
-
-GoogleNowUtilityUnitTest.prototype = {
- __proto__: testing.Test.prototype,
-
- /** @override */
- extraLibraries: [
- 'common_test_util.js',
- 'utility_test_util.js',
- 'utility.js'
- ]
-};
-
-TEST_F('GoogleNowUtilityUnitTest', 'SendErrorReport1', function() {
- // Test sending report for an error with a message that can be sent to server.
-
- // Setup and expectations.
- var testStack = 'Error: TEST ERROR MESSAGE\n ' +
- 'at buildErrorWithMessageForServer ' +
- '(chrome-extension://ext_id/utility.js:29:15)\n' +
- ' at <anonymous>:2:16\n ' +
- 'at Object.InjectedScript._evaluateOn (<anonymous>:580:39)\n ' +
- 'at Object.InjectedScript._evaluateAndWrap (<anonymous>:539:52)\n ' +
- 'at Object.InjectedScript.evaluate (<anonymous>:458:21)';
-
- var testError = {
- canSendMessageToServer: true,
- stack: testStack,
- name: 'TEST ERROR NAME',
- message: 'TEST ERROR MESSAGE'
- };
-
- var testIdentityToken = 'test identity token';
-
- this.makeAndRegisterMockGlobals(['buildServerRequest']);
- this.makeMockLocalFunctions(['sendRequest', 'setRequestHeader']);
- this.makeAndRegisterMockApis(['chrome.identity.getAuthToken']);
-
- var mockRequest = {
- send: this.mockLocalFunctions.functions().sendRequest,
- setRequestHeader: this.mockLocalFunctions.functions().setRequestHeader
- };
-
- var expectedRequestObject = {
- message: 'TEST ERROR NAME: TEST ERROR MESSAGE',
- file: '//ext_id/utility.js',
- line: '29',
- trace: 'Error: TEST ERROR MESSAGE\n ' +
- 'at buildErrorWithMessageForServer (chrome-extension://ext_id/util' +
- 'ity.js:29:15)\n ' +
- 'at <anonymous>:2:16\n ' +
- 'at Object.InjectedScript._evaluateOn (<anonymous>:580:39)\n ' +
- 'at Object.InjectedScript._evaluateAndWrap (<anonymous>:539:52)\n' +
- ' at Object.InjectedScript.evaluate (<anonymous>:458:21)'
- };
-
- this.mockGlobals.expects(once()).
- buildServerRequest('POST', 'jserrors', 'application/json').
- will(returnValue(mockRequest));
-
- var chromeIdentityGetAuthTokenSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- chrome_identity_getAuthToken(
- chromeIdentityGetAuthTokenSavedArgs.match(
- eqJSON({interactive: false})),
- chromeIdentityGetAuthTokenSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- chromeIdentityGetAuthTokenSavedArgs,
- 1,
- testIdentityToken));
-
- this.mockLocalFunctions.expects(once()).setRequestHeader(
- 'Authorization', 'Bearer test identity token');
- this.mockLocalFunctions.expects(once()).sendRequest(
- JSON.stringify(expectedRequestObject));
-
- // Invoking the tested function.
- sendErrorReport(testError);
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'SendErrorReport2', function() {
- // Test sending report for an error with a message that should not be sent to
- // server, with an error generated in an anonymous function.
-
- // Setup and expectations.
- var testStack = 'TypeError: Property \'processPendingDismissals\' of ' +
- 'object [object Object] is not a function\n ' +
- 'at chrome-extension://ext_id/background.js:444:11\n ' +
- 'at chrome-extension://ext_id/utility.js:509:7';
-
- var testError = {
- stack: testStack,
- name: 'TypeError'
- };
-
- var testIdentityToken = 'test identity token';
-
- this.makeAndRegisterMockGlobals(['buildServerRequest']);
- this.makeMockLocalFunctions(['sendRequest', 'setRequestHeader']);
- this.makeAndRegisterMockApis(['chrome.identity.getAuthToken']);
-
- var mockRequest = {
- send: this.mockLocalFunctions.functions().sendRequest,
- setRequestHeader: this.mockLocalFunctions.functions().setRequestHeader
- };
-
- var expectedRequestObject = {
- message: 'TypeError',
- file: '//ext_id/background.js',
- line: '444',
- trace: '(message removed)\n ' +
- 'at chrome-extension://ext_id/background.js:444:11\n ' +
- 'at chrome-extension://ext_id/utility.js:509:7'
- };
-
- this.mockGlobals.expects(once()).
- buildServerRequest('POST', 'jserrors', 'application/json').
- will(returnValue(mockRequest));
-
- var chromeIdentityGetAuthTokenSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- chrome_identity_getAuthToken(
- chromeIdentityGetAuthTokenSavedArgs.match(
- eqJSON({interactive: false})),
- chromeIdentityGetAuthTokenSavedArgs.match(ANYTHING)).
- will(invokeCallback(
- chromeIdentityGetAuthTokenSavedArgs,
- 1,
- testIdentityToken));
-
- this.mockLocalFunctions.expects(once()).setRequestHeader(
- 'Authorization', 'Bearer test identity token');
- this.mockLocalFunctions.expects(once()).sendRequest(
- JSON.stringify(expectedRequestObject));
-
- // Invoking the tested function.
- sendErrorReport(testError);
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'WrapperCheckInWrappedCallback', function() {
- // Test generating an error when calling wrapper.checkInWrappedCallback from a
- // non-instrumented code.
-
- // Setup and expectations.
- var testError = {
- testField: 'TEST VALUE'
- };
-
- this.makeAndRegisterMockGlobals([
- 'buildErrorWithMessageForServer',
- 'reportError'
- ]);
-
- this.mockGlobals.expects(once()).
- buildErrorWithMessageForServer('Not in instrumented callback').
- will(returnValue(testError));
- this.mockGlobals.expects(once()).
- reportError(eqJSON(testError));
-
- // Invoking the tested function.
- wrapper.checkInWrappedCallback();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackEvent', function() {
- // Tests wrapping event handler and that the handler code counts as an
- // instrumented callback.
-
- // Setup.
- var testError = {
- testField: 'TEST VALUE'
- };
-
- this.makeAndRegisterMockGlobals([
- 'buildErrorWithMessageForServer',
- 'reportError'
- ]);
- var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend');
-
- this.makeMockLocalFunctions(['callback']);
-
- // Step 1. Wrap a callback.
- var wrappedCallback =
- wrapper.wrapCallback(this.mockLocalFunctions.functions().callback, true);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Invoke wrapped callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).
- callback('test string', 239).
- will(callFunction(function() {
- wrapper.checkInWrappedCallback(); // it should succeed
- }));
-
- // Invoking tested function.
- wrappedCallback('test string', 239);
- Mock4JS.verifyAllMocks();
-
- // Step 3. Check that after the callback we are again in non-instrumented
- // code.
- // Expectations.
- this.mockGlobals.expects(once()).
- buildErrorWithMessageForServer('Not in instrumented callback').
- will(returnValue(testError));
- this.mockGlobals.expects(once()).
- reportError(eqJSON(testError));
-
- // Invocation.
- wrapper.checkInWrappedCallback();
-
- // Step 4. Check that there won't be errors whe the page unloads.
- assertEquals(1, onSuspendHandlerContainer.length);
- onSuspendHandlerContainer[0]();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackPlugin', function() {
- // Tests calling plugin's prologue and epilogue.
-
- // Setup.
- this.makeMockLocalFunctions([
- 'callback',
- 'pluginFactory',
- 'prologue',
- 'epilogue'
- ]);
-
- // Step 1. Register plugin factory.
- wrapper.registerWrapperPluginFactory(
- this.mockLocalFunctions.functions().pluginFactory);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Wrap a callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).
- pluginFactory().
- will(returnValue({
- prologue: this.mockLocalFunctions.functions().prologue,
- epilogue: this.mockLocalFunctions.functions().epilogue
- }));
-
- // Invoking tested function.
- var wrappedCallback =
- wrapper.wrapCallback(this.mockLocalFunctions.functions().callback, true);
- Mock4JS.verifyAllMocks();
-
- // Step 3. Call the wrapped callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).prologue();
- this.mockLocalFunctions.expects(once()).callback();
- this.mockLocalFunctions.expects(once()).epilogue();
-
- // Invoking wrapped callback.
- wrappedCallback();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackCatchError', function() {
- // Tests catching and sending errors by a wrapped callback.
-
- // Setup.
- this.makeAndRegisterMockGlobals([
- 'reportError'
- ]);
- this.makeMockLocalFunctions(['callback']);
-
- // Step 1. Wrap a callback.
- var wrappedCallback =
- wrapper.wrapCallback(this.mockLocalFunctions.functions().callback, true);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Invoke wrapped callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).
- callback().
- will(callFunction(function() {
- undefined.x = 5;
- }));
- this.mockGlobals.expects(once()).
- reportError(
- eqToString('TypeError: Cannot set property \'x\' of undefined'));
-
- // Invoking tested function.
- wrappedCallback();
-});
-
-TEST_F('GoogleNowUtilityUnitTest',
- 'WrapperInstrumentChromeApiFunction',
- function() {
- // Tests wrapper.instrumentChromeApiFunction().
-
- // Setup.
- this.makeMockLocalFunctions([
- 'apiFunction1',
- 'apiFunction2',
- 'callback1',
- 'callback2',
- 'pluginFactory',
- 'prologue',
- 'epilogue'
- ]);
- chrome.testApi = {
- addListener: this.mockLocalFunctions.functions().apiFunction1
- };
-
- // Step 1. Instrument the listener.
- wrapper.instrumentChromeApiFunction('testApi.addListener', 1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Invoke the instrumented API call.
- // Expectations.
- var function1SavedArgs = new SaveMockArguments();
- this.mockLocalFunctions.expects(once()).
- apiFunction1(
- function1SavedArgs.match(eq(239)),
- function1SavedArgs.match(ANYTHING));
-
- // Invocation.
- instrumented.testApi.addListener(
- 239, this.mockLocalFunctions.functions().callback1);
- Mock4JS.verifyAllMocks();
-
- // Step 3. Invoke the callback that was passed by the instrumented function
- // to the original one.
- // Expectations.
- this.mockLocalFunctions.expects(once()).callback1(237);
-
- // Invocation.
- function1SavedArgs.arguments[1](237);
- Mock4JS.verifyAllMocks();
-
- // Step 4. Register plugin factory.
- wrapper.registerWrapperPluginFactory(
- this.mockLocalFunctions.functions().pluginFactory);
- Mock4JS.verifyAllMocks();
-
- // Step 5. Bind the API to another function.
- chrome.testApi.addListener = this.mockLocalFunctions.functions().apiFunction2;
-
- // Step 6. Invoke the API with another callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).
- pluginFactory().
- will(returnValue({
- prologue: this.mockLocalFunctions.functions().prologue,
- epilogue: this.mockLocalFunctions.functions().epilogue
- }));
- var function2SavedArgs = new SaveMockArguments();
- this.mockLocalFunctions.expects(once()).
- apiFunction2(
- function2SavedArgs.match(eq(239)),
- function2SavedArgs.match(ANYTHING));
-
- // Invocation.
- instrumented.testApi.addListener(
- 239, this.mockLocalFunctions.functions().callback2);
- Mock4JS.verifyAllMocks();
-
- // Step 7. Invoke the callback that was passed by the instrumented function
- // to the original one.
- // Expectations.
- this.mockLocalFunctions.expects(once()).prologue();
- this.mockLocalFunctions.expects(once()).callback2(237);
- this.mockLocalFunctions.expects(once()).epilogue();
-
- // Invocation.
- function2SavedArgs.arguments[1](237);
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'WrapperOnSuspendListenerFail', function() {
- // Tests that upon unloading event page, we get an error if there are pending
- // required callbacks.
-
- // Setup.
- var testError = {
- testField: 'TEST VALUE'
- };
- this.makeAndRegisterMockGlobals([
- 'buildErrorWithMessageForServer',
- 'reportError'
- ]);
- this.makeMockLocalFunctions(['listener', 'callback']);
- var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend');
-
- // Step 1. Wrap event listener.
- var wrappedListener =
- wrapper.wrapCallback(this.mockLocalFunctions.functions().listener, true);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Invoke event listener, which will wrap a required callback.
- // Setup and expectations.
- var wrappedCallback;
- var testFixture = this;
- this.mockLocalFunctions.expects(once()).
- listener().
- will(callFunction(function() {
- wrappedCallback = wrapper.wrapCallback(
- testFixture.mockLocalFunctions.functions().callback);
- }));
-
- // Invocation.
- wrappedListener();
- Mock4JS.verifyAllMocks();
-
- // Step 3. Fire runtime.onSuspend event.
- // Expectations.
- this.mockGlobals.expects(once()).
- buildErrorWithMessageForServer(stringContains(
- 'ASSERT: Pending callbacks when unloading event page')).
- will(returnValue(testError));
- this.mockGlobals.expects(once()).
- reportError(eqJSON(testError));
-
- // Invocation.
- assertEquals(1, onSuspendHandlerContainer.length);
- onSuspendHandlerContainer[0]();
-});
-
-TEST_F('GoogleNowUtilityUnitTest',
- 'WrapperOnSuspendListenerSuccess',
- function() {
- // Tests that upon unloading event page, we don't get an error if there are no
- // pending required callbacks.
-
- // Setup.
- this.makeMockLocalFunctions(['listener', 'callback']);
- var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend');
-
- // Step 1. Wrap event listener.
- var wrappedListener =
- wrapper.wrapCallback(this.mockLocalFunctions.functions().listener, true);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Invoke event listener, which will wrap a required callback.
- // Setup and expectations.
- var wrappedCallback;
- var testFixture = this;
- this.mockLocalFunctions.expects(once()).
- listener().
- will(callFunction(function() {
- wrappedCallback = wrapper.wrapCallback(
- testFixture.mockLocalFunctions.functions().callback);
- }));
-
- // Invocation.
- wrappedListener();
- Mock4JS.verifyAllMocks();
-
- // Step 3. Call wrapped callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).callback();
-
- // Invocation.
- wrappedCallback();
-
- // Step 4. Fire runtime.onSuspend event.
- assertEquals(1, onSuspendHandlerContainer.length);
- onSuspendHandlerContainer[0]();
-});
-
-var taskNameA = 'TASK A';
-var taskNameB = 'TASK B';
-var taskNameC = 'TASK C';
-
-function areTasksConflicting(newTaskName, scheduledTaskName) {
- // Task B is conflicting with Task A. This means that if Task B is added when
- // Task A is running, Task B will be ignored (but not vice versa). No other
- // pair is conflicting.
- return newTaskName == taskNameB && scheduledTaskName == taskNameA;
-}
-
-function setUpTaskManagerTest(fixture) {
- fixture.makeAndRegisterMockApis([
- 'wrapper.checkInWrappedCallback',
- 'wrapper.registerWrapperPluginFactory',
- 'wrapper.debugGetStateString'
- ]);
- fixture.makeMockLocalFunctions(['task1', 'task2', 'task3']);
- fixture.makeAndRegisterMockGlobals(['reportError']);
-
- fixture.mockApis.stubs().wrapper_checkInWrappedCallback();
- fixture.mockApis.stubs().wrapper_debugGetStateString().
- will(returnValue('testWrapperDebugState'));
-
- var registerWrapperPluginFactorySavedArgs = new SaveMockArguments();
- fixture.mockApis.expects(once()).wrapper_registerWrapperPluginFactory(
- registerWrapperPluginFactorySavedArgs.match(ANYTHING));
- var tasks = buildTaskManager(areTasksConflicting);
- Mock4JS.verifyAllMocks();
-
- return {
- tasks: tasks,
- pluginFactory: registerWrapperPluginFactorySavedArgs.arguments[0]
- };
-}
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManager2Sequential', function() {
- // Tests that 2 tasks get successfully executed consecutively, even if the
- // second one conflicts with the first.
-
- // Setup.
- var test = setUpTaskManagerTest(this);
-
- // Step 1. Add 1st task that doesn't create pending callbacks.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1();
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Add 2nd task.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task2();
- // Invocation.
- test.tasks.add(taskNameB, this.mockLocalFunctions.functions().task2);
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerConflicting', function() {
- // Tests that adding a task while a conflicting task is being executed causes
- // the second one to be ignored.
-
- // Setup.
- var test = setUpTaskManagerTest(this);
- var task1PluginInstance;
-
- // Step 1. Add 1st task that creates a pending callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1().
- will(callFunction(function() {
- task1PluginInstance = test.pluginFactory();
- }));
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Add 2nd task. Since it conflicts with currently running task1
- // (see areTasksConflicting), it should be ignored.
- test.tasks.add(taskNameB, this.mockLocalFunctions.functions().task2);
- Mock4JS.verifyAllMocks();
-
- // Step 3. Enter the callback of task1.
- task1PluginInstance.prologue();
- Mock4JS.verifyAllMocks();
-
- // Step 4. Leave the callback of task1.
- task1PluginInstance.epilogue();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerNestedTaskEnqueue', function() {
- // Tests that adding a task while a non-conflicting task is being executed
- // causes the second one to be executed after the first one completes.
-
- // Setup.
- var test = setUpTaskManagerTest(this);
- var task1PluginInstance;
-
- // Step 1. Add 1st task that creates a pending callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1().
- will(callFunction(function() {
- task1PluginInstance = test.pluginFactory();
- }));
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Add 2nd task. Since it doesn't conflict with currently running
- // task1 (see areTasksConflicting), it should not be ignored.
- test.tasks.add(taskNameC, this.mockLocalFunctions.functions().task2);
- Mock4JS.verifyAllMocks();
-
- // Step 3. Enter the callback of task1.
- task1PluginInstance.prologue();
- Mock4JS.verifyAllMocks();
-
- // Step 4. Leave the callback of task1.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task2();
- // Invocation.
- task1PluginInstance.epilogue();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerBranching', function() {
- // Tests that task manager correctly detects completion of tasks that create
- // branching chains of callbacks (in this test, task1 creates pending
- // callbacks 1 and 2, and callback 1 creates pending callback 3).
-
- // Setup.
- var test = setUpTaskManagerTest(this);
- var task1PluginInstance1, task1PluginInstance2, task1PluginInstance3;
-
- // Step 1. Add 1st task that creates a 2 pending callbacks.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1().
- will(callFunction(function() {
- task1PluginInstance1 = test.pluginFactory();
- task1PluginInstance2 = test.pluginFactory();
- }));
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Add 2nd task, which is not conflicting (see areTasksConflicting)
- // with task1.
- test.tasks.add(taskNameC, this.mockLocalFunctions.functions().task2);
- Mock4JS.verifyAllMocks();
-
- // Step 3. Enter callback 1, create pending callback 3, exit callback 1.
- // Enter/exit callback 2. Enter callback 3.
- task1PluginInstance1.prologue();
- task1PluginInstance3 = test.pluginFactory();
- task1PluginInstance1.epilogue();
- task1PluginInstance2.prologue();
- task1PluginInstance2.epilogue();
- task1PluginInstance3.prologue();
- Mock4JS.verifyAllMocks();
-
- // Step 4. Leave 3rd callback of task1. Now task1 is complete, and task2
- // should start.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task2();
- // Invocation.
- task1PluginInstance3.epilogue();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerSuspendError', function() {
- // Tests that task manager's onSuspend method reports an error if there are
- // pending tasks.
-
- // Setup.
- var test = setUpTaskManagerTest(this);
- var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend');
-
- // Step 1. Add a task that creates a pending callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1().
- will(callFunction(function() {
- test.pluginFactory();
- }));
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Invoke onSuspend event of the task manager.
- // Setup and expectations. The 2 callbacks in onSuspendHandlerContainer are
- // from the wrapper and the task manager.
- assertEquals(2, onSuspendHandlerContainer.length);
- this.mockGlobals.expects(once()).reportError(eqToString(
- 'Error: ASSERT: Incomplete task when unloading event page,' +
- ' queue = [{"name":"TASK A"}], testWrapperDebugState'));
- // Invocation.
- onSuspendHandlerContainer[1]();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerSuspendSuccess', function() {
- // Tests that task manager's onSuspend method does not report an error if all
- // tasks completed.
-
- // Setup.
- var test = setUpTaskManagerTest(this);
- var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend');
- var task1PluginInstance;
-
- // Step 1. Add a task that creates a pending callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1().
- will(callFunction(function() {
- task1PluginInstance = test.pluginFactory();
- }));
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Invoke task's callback and the onSuspend event of the task manager.
- // The 2 callbacks in onSuspendHandlerContainer are from the wrapper and the
- // task manager.
- task1PluginInstance.prologue();
- task1PluginInstance.epilogue();
- onSuspendHandlerContainer[1]();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManager3Tasks', function() {
- // Tests that 3 tasks can be executed too. In particular, that if the second
- // task is a single-step task which execution was originally blocked by task1,
- // unblocking it causes immediate synchronous execution of both tasks 2 and 3.
-
- // Setup.
- var test = setUpTaskManagerTest(this);
- var task1PluginInstance;
-
- // Step 1. Add 1st task that creates a pending callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1().
- will(callFunction(function() {
- task1PluginInstance = test.pluginFactory();
- }));
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Add 2nd and 3rd tasks, both non-conflicting (see
- // areTasksConflicting) with task1.
- test.tasks.add(taskNameC, this.mockLocalFunctions.functions().task2);
- test.tasks.add(taskNameC, this.mockLocalFunctions.functions().task3);
- Mock4JS.verifyAllMocks();
-
- // Step 3. Enter the callback of task1.
- task1PluginInstance.prologue();
- Mock4JS.verifyAllMocks();
-
- // Step 4. Leave the callback of task1.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task2();
- this.mockLocalFunctions.expects(once()).task3();
- // Invocation.
- task1PluginInstance.epilogue();
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerNestedNonTask', function() {
- // Tests callbacks requested while a task is running, but not from a callback
- // belonging to a task, are not counted as a part of the task.
-
- // Setup.
- var test = setUpTaskManagerTest(this);
- var task1PluginInstance;
-
- // Step 1. Add 1st task that creates a pending callback.
- // Expectations.
- this.mockLocalFunctions.expects(once()).task1().
- will(callFunction(function() {
- task1PluginInstance = test.pluginFactory();
- }));
- // Invocation.
- test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Create a pending callback from code that is not a part of the task.
- test.pluginFactory();
- Mock4JS.verifyAllMocks();
-
- // Step 3. Enter the callback of task1. After this, task1 should be
- // finished despite the pending non-task callback.
- task1PluginInstance.prologue();
- task1PluginInstance.epilogue();
- Mock4JS.verifyAllMocks();
-
- // Step 4. Check that task1 is finished by submitting task2, which should
- // be executed immediately.
- this.mockLocalFunctions.expects(once()).task2();
- test.tasks.add(taskNameC, this.mockLocalFunctions.functions().task2);
-});
-
-var testAttemptAlarmName = 'attempt-scheduler-testAttempts';
-var testAttemptStorageKey = 'current-delay-testAttempts';
-var testInitialDelaySeconds = 239;
-var testMaximumDelaySeconds = 2239;
-// Value to be returned by mocked Math.random(). We want the value returned by
-// Math.random() to be predictable to be able to check results against expected
-// values. A fixed seed would be okay, but fixed seeding isn't possible in JS at
-// the moment.
-var testRandomValue = 0.31415926;
-
-/**
- * Creates a default storage current delay object.
- */
-function createTestAttemptStorageEntryRequest() {
- var storageObject = {};
- storageObject[testAttemptStorageKey] = undefined;
- return storageObject;
-}
-
-/**
- * Creates a test storage object that attempt manager uses to store current
- * delay.
- */
-function createTestAttemptStorageEntry(delaySeconds) {
- var storageObject = {};
- storageObject[testAttemptStorageKey] = delaySeconds;
- return storageObject;
-}
-
-function setupAttemptManagerTest(fixture) {
- Math.random = function() { return testRandomValue; }
-
- fixture.makeMockLocalFunctions([
- 'attempt',
- 'isRunningCallback'
- ]);
- fixture.makeAndRegisterMockApis([
- 'chrome.alarms.clear',
- 'chrome.alarms.create',
- 'chrome.storage.local.remove',
- 'chrome.storage.local.set',
- 'fillFromChromeLocalStorage',
- 'instrumented.alarms.get'
- ]);
-
- var testAttempts = buildAttemptManager(
- 'testAttempts',
- fixture.mockLocalFunctions.functions().attempt,
- testInitialDelaySeconds,
- testMaximumDelaySeconds);
- Mock4JS.verifyAllMocks();
-
- return {
- attempts: testAttempts
- };
-}
-
-TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerStartStop', function() {
- // Tests starting and stopping an attempt manager.
-
- // Setup.
- var test = setupAttemptManagerTest(this);
-
- // Step 1. Check that attempt manager is not running.
- // Expectations.
- var alarmsGetSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_alarms_get(
- alarmsGetSavedArgs.match(eq(testAttemptAlarmName)),
- alarmsGetSavedArgs.match(ANYTHING)).
- will(invokeCallback(alarmsGetSavedArgs, 1, undefined));
- this.mockLocalFunctions.expects(once()).isRunningCallback(false);
- // Invocation.
- test.attempts.isRunning(
- this.mockLocalFunctions.functions().isRunningCallback);
- Mock4JS.verifyAllMocks();
-
- // Step 2. Start attempt manager with no parameters.
- // Expectations.
- var expectedRetryDelaySeconds =
- testInitialDelaySeconds * (1 + testRandomValue * 0.2);
- this.mockApis.expects(once()).chrome_alarms_create(
- testAttemptAlarmName,
- eqJSON({
- delayInMinutes: expectedRetryDelaySeconds / 60,
- periodInMinutes: testMaximumDelaySeconds / 60
- }));
- this.mockApis.expects(once()).chrome_storage_local_set(
- eqJSON(createTestAttemptStorageEntry(expectedRetryDelaySeconds)));
- // Invocation.
- test.attempts.start();
- Mock4JS.verifyAllMocks();
-
- // Step 3. Check that attempt manager is running.
- // Expectations.
- alarmsGetSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_alarms_get(
- alarmsGetSavedArgs.match(eq(testAttemptAlarmName)),
- alarmsGetSavedArgs.match(ANYTHING)).
- will(invokeCallback(alarmsGetSavedArgs, 1, {testField: 'TEST VALUE'}));
- this.mockLocalFunctions.expects(once()).isRunningCallback(true);
- // Invocation.
- test.attempts.isRunning(
- this.mockLocalFunctions.functions().isRunningCallback);
- Mock4JS.verifyAllMocks();
-
- // Step 4. Stop task manager.
- // Expectations.
- this.mockApis.expects(once()).chrome_alarms_clear(testAttemptAlarmName);
- this.mockApis.expects(once()).chrome_storage_local_remove(
- testAttemptStorageKey);
- // Invocation.
- test.attempts.stop();
-});
-
-TEST_F(
- 'GoogleNowUtilityUnitTest',
- 'AttemptManagerStartWithDelayParam',
- function() {
- // Tests starting an attempt manager with a delay parameter.
-
- // Setup.
- var test = setupAttemptManagerTest(this);
- var testFirstDelaySeconds = 1039;
-
- // Starting attempt manager with a parameter specifying first delay.
- // Expectations.
- this.mockApis.expects(once()).chrome_alarms_create(
- testAttemptAlarmName,
- eqJSON({
- delayInMinutes: testFirstDelaySeconds / 60,
- periodInMinutes: testMaximumDelaySeconds / 60
- }));
- this.mockApis.expects(once()).chrome_storage_local_remove(
- testAttemptStorageKey);
- // Invocation.
- test.attempts.start(testFirstDelaySeconds);
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerExponGrowth', function() {
- // Tests that retry time grows exponentially. We don't need to check the case
- // of growing more than once, since the object doesn't have state, and the
- // test checks all its inputs and outputs of the tested code.
-
- // Setup.
- var test = setupAttemptManagerTest(this);
- var testStoredRetryDelay = 433;
-
- // Call scheduleRetry, which schedules a retry.
- // Current retry time is less than 1/2 of the maximum delay.
- // Expectations.
- var expectedRetryDelaySeconds =
- testStoredRetryDelay * 2 * (1 + testRandomValue * 0.2);
- expectChromeLocalStorageGet(
- this,
- createTestAttemptStorageEntryRequest(),
- createTestAttemptStorageEntry(testStoredRetryDelay),
- true);
- this.mockApis.expects(once()).chrome_alarms_create(
- testAttemptAlarmName,
- eqJSON({
- delayInMinutes: expectedRetryDelaySeconds / 60,
- periodInMinutes: testMaximumDelaySeconds / 60}));
- this.mockApis.expects(once()).chrome_storage_local_set(
- eqJSON(createTestAttemptStorageEntry(expectedRetryDelaySeconds)));
- // Invocation.
- var thenCalled = false;
- var catchCalled = false;
- test.attempts.scheduleRetry().then(function(request) {
- thenCalled = true;
- }).catch(function(request) {
- catchCalled = true;
- });
- assertTrue(thenCalled);
- assertFalse(catchCalled);
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerGrowthLimit', function() {
- // Tests that retry time stops growing at the maximum value.
-
- // Setup.
- var test = setupAttemptManagerTest(this);
- var testStoredRetryDelay = 1500;
-
- // Call scheduleRetry, which schedules a retry.
- // Current retry time is greater than 1/2 of the maximum delay.
- // Expectations.
- var expectedRetryDelaySeconds =
- testMaximumDelaySeconds * (1 + testRandomValue * 0.2);
- expectChromeLocalStorageGet(
- this,
- createTestAttemptStorageEntryRequest(),
- createTestAttemptStorageEntry(testStoredRetryDelay),
- true);
- this.mockApis.expects(once()).chrome_alarms_create(
- testAttemptAlarmName,
- eqJSON({
- delayInMinutes: expectedRetryDelaySeconds / 60,
- periodInMinutes: testMaximumDelaySeconds / 60
- }));
- this.mockApis.expects(once()).chrome_storage_local_set(
- eqJSON(createTestAttemptStorageEntry(expectedRetryDelaySeconds)));
- // Invocation.
- var thenCalled = false;
- var catchCalled = false;
- test.attempts.scheduleRetry().then(function(request) {
- thenCalled = true;
- }).catch(function(request) {
- catchCalled = true;
- });
- assertTrue(thenCalled);
- assertFalse(catchCalled);
-});
-
-TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerAlarm', function() {
- // Tests that firing the alarm invokes the attempt.
-
- // Setup.
- var test = setupAttemptManagerTest(this);
- var onAlarmHandlerContainer = getMockHandlerContainer('alarms.onAlarm');
- assertEquals(1, onAlarmHandlerContainer.length);
-
- // Fire the alarm and check that this invokes the attempt callback.
- // Expectations.
- var alarmsGetSavedArgs = new SaveMockArguments();
- this.mockApis.expects(once()).
- instrumented_alarms_get(
- alarmsGetSavedArgs.match(eq(testAttemptAlarmName)),
- alarmsGetSavedArgs.match(ANYTHING)).
- will(invokeCallback(alarmsGetSavedArgs, 1, {testField: 'TEST VALUE'}));
- this.mockLocalFunctions.expects(once()).attempt();
- // Invocation.
- onAlarmHandlerContainer[0]({name: testAttemptAlarmName});
-});
diff --git a/chromium/chrome/browser/resources/hangout_services/manifest.json b/chromium/chrome/browser/resources/hangout_services/manifest.json
index ee976903196..125134723db 100644
--- a/chromium/chrome/browser/resources/hangout_services/manifest.json
+++ b/chromium/chrome/browser/resources/hangout_services/manifest.json
@@ -5,7 +5,7 @@
"name": "Google Hangouts",
// Note: Always update the version number when this file is updated. Chrome
// triggers extension preferences update on the version increase.
- "version": "1.3.2",
+ "version": "1.3.3",
"manifest_version": 2,
"externally_connectable": {
"matches": [
diff --git a/chromium/chrome/browser/resources/hangout_services/thunk.js b/chromium/chrome/browser/resources/hangout_services/thunk.js
index 68c28bf7dc5..2278a65d129 100644
--- a/chromium/chrome/browser/resources/hangout_services/thunk.js
+++ b/chromium/chrome/browser/resources/hangout_services/thunk.js
@@ -202,6 +202,12 @@ chrome.runtime.onMessageExternal.addListener(
chrome.webrtcLoggingPrivate.stopWebRtcEventLogging(
requestInfo, origin, doSendResponse);
return true;
+ } else if (method == 'setAudioExperiments') {
+ var experiments = message['experiments'];
+ chrome.webrtcAudioPrivate.setAudioExperiments(
+ requestInfo, origin, experiments);
+ doSendResponse();
+ return false;
}
throw new Error('Unknown method: ' + method);
diff --git a/chromium/chrome/browser/resources/local_ntp/most_visited_single.js b/chromium/chrome/browser/resources/local_ntp/most_visited_single.js
index 848ec2eeaf3..9eb0b16a6e9 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_single.js
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -28,11 +28,11 @@ var LOG_TYPE = {
/**
* The different sources that an NTP tile can have.
- * Note: Keep in sync with components/ntp_tiles/ntp_tile_source.h
+ * Note: Keep in sync with components/ntp_tiles/tile_source.h
* @enum {number}
* @const
*/
-var NTPTileSource = {
+var TileSource = {
TOP_SITES: 0,
SUGGESTIONS_SERVICE: 1,
POPULAR: 3,
@@ -41,6 +41,22 @@ var NTPTileSource = {
/**
+ * The different (visual) types that an NTP tile can have.
+ * Note: Keep in sync with components/ntp_tiles/tile_visual_type.h
+ * @enum {number}
+ * @const
+ */
+var TileVisualType = {
+ NONE: 0,
+ ICON_REAL: 1,
+ ICON_COLOR: 2,
+ ICON_DEFAULT: 3,
+ THUMBNAIL: 7,
+ THUMBNAIL_FAILED: 8,
+};
+
+
+/**
* Total number of tiles to show at any time. If the host page doesn't send
* enough tiles, we fill them blank.
* @const {number}
@@ -96,21 +112,25 @@ var logEvent = function(eventType) {
/**
* Log impression of an NTP tile.
* @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES.
- * @param {number} tileSource The source from NTPTileSource.
+ * @param {number} tileSource The source from TileSource.
+ * @param {number} tileType The type from TileVisualType.
*/
-function logMostVisitedImpression(tileIndex, tileSource) {
+function logMostVisitedImpression(tileIndex, tileSource, tileType) {
chrome.embeddedSearch.newTabPage.logMostVisitedImpression(tileIndex,
- tileSource);
+ tileSource,
+ tileType);
}
/**
* Log click on an NTP tile.
* @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES.
- * @param {number} tileSource The source from NTPTileSource.
+ * @param {number} tileSource The source from TileSource.
+ * @param {number} tileType The type from TileVisualType.
*/
-function logMostVisitedNavigation(tileIndex, tileSource) {
+function logMostVisitedNavigation(tileIndex, tileSource, tileType) {
chrome.embeddedSearch.newTabPage.logMostVisitedNavigation(tileIndex,
- tileSource);
+ tileSource,
+ tileType);
}
/**
@@ -317,7 +337,7 @@ var addTile = function(args) {
tiles.appendChild(renderTile(data));
} else if (args.url) {
// If a URL is passed: a server-side suggestion.
- args.tileSource = NTPTileSource.SUGGESTIONS_SERVICE;
+ args.tileSource = TileSource.SUGGESTIONS_SERVICE;
// check sanity of the arguments
if (/^javascript:/i.test(args.url) ||
/^javascript:/i.test(args.thumbnailUrl))
@@ -371,7 +391,9 @@ var renderTile = function(data) {
// The tile will be appended to tiles.
var position = tiles.children.length;
- logMostVisitedImpression(position, data.tileSource);
+
+ // This is set in the load/error event for the thumbnail image.
+ var tileType = TileVisualType.NONE;
tile.className = 'mv-tile';
tile.setAttribute('data-tid', data.tid);
@@ -389,7 +411,7 @@ var renderTile = function(data) {
tile.title = data.title;
tile.addEventListener('click', function(ev) {
- logMostVisitedNavigation(position, data.tileSource);
+ logMostVisitedNavigation(position, data.tileSource, tileType);
});
tile.addEventListener('keydown', function(event) {
@@ -441,88 +463,31 @@ var renderTile = function(data) {
title.classList.add('multiline');
}
- // We keep track of the outcome of loading possible thumbnails for this
- // tile. Possible values:
- // - null: waiting for load/error
- // - false: error
- // - a string: URL that loaded correctly.
- // This is populated by imageLoaded/imageLoadFailed, and selectBestImage
- // selects the best one to display.
- var results = [];
var thumb = tile.querySelector('.mv-thumb');
var img = document.createElement('img');
- var loaded = false;
-
- var selectBestImage = function() {
- if (loaded) {
- return;
- }
- // |results| is ordered from best candidate to worst.
- for (var i = 0; i < results.length; ++i) {
- if (results[i] === null) {
- // A better candidate is still waiting to be loaded; defer.
- return;
- }
- if (results[i] != false) {
- // This is the best (non-failed) candidate. Use it!
- img.src = results[i];
- loaded = true;
- return;
- }
- }
- // If we get here, then all candidates failed to load.
- thumb.classList.add('failed-img');
- thumb.removeChild(img);
- // Usually we count the load once the img element gets either a 'load' or
- // an 'error' event. Since we have removed the img element, instead count
- // the load here.
- countLoad();
- };
-
- var imageLoaded = function(idx, url) {
- return function(ev) {
- results[idx] = url;
- selectBestImage();
- };
- };
-
- var imageLoadFailed = function(idx) {
- return function(ev) {
- results[idx] = false;
- selectBestImage();
- };
- };
-
img.title = data.title;
+ img.src = data.thumbnailUrl;
loadedCounter += 1;
- img.addEventListener('load', countLoad);
- img.addEventListener('error', countLoad);
+ img.addEventListener('load', function(ev) {
+ // Store the type for a potential later navigation.
+ tileType = TileVisualType.THUMBNAIL;
+ logMostVisitedImpression(position, data.tileSource, tileType);
+ // Note: It's important to call countLoad last, because that might emit the
+ // NTP_ALL_TILES_LOADED event, which must happen after the impression log.
+ countLoad();
+ });
img.addEventListener('error', function(ev) {
thumb.classList.add('failed-img');
thumb.removeChild(img);
+ // Store the type for a potential later navigation.
+ tileType = TileVisualType.THUMBNAIL_FAILED;
+ logMostVisitedImpression(position, data.tileSource, tileType);
+ // Note: It's important to call countLoad last, because that might emit the
+ // NTP_ALL_TILES_LOADED event, which must happen after the impression log.
+ countLoad();
});
thumb.appendChild(img);
- if (data.thumbnailUrl) {
- img.src = data.thumbnailUrl;
- } else {
- // Get all thumbnailUrls for the tile.
- // They are ordered from best one to be used to worst.
- for (var i = 0; i < data.thumbnailUrls.length; ++i) {
- results.push(null);
- }
- for (var i = 0; i < data.thumbnailUrls.length; ++i) {
- if (data.thumbnailUrls[i]) {
- var image = new Image();
- image.src = data.thumbnailUrls[i];
- image.onload = imageLoaded(i, data.thumbnailUrls[i]);
- image.onerror = imageLoadFailed(i);
- } else {
- imageLoadFailed(i)(/*ev=*/null);
- }
- }
- }
-
var favicon = tile.querySelector('.mv-favicon');
if (data.faviconUrl) {
var fi = document.createElement('img');
diff --git a/chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js b/chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js
index 6334ebde671..54a5e337b57 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js
@@ -58,8 +58,8 @@ window.addEventListener('DOMContentLoaded', function() {
if (data.dummy) {
showEmptyTile();
- } else if (data.thumbnailUrls && data.thumbnailUrls.length) {
- createThumbnail(data.thumbnailUrls[0], 'thumbnail');
+ } else if (data.thumbnailUrl) {
+ createThumbnail(data.thumbnailUrl, 'thumbnail');
} else if (data.domain) {
showDomainElement();
} else {
diff --git a/chromium/chrome/browser/resources/local_ntp/most_visited_util.js b/chromium/chrome/browser/resources/local_ntp/most_visited_util.js
index 5620d5f0246..d7dc58d868b 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_util.js
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_util.js
@@ -7,10 +7,24 @@
* @fileoverview Utilities for rendering most visited thumbnails and titles.
*/
+// Don't remove; see crbug.com/678778.
// <include src="instant_iframe_validation.js">
/**
+ * The different types of events that are logged from the NTP. The multi-iframe
+ * version of the NTP does *not* actually log any statistics anymore; this is
+ * only required as a workaround for crbug.com/698675.
+ * Note: Keep in sync with common/ntp_logging_events.h
+ * @enum {number}
+ * @const
+ */
+var NTP_LOGGING_EVENT_TYPE = {
+ NTP_ALL_TILES_RECEIVED: 12,
+};
+
+
+/**
* The origin of this request.
* @const {string}
*/
@@ -212,6 +226,11 @@ function fillMostVisited(location, fill) {
};
} else {
var apiHandle = chrome.embeddedSearch.newTabPage;
+ // Note: This does not actually result in any logging; it's a workaround for
+ // crbug.com/698675. It effectively sets the "instant support" state of the
+ // tab to true, which makes later calls to fetch the most visited items
+ // succeed.
+ apiHandle.logEvent(NTP_LOGGING_EVENT_TYPE.NTP_ALL_TILES_RECEIVED);
data = apiHandle.getMostVisitedItemData(params.rid);
if (!data)
return;
diff --git a/chromium/chrome/browser/resources/md_bookmarks/OWNERS b/chromium/chrome/browser/resources/md_bookmarks/OWNERS
index 793f7b9dc7a..d0663e00c74 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/OWNERS
+++ b/chromium/chrome/browser/resources/md_bookmarks/OWNERS
@@ -1,3 +1,5 @@
calamity@chromium.org
dbeam@chromium.org
tsergeant@chromium.org
+
+# COMPONENT: UI>Browser>Bookmarks
diff --git a/chromium/chrome/browser/resources/md_bookmarks/actions.html b/chromium/chrome/browser/resources/md_bookmarks/actions.html
new file mode 100644
index 00000000000..0af2983bb35
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/actions.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://bookmarks/actions.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/actions.js b/chromium/chrome/browser/resources/md_bookmarks/actions.js
new file mode 100644
index 00000000000..9f6a63d11ab
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/actions.js
@@ -0,0 +1,215 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Module for functions which produce action objects. These are
+ * listed in one place to document available actions and their parameters.
+ */
+
+cr.define('bookmarks.actions', function() {
+ /**
+ * @param {string} id
+ * @param {BookmarkTreeNode} treeNode
+ */
+ function createBookmark(id, treeNode) {
+ return {
+ name: 'create-bookmark',
+ id: id,
+ parentId: treeNode.parentId,
+ parentIndex: treeNode.index,
+ node: bookmarks.util.normalizeNode(treeNode),
+ };
+ }
+
+ /**
+ * @param {string} id
+ * @param {{title: string, url: (string|undefined)}} changeInfo
+ * @return {!Action}
+ */
+ function editBookmark(id, changeInfo) {
+ return {
+ name: 'edit-bookmark',
+ id: id,
+ changeInfo: changeInfo,
+ };
+ }
+
+ /**
+ * @param {string} id
+ * @param {string} parentId
+ * @param {number} index
+ * @param {string} oldParentId
+ * @param {number} oldIndex
+ * @return {!Action}
+ */
+ function moveBookmark(id, parentId, index, oldParentId, oldIndex) {
+ return {
+ name: 'move-bookmark',
+ id: id,
+ parentId: parentId,
+ index: index,
+ oldParentId: oldParentId,
+ oldIndex: oldIndex,
+ };
+ }
+
+ /**
+ * @param {string} id
+ * @param {!Array<string>} newChildIds
+ */
+ function reorderChildren(id, newChildIds) {
+ return {
+ name: 'reorder-children',
+ id: id,
+ children: newChildIds,
+ };
+ }
+
+ /**
+ * @param {string} id
+ * @param {string} parentId
+ * @param {number} index
+ * @param {NodeList} nodes
+ * @return {!Action}
+ */
+ function removeBookmark(id, parentId, index, nodes) {
+ var descendants = bookmarks.util.getDescendants(nodes, id);
+ return {
+ name: 'remove-bookmark',
+ id: id,
+ descendants: descendants,
+ parentId: parentId,
+ index: index,
+ };
+ }
+
+ /**
+ * @param {NodeList} nodeMap
+ * @return {!Action}
+ */
+ function refreshNodes(nodeMap) {
+ return {
+ name: 'refresh-nodes',
+ nodes: nodeMap,
+ };
+ };
+
+ /**
+ * @param {string} id
+ * @return {!Action}
+ */
+ function selectFolder(id) {
+ assert(id != '0', 'Cannot select root folder');
+ return {
+ name: 'select-folder',
+ id: id,
+ };
+ }
+
+ /**
+ * @param {string} id
+ * @param {boolean} open
+ * @return {!Action}
+ */
+ function changeFolderOpen(id, open) {
+ return {
+ name: 'change-folder-open',
+ id: id,
+ open: open,
+ };
+ }
+
+ /** @return {!Action} */
+ function clearSearch() {
+ return {
+ name: 'clear-search',
+ };
+ }
+
+ /** @return {!Action} */
+ function deselectItems() {
+ return {
+ name: 'deselect-items',
+ };
+ }
+
+ /**
+ * @param {string} id
+ * @param {boolean} add
+ * @param {boolean} range
+ * @param {BookmarksPageState} state
+ * @return {!Action}
+ */
+ function selectItem(id, add, range, state) {
+ var anchor = state.selection.anchor;
+ var toSelect = [];
+
+ // TODO(tsergeant): Make it possible to deselect items by ctrl-clicking them
+ // again.
+ if (range && anchor) {
+ var displayedList = bookmarks.util.getDisplayedList(state);
+ var selectedIndex = displayedList.indexOf(id);
+ assert(selectedIndex != -1);
+ var anchorIndex = displayedList.indexOf(anchor);
+ if (anchorIndex == -1)
+ anchorIndex = selectedIndex;
+
+ var startIndex = Math.min(anchorIndex, selectedIndex);
+ var endIndex = Math.max(anchorIndex, selectedIndex);
+
+ for (var i = startIndex; i <= endIndex; i++)
+ toSelect.push(displayedList[i]);
+ } else {
+ toSelect.push(id);
+ }
+
+ return {
+ name: 'select-items',
+ add: add,
+ anchor: id,
+ items: toSelect,
+ };
+ }
+
+ /**
+ * @param {string} term
+ * @return {!Action}
+ */
+ function setSearchTerm(term) {
+ if (!term)
+ return clearSearch();
+
+ return {
+ name: 'start-search',
+ term: term,
+ };
+ }
+
+ /**
+ * @param {!Array<string>} ids
+ * @return {!Action}
+ */
+ function setSearchResults(ids) {
+ return {
+ name: 'finish-search',
+ results: ids,
+ };
+ }
+
+ return {
+ changeFolderOpen: changeFolderOpen,
+ clearSearch: clearSearch,
+ createBookmark: createBookmark,
+ deselectItems: deselectItems,
+ editBookmark: editBookmark,
+ moveBookmark: moveBookmark,
+ refreshNodes: refreshNodes,
+ removeBookmark: removeBookmark,
+ reorderChildren: reorderChildren,
+ selectFolder: selectFolder,
+ selectItem: selectItem,
+ setSearchResults: setSearchResults,
+ setSearchTerm: setSearchTerm,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/api_listener.html b/chromium/chrome/browser/resources/md_bookmarks/api_listener.html
new file mode 100644
index 00000000000..3fc0a5979ce
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/api_listener.html
@@ -0,0 +1,5 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://bookmarks/actions.html">
+<link rel="import" href="chrome://bookmarks/store.html">
+<link rel="import" href="chrome://bookmarks/util.html">
+<script src="chrome://bookmarks/api_listener.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/api_listener.js b/chromium/chrome/browser/resources/md_bookmarks/api_listener.js
new file mode 100644
index 00000000000..e65bc9391b6
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/api_listener.js
@@ -0,0 +1,94 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Listener functions which translate events from the
+ * chrome.bookmarks API into actions to modify the local page state.
+ */
+
+cr.define('bookmarks.ApiListener', function() {
+ /** @param {Action} action */
+ function dispatch(action) {
+ bookmarks.Store.getInstance().handleAction(action);
+ }
+
+ /**
+ * @param {string} id
+ * @param {{title: string, url: (string|undefined)}} changeInfo
+ */
+ function onBookmarkChanged(id, changeInfo) {
+ dispatch(bookmarks.actions.editBookmark(id, changeInfo));
+ }
+
+ /**
+ * @param {string} id
+ * @param {BookmarkTreeNode} treeNode
+ */
+ function onBookmarkCreated(id, treeNode) {
+ dispatch(bookmarks.actions.createBookmark(id, treeNode));
+ }
+
+ /**
+ * @param {string} id
+ * @param {{parentId: string, index: number}} removeInfo
+ */
+ function onBookmarkRemoved(id, removeInfo) {
+ var nodes = bookmarks.Store.getInstance().data.nodes;
+ dispatch(bookmarks.actions.removeBookmark(
+ id, removeInfo.parentId, removeInfo.index, nodes));
+ }
+
+ /**
+ * @param {string} id
+ * @param {{
+ * parentId: string,
+ * index: number,
+ * oldParentId: string,
+ * oldIndex: number
+ * }} moveInfo
+ */
+ function onBookmarkMoved(id, moveInfo) {
+ dispatch(bookmarks.actions.moveBookmark(
+ id, moveInfo.parentId, moveInfo.index, moveInfo.oldParentId,
+ moveInfo.oldIndex));
+ }
+
+ /**
+ * @param {string} id
+ * @param {{childIds: !Array<string>}} reorderInfo
+ */
+ function onChildrenReordered(id, reorderInfo) {
+ dispatch(bookmarks.actions.reorderChildren(id, reorderInfo.childIds));
+ }
+
+ /**
+ * Pauses the Created handler during an import. The imported nodes will all be
+ * loaded at once when the import is finished.
+ */
+ function onImportBegan() {
+ chrome.bookmarks.onCreated.removeListener(onBookmarkCreated);
+ }
+
+ function onImportEnded() {
+ chrome.bookmarks.getTree(function(results) {
+ dispatch(bookmarks.actions.refreshNodes(
+ bookmarks.util.normalizeNodes(results[0])));
+ });
+ chrome.bookmarks.onCreated.addListener(onBookmarkCreated);
+ }
+
+ function init() {
+ chrome.bookmarks.onChanged.addListener(onBookmarkChanged);
+ chrome.bookmarks.onChildrenReordered.addListener(onChildrenReordered);
+ chrome.bookmarks.onCreated.addListener(onBookmarkCreated);
+ chrome.bookmarks.onMoved.addListener(onBookmarkMoved);
+ chrome.bookmarks.onRemoved.addListener(onBookmarkRemoved);
+ chrome.bookmarks.onImportBegan.addListener(onImportBegan);
+ chrome.bookmarks.onImportEnded.addListener(onImportEnded);
+ }
+
+ return {
+ init: init,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/app.html b/chromium/chrome/browser/resources/md_bookmarks/app.html
index 3c1b115a26e..35229aeb64e 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/app.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/app.html
@@ -1,9 +1,15 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/cr/ui/splitter.html">
+<link rel="import" href="chrome://bookmarks/api_listener.html">
+<link rel="import" href="chrome://bookmarks/constants.html">
+<link rel="import" href="chrome://bookmarks/dnd_manager.html">
<link rel="import" href="chrome://bookmarks/list.html">
+<link rel="import" href="chrome://bookmarks/router.html">
<link rel="import" href="chrome://bookmarks/shared_vars.html">
<link rel="import" href="chrome://bookmarks/sidebar.html">
<link rel="import" href="chrome://bookmarks/store.html">
<link rel="import" href="chrome://bookmarks/toolbar.html">
+<link rel="import" href="chrome://bookmarks/util.html">
<dom-module id="bookmarks-app">
<template>
@@ -12,7 +18,6 @@
display: flex;
flex-direction: column;
height: 100%;
- overflow: hidden;
}
#main-container {
@@ -22,26 +27,33 @@
overflow: auto;
}
+ #splitter {
+ cursor: e-resize;
+ flex: 0 0 var(--splitter-width);
+ }
+
+ :host-context([dir='rtl']) #splitter {
+ cursor: w-resize;
+ }
+
bookmarks-sidebar {
- flex: 0 0 var(--sidebar-width);
+ max-width: 40%;
+ min-width: var(--min-sidebar-width);
+ width: var(--min-sidebar-width);
}
bookmarks-list {
flex: 1;
+ min-width: 550px;
}
</style>
- <bookmarks-toolbar search-term="[[searchTerm]]"></bookmarks-toolbar>
+ <bookmarks-toolbar sidebar-width="[[sidebarWidth_]]"></bookmarks-toolbar>
<div id="main-container">
- <bookmarks-sidebar root-folders="[[rootNode.children]]">
- </bookmarks-sidebar>
- <bookmarks-list displayed-list="[[displayedList]]"
- search-term="[[searchTerm]]"></bookmarks-list>
+ <bookmarks-sidebar id="sidebar"></bookmarks-sidebar>
+ <div id="splitter"></div>
+ <bookmarks-list></bookmarks-list>
</div>
- <bookmarks-store selected-id="{{selectedId}}"
- root-node="{{rootNode}}"
- search-term="{{searchTerm}}"
- displayed-list="{{displayedList}}">
- </bookmarks-store>
+ <bookmarks-router></bookmarks-router>
</template>
<script src="chrome://bookmarks/app.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/app.js b/chromium/chrome/browser/resources/md_bookmarks/app.js
index 89d6310e5ff..ed59f5e4024 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/app.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/app.js
@@ -5,21 +5,120 @@
Polymer({
is: 'bookmarks-app',
- properties: {
- selectedId: String,
+ behaviors: [
+ bookmarks.StoreClient,
+ ],
- /** @type {BookmarkTreeNode} */
- rootNode: Object,
+ properties: {
+ /** @private */
+ searchTerm_: {
+ type: String,
+ observer: 'searchTermChanged_',
+ },
- searchTerm: String,
+ /** @type {ClosedFolderState} */
+ closedFoldersState_: {
+ type: Object,
+ observer: 'closedFoldersStateChanged_',
+ },
- /** @type {Array<BookmarkTreeNode>} */
- displayedList: Array,
+ /** @private */
+ sidebarWidth_: String,
},
+ /** @private{?function(!Event)} */
+ boundUpdateSidebarWidth_: null,
+
+ /** @private {bookmarks.DNDManager} */
+ dndManager_: null,
+
/** @override */
attached: function() {
- /** @type {BookmarksStore} */ (this.$$('bookmarks-store'))
- .initializeStore();
+ this.watch('searchTerm_', function(store) {
+ return store.search.term;
+ });
+
+ this.watch('closedFoldersState_', function(store) {
+ return store.closedFolders;
+ });
+
+ chrome.bookmarks.getTree(function(results) {
+ var nodeList = bookmarks.util.normalizeNodes(results[0]);
+ var initialState = bookmarks.util.createEmptyState();
+ initialState.nodes = nodeList;
+ initialState.selectedFolder = nodeList[ROOT_NODE_ID].children[0];
+ var closedFoldersString =
+ window.localStorage[LOCAL_STORAGE_CLOSED_FOLDERS_KEY];
+ initialState.closedFolders = closedFoldersString ?
+ new Set(
+ /** @type Array<string> */ (JSON.parse(closedFoldersString))) :
+ new Set();
+
+ bookmarks.Store.getInstance().init(initialState);
+ bookmarks.ApiListener.init();
+
+ }.bind(this));
+
+ this.boundUpdateSidebarWidth_ = this.updateSidebarWidth_.bind(this);
+
+ this.initializeSplitter_();
+
+ this.dndManager_ = new bookmarks.DNDManager();
+ this.dndManager_.init();
+ },
+
+ detached: function() {
+ window.removeEventListener('resize', this.boundUpdateSidebarWidth_);
+ this.dndManager_.destroy();
+ },
+
+ /**
+ * Set up the splitter and set the initial width from localStorage.
+ * @private
+ */
+ initializeSplitter_: function() {
+ var splitter = this.$.splitter;
+ cr.ui.Splitter.decorate(splitter);
+ var splitterTarget = this.$.sidebar;
+
+ // The splitter persists the size of the left component in the local store.
+ if (LOCAL_STORAGE_TREE_WIDTH_KEY in window.localStorage) {
+ splitterTarget.style.width =
+ window.localStorage[LOCAL_STORAGE_TREE_WIDTH_KEY];
+ }
+ this.sidebarWidth_ = splitterTarget.getComputedStyleValue('width');
+
+ splitter.addEventListener('resize', function(e) {
+ window.localStorage[LOCAL_STORAGE_TREE_WIDTH_KEY] =
+ splitterTarget.style.width;
+ this.updateSidebarWidth_();
+ }.bind(this));
+
+ splitter.addEventListener('dragmove', this.boundUpdateSidebarWidth_);
+ window.addEventListener('resize', this.boundUpdateSidebarWidth_);
+ },
+
+ /** @private */
+ updateSidebarWidth_: function() {
+ this.sidebarWidth_ = this.$.sidebar.getComputedStyleValue('width');
+ },
+
+ /** @private */
+ searchTermChanged_: function() {
+ if (!this.searchTerm_)
+ return;
+
+ chrome.bookmarks.search(this.searchTerm_, function(results) {
+ var ids = results.map(function(node) {
+ return node.id;
+ });
+ this.dispatch(bookmarks.actions.setSearchResults(ids));
+ }.bind(this));
+ },
+
+ /** @private */
+ closedFoldersStateChanged_: function() {
+ window.localStorage[LOCAL_STORAGE_CLOSED_FOLDERS_KEY] =
+ JSON.stringify(Array.from(this.closedFoldersState_));
},
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
index a263751835f..582f84a2252 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
@@ -4,19 +4,74 @@
{
'targets': [
{
+ 'target_name': 'actions',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'util',
+ 'types',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
+ },
+ {
+ 'target_name': 'api_listener',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'actions',
+ 'store',
+ 'util',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'app',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:splitter',
'<(EXTERNS_GYP):chrome_extensions',
- 'store'
+ 'api_listener',
+ 'dnd_manager',
+ 'router',
+ 'store',
+ 'store_client',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'constants',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
+ },
+ {
+ 'target_name': 'dnd_manager',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):bookmark_manager_private',
+ '<(EXTERNS_GYP):metrics_private',
+ 'store',
+ 'types',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
+ },
+ {
+ 'target_name': 'edit_dialog',
+ 'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'types',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
+ },
+ {
'target_name': 'folder_node',
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
'dependencies': [
'<(EXTERNS_GYP):chrome_extensions',
- 'store'
+ 'actions',
+ 'store_client',
],
},
{
@@ -24,6 +79,8 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
'<(EXTERNS_GYP):chrome_extensions',
+ 'actions',
+ 'store_client',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -32,28 +89,54 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
- '<(EXTERNS_GYP):bookmark_manager_private',
- '<(EXTERNS_GYP):chrome_extensions',
- 'item',
+ '<(EXTERNS_GYP):bookmark_manager_private',
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'actions',
+ 'edit_dialog',
+ 'store_client',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'reducers',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ 'actions',
+ 'types',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'router',
+ 'dependencies': [
+ 'actions',
+ 'store_client',
+ ],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'sidebar',
'dependencies': [
- 'folder_node',
+ 'store_client',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'store',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(EXTERNS_GYP):chrome_extensions',
- 'router',
+ 'reducers',
+ 'types',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
+ },
+ {
+ 'target_name': 'store_client',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ 'store',
+ 'types',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
},
@@ -62,9 +145,29 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
'<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar',
+ '<(EXTERNS_GYP):bookmark_manager_private',
'<(EXTERNS_GYP):chrome_extensions',
+ 'edit_dialog',
+ 'store_client',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'types',
+ 'dependencies': [
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'constants',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
+ },
+ {
+ 'target_name': 'util',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):chrome_extensions',
+ 'types',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
+ }
]
}
diff --git a/chromium/chrome/browser/resources/md_bookmarks/constants.html b/chromium/chrome/browser/resources/md_bookmarks/constants.html
new file mode 100644
index 00000000000..45f3cb541dd
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/constants.html
@@ -0,0 +1 @@
+<script src="chrome://bookmarks/constants.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/constants.js b/chromium/chrome/browser/resources/md_bookmarks/constants.js
new file mode 100644
index 00000000000..95949765783
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/constants.js
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Enumeration of valid drop locations relative to an element. These are
+ * bit masks to allow combining multiple locations in a single value.
+ * @enum {number}
+ * @const
+ */
+var DropPosition = {
+ NONE: 0,
+ ABOVE: 1,
+ ON: 2,
+ BELOW: 4,
+};
+
+/** @const */
+var LOCAL_STORAGE_CLOSED_FOLDERS_KEY = 'closedState';
+
+/** @const */
+var LOCAL_STORAGE_TREE_WIDTH_KEY = 'treeWidth';
+
+/** @const */
+var ROOT_NODE_ID = '0';
diff --git a/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html
new file mode 100644
index 00000000000..0a87bf04183
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://bookmarks/constants.html">
+<script src="chrome://bookmarks/dnd_manager.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js
new file mode 100644
index 00000000000..9f3d08988d5
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js
@@ -0,0 +1,624 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('bookmarks', function() {
+ /**
+ * @param {BookmarkElement} element
+ * @return {boolean}
+ */
+ function isBookmarkItem(element) {
+ return element.tagName == 'BOOKMARKS-ITEM';
+ }
+
+ /**
+ * @param {BookmarkElement} element
+ * @return {boolean}
+ */
+ function isBookmarkFolderNode(element) {
+ return element.tagName == 'BOOKMARKS-FOLDER-NODE';
+ }
+
+ /**
+ * @param {BookmarkElement} element
+ * @return {boolean}
+ */
+ function isBookmarkList(element) {
+ return element.tagName == 'BOOKMARKS-LIST';
+ }
+
+ /**
+ * @param {Array<!Element>|undefined} path
+ * @return {BookmarkElement}
+ */
+ function getBookmarkElement(path) {
+ if (!path)
+ return null;
+
+ for (var i = 0; i < path.length; i++) {
+ if (isBookmarkItem(path[i]) || isBookmarkFolderNode(path[i]) ||
+ isBookmarkList(path[i]))
+ return path[i];
+ }
+ return null;
+ }
+
+ /**
+ * @param {BookmarkElement} bookmarkElement
+ * @return {BookmarkNode}
+ */
+ function getBookmarkNode(bookmarkElement) {
+ return bookmarks.Store.getInstance().data.nodes[bookmarkElement.itemId];
+ }
+
+ /**
+ * Contains and provides utility methods for drag data sent by the
+ * bookmarkManagerPrivate API.
+ * @constructor
+ */
+ function DragInfo() {
+ /** @type {DragData} */
+ this.dragData = null;
+ }
+
+ DragInfo.prototype = {
+ /** @param {DragData} newDragData */
+ handleChromeDragEnter: function(newDragData) {
+ this.dragData = newDragData;
+ },
+
+ clearDragData: function() {
+ this.dragData = null;
+ },
+
+ /** @return {boolean} */
+ isDragValid: function() {
+ return !!this.dragData;
+ },
+
+ /** @return {boolean} */
+ isSameProfile: function() {
+ return !!this.dragData && this.dragData.sameProfile;
+ },
+
+ /** @return {boolean} */
+ isDraggingFolders: function() {
+ return !!this.dragData && this.dragData.elements.some(function(node) {
+ return !node.url;
+ });
+ },
+
+ /** @return {boolean} */
+ isDraggingBookmark: function(bookmarkId) {
+ return !!this.dragData && this.isSameProfile() &&
+ this.dragData.elements.some(function(node) {
+ return node.id == bookmarkId;
+ });
+ },
+
+ /** @return {boolean} */
+ isDraggingChildBookmark: function(folderId) {
+ return !!this.dragData && this.isSameProfile() &&
+ this.dragData.elements.some(function(node) {
+ return node.parentId == folderId;
+ });
+ },
+
+ /** @return {boolean} */
+ isDraggingFolderToDescendant: function(itemId, nodes) {
+ if (!this.isSameProfile())
+ return false;
+
+ var parentId = nodes[itemId].parentId;
+ var parents = {};
+ while (parentId) {
+ parents[parentId] = true;
+ parentId = nodes[parentId].parentId;
+ }
+
+ return !!this.dragData && this.dragData.elements.some(function(node) {
+ return parents[node.id];
+ });
+ },
+ };
+
+
+ /**
+ * Manages auto expanding of sidebar folders on hover while dragging.
+ * @constructor
+ */
+ function AutoExpander() {
+ /** @const {number} */
+ this.EXPAND_FOLDER_DELAY = 400;
+
+ /** @private {number} */
+ this.lastTimestamp_ = 0;
+
+ /** @private {BookmarkElement|null} */
+ this.lastElement_ = null;
+
+ /** @private {number} */
+ this.testTimestamp_ = 0;
+ }
+
+ AutoExpander.prototype = {
+ /**
+ * @param {Event} e
+ * @param {?BookmarkElement} overElement
+ */
+ update: function(e, overElement) {
+ var eventTimestamp = this.testTimestamp_ || e.timeStamp;
+ var itemId = overElement ? overElement.itemId : null;
+ var store = bookmarks.Store.getInstance();
+
+ // If hovering over the same folder as last update, open the folder after
+ // the delay has passed.
+ if (overElement && overElement == this.lastElement_) {
+ if (eventTimestamp - this.lastTimestamp_ < this.EXPAND_FOLDER_DELAY)
+ return;
+
+ var action = bookmarks.actions.changeFolderOpen(itemId, true);
+ store.handleAction(action);
+ } else if (
+ overElement && isBookmarkFolderNode(overElement) &&
+ bookmarks.util.hasChildFolders(itemId, store.data.nodes) &&
+ store.data.closedFolders.has(itemId)) {
+ // Since this is a closed folder node that has children, set the auto
+ // expander to this element.
+ this.lastTimestamp_ = eventTimestamp;
+ this.lastElement_ = overElement;
+ return;
+ }
+
+ // If the folder has been expanded or we have moved to a different
+ // element, reset the auto expander.
+ this.lastTimestamp_ = 0;
+ this.lastElement_ = null;
+ },
+ };
+
+ /**
+ * Encapsulates the behavior of the drag and drop indicator which puts a line
+ * between items or highlights folders which are valid drop targets.
+ * @constructor
+ */
+ function DropIndicator() {
+ /**
+ * @private {number|null} Timer id used to help minimize flicker.
+ */
+ this.removeDropIndicatorTimer_ = null;
+
+ /**
+ * The element that had a style applied it to indicate the drop location.
+ * This is used to easily remove the style when necessary.
+ * @private {BookmarkElement|null}
+ */
+ this.lastIndicatorElement_ = null;
+
+ /**
+ * The style that was applied to indicate the drop location.
+ * @private {?string|null}
+ */
+ this.lastIndicatorClassName_ = null;
+
+ /**
+ * Used to instantly remove the indicator style in tests.
+ * @private {function((Function|null|string), number)}
+ */
+ this.setTimeout_ = window.setTimeout.bind(window);
+ }
+
+ DropIndicator.prototype = {
+ /**
+ * Applies the drop indicator style on the target element and stores that
+ * information to easily remove the style in the future.
+ * @param {HTMLElement} indicatorElement
+ * @param {DropPosition} position
+ */
+ addDropIndicatorStyle: function(indicatorElement, position) {
+ var indicatorStyleName = position == DropPosition.ABOVE ?
+ 'drag-above' :
+ position == DropPosition.BELOW ? 'drag-below' : 'drag-on';
+
+ this.lastIndicatorElement_ = indicatorElement;
+ this.lastIndicatorClassName_ = indicatorStyleName;
+
+ indicatorElement.classList.add(indicatorStyleName);
+ },
+
+ /**
+ * Clears the drop indicator style from the last drop target.
+ */
+ removeDropIndicatorStyle: function() {
+ if (!this.lastIndicatorElement_ || !this.lastIndicatorClassName_)
+ return;
+
+ this.lastIndicatorElement_.classList.remove(this.lastIndicatorClassName_);
+ this.lastIndicatorElement_ = null;
+ this.lastIndicatorClassName_ = null;
+ },
+
+ /**
+ * Displays the drop indicator on the current drop target to give the
+ * user feedback on where the drop will occur.
+ * @param {DropDestination} dropDest
+ */
+ update: function(dropDest) {
+ window.clearTimeout(this.removeDropIndicatorTimer_);
+
+ var indicatorElement = dropDest.element.getDropTarget();
+ var position = dropDest.position;
+
+ this.removeDropIndicatorStyle();
+ this.addDropIndicatorStyle(indicatorElement, position);
+ },
+
+ /**
+ * Stop displaying the drop indicator.
+ */
+ finish: function() {
+ // The use of a timeout is in order to reduce flickering as we move
+ // between valid drop targets.
+ window.clearTimeout(this.removeDropIndicatorTimer_);
+ this.removeDropIndicatorTimer_ = this.setTimeout_(function() {
+ this.removeDropIndicatorStyle();
+ }.bind(this), 100);
+ },
+
+ disableTimeoutForTesting: function() {
+ this.setTimeout_ = function(fn, timeout) {
+ fn();
+ };
+ },
+ };
+
+ /**
+ * Manages drag and drop events for the bookmarks-app.
+ * @constructor
+ */
+ function DNDManager() {
+ /** @private {bookmarks.DragInfo} */
+ this.dragInfo_ = null;
+
+ /** @private {?DropDestination} */
+ this.dropDestination_ = null;
+
+ /** @private {bookmarks.DropIndicator} */
+ this.dropIndicator_ = null;
+
+ /** @private {Object<string, function(!Event)>} */
+ this.documentListeners_ = null;
+ }
+
+ DNDManager.prototype = {
+ init: function() {
+ this.dragInfo_ = new DragInfo();
+ this.dropIndicator_ = new DropIndicator();
+ this.autoExpander_ = new AutoExpander();
+
+ this.documentListeners_ = {
+ 'dragstart': this.onDragStart_.bind(this),
+ 'dragenter': this.onDragEnter_.bind(this),
+ 'dragover': this.onDragOver_.bind(this),
+ 'dragleave': this.onDragLeave_.bind(this),
+ 'drop': this.onDrop_.bind(this),
+ 'dragend': this.clearDragData_.bind(this),
+ 'mouseup': this.clearDragData_.bind(this),
+ // TODO(calamity): Add touch support.
+ };
+ for (var event in this.documentListeners_)
+ document.addEventListener(event, this.documentListeners_[event]);
+
+ chrome.bookmarkManagerPrivate.onDragEnter.addListener(
+ this.dragInfo_.handleChromeDragEnter.bind(this.dragInfo_));
+ chrome.bookmarkManagerPrivate.onDragLeave.addListener(
+ this.clearDragData_.bind(this));
+ chrome.bookmarkManagerPrivate.onDrop.addListener(
+ this.clearDragData_.bind(this));
+ },
+
+ destroy: function() {
+ for (var event in this.documentListeners_)
+ document.removeEventListener(event, this.documentListeners_[event]);
+ },
+
+ /** @private */
+ onDragLeave_: function() {
+ this.dropIndicator_.finish();
+ },
+
+ /**
+ * @private
+ * @param {!Event} e
+ */
+ onDrop_: function(e) {
+ if (this.dropDestination_) {
+ e.preventDefault();
+
+ var dropInfo = this.calculateDropInfo_(this.dropDestination_);
+ if (dropInfo.index != -1)
+ chrome.bookmarkManagerPrivate.drop(dropInfo.parentId, dropInfo.index);
+ else
+ chrome.bookmarkManagerPrivate.drop(dropInfo.parentId);
+ }
+
+ this.dropDestination_ = null;
+ this.dropIndicator_.finish();
+ },
+
+ /**
+ * @param {DropDestination} dropDestination
+ * @return {{parentId: string, index: number}}
+ */
+ calculateDropInfo_: function(dropDestination) {
+ if (isBookmarkList(dropDestination.element)) {
+ return {
+ index: 0,
+ parentId: bookmarks.Store.getInstance().data.selectedFolder,
+ };
+ }
+
+ var node = getBookmarkNode(dropDestination.element);
+ var position = dropDestination.position;
+ var index = -1;
+ var parentId = node.id;
+
+ if (position != DropPosition.ON) {
+ var state = bookmarks.Store.getInstance().data;
+
+ // Drops between items in the normal list and the sidebar use the drop
+ // destination node's parent.
+ parentId = assert(node.parentId);
+ index = state.nodes[parentId].children.indexOf(node.id);
+
+ // TODO(calamity): Handle dropping to an empty bookmark list.
+ if (position == DropPosition.BELOW)
+ index++;
+ }
+
+ return {
+ index: index,
+ parentId: parentId,
+ };
+ },
+
+ /** @private */
+ clearDragData_: function() {
+ this.dragInfo_.clearDragData();
+ this.dropDestination_ = null;
+ this.dropIndicator_.finish();
+ },
+
+ /**
+ * @private
+ * @param {Event} e
+ */
+ onDragStart_: function(e) {
+ var dragElement = getBookmarkElement(e.path);
+ if (!dragElement)
+ return;
+
+ // Determine the selected bookmarks.
+ var state = bookmarks.Store.getInstance().data;
+ var draggedNodes = Array.from(state.selection.items);
+
+ if (isBookmarkFolderNode(dragElement) ||
+ draggedNodes.indexOf(dragElement.itemId) == -1) {
+ // TODO(calamity): clear current selection.
+ draggedNodes = [dragElement.itemId];
+ }
+
+ e.preventDefault();
+
+ // If we are dragging a single link, we can do the *Link* effect.
+ // Otherwise, we only allow copy and move.
+ if (e.dataTransfer) {
+ e.dataTransfer.effectAllowed =
+ draggedNodes.length == 1 && state.nodes[draggedNodes[0]].url ?
+ 'copyLink' :
+ 'copyMove';
+ }
+
+ // TODO(calamity): account for touch.
+ chrome.bookmarkManagerPrivate.startDrag(draggedNodes, false);
+ },
+
+ /**
+ * @private
+ * @param {Event} e
+ */
+ onDragEnter_: function(e) {
+ e.preventDefault();
+ },
+
+ /**
+ * @private
+ * @param {Event} e
+ */
+ onDragOver_: function(e) {
+ this.dropDestination_ = null;
+
+ // This is necessary to actually trigger the 'none' effect, even though
+ // the event will have this set to 'none' already.
+ if (e.dataTransfer)
+ e.dataTransfer.dropEffect = 'none';
+
+ // Allow normal DND on text inputs.
+ if (e.path[0].tagName == 'INPUT')
+ return;
+
+ // The default operation is to allow dropping links etc to do
+ // navigation. We never want to do that for the bookmark manager.
+ e.preventDefault();
+
+ if (!this.dragInfo_.isDragValid())
+ return;
+
+ var overElement = getBookmarkElement(e.path);
+ this.autoExpander_.update(e, overElement);
+ if (!overElement)
+ return;
+
+
+ // Now we know that we can drop. Determine if we will drop above, on or
+ // below based on mouse position etc.
+ this.dropDestination_ =
+ this.calculateDropDestination_(e.clientY, overElement);
+ if (!this.dropDestination_)
+ return;
+
+ if (e.dataTransfer) {
+ e.dataTransfer.dropEffect =
+ this.dragInfo_.isSameProfile() ? 'move' : 'copy';
+ }
+
+ this.dropIndicator_.update(this.dropDestination_);
+ },
+
+ /**
+ * This function determines where the drop will occur.
+ * @private
+ * @param {number} elementClientY
+ * @param {!BookmarkElement} overElement
+ * @return {?DropDestination} If no valid drop position is found, null,
+ * otherwise:
+ * element - The target element that will receive the drop.
+ * position - A |DropPosition| relative to the |element|.
+ */
+ calculateDropDestination_: function(elementClientY, overElement) {
+ var validDropPositions = this.calculateValidDropPositions_(overElement);
+ if (validDropPositions == DropPosition.NONE)
+ return null;
+
+ var above = validDropPositions & DropPosition.ABOVE;
+ var below = validDropPositions & DropPosition.BELOW;
+ var on = validDropPositions & DropPosition.ON;
+ var rect = overElement.getDropTarget().getBoundingClientRect();
+ var yRatio = (elementClientY - rect.top) / rect.height;
+
+ if (above && (yRatio <= .25 || yRatio <= .5 && (!below || !on)))
+ return {element: overElement, position: DropPosition.ABOVE};
+
+ if (below && (yRatio > .75 || yRatio > .5 && (!above || !on)))
+ return {element: overElement, position: DropPosition.BELOW};
+
+ if (on)
+ return {element: overElement, position: DropPosition.ON};
+
+ return null;
+ },
+
+ /**
+ * Determines the valid drop positions for the given target element.
+ * @private
+ * @param {!BookmarkElement} overElement The element that we are currently
+ * dragging over.
+ * @return {DropPosition} An bit field enumeration of valid drop locations.
+ */
+ calculateValidDropPositions_: function(overElement) {
+ var dragInfo = this.dragInfo_;
+ var state = bookmarks.Store.getInstance().data;
+ var itemId = overElement.itemId;
+
+ // Drags aren't allowed onto the search result list.
+ if ((isBookmarkList(overElement) || isBookmarkItem(overElement)) &&
+ bookmarks.util.isShowingSearch(state)) {
+ return DropPosition.NONE;
+ }
+
+ if (isBookmarkList(overElement))
+ itemId = state.selectedFolder;
+
+ // Drags of a bookmark onto itself or of a folder into its children aren't
+ // allowed.
+ if (dragInfo.isDraggingBookmark(itemId) ||
+ dragInfo.isDraggingFolderToDescendant(itemId, state.nodes)) {
+ return DropPosition.NONE;
+ }
+
+ var validDropPositions = this.calculateDropAboveBelow_(overElement);
+ if (this.canDropOn_(overElement))
+ validDropPositions |= DropPosition.ON;
+
+ return validDropPositions;
+ },
+
+ /**
+ * @private
+ * @param {BookmarkElement} overElement
+ * @return {DropPosition}
+ */
+ calculateDropAboveBelow_: function(overElement) {
+ var dragInfo = this.dragInfo_;
+ var state = bookmarks.Store.getInstance().data;
+
+ if (isBookmarkList(overElement))
+ return DropPosition.NONE;
+
+ // We cannot drop between Bookmarks bar and Other bookmarks.
+ if (getBookmarkNode(overElement).parentId == ROOT_NODE_ID)
+ return DropPosition.NONE;
+
+ var isOverFolderNode = isBookmarkFolderNode(overElement);
+
+ // We can only drop between items in the tree if we have any folders.
+ if (isOverFolderNode && !dragInfo.isDraggingFolders())
+ return DropPosition.NONE;
+
+ var validDropPositions = DropPosition.NONE;
+
+ // Cannot drop above if the item above is already in the drag source.
+ var previousElem = overElement.previousElementSibling;
+ if (!previousElem || !dragInfo.isDraggingBookmark(previousElem.itemId))
+ validDropPositions |= DropPosition.ABOVE;
+
+ // Don't allow dropping below an expanded sidebar folder item since it is
+ // confusing to the user anyway.
+ if (isOverFolderNode && !state.closedFolders.has(overElement.itemId) &&
+ bookmarks.util.hasChildFolders(overElement.itemId, state.nodes)) {
+ return validDropPositions;
+ }
+
+ var nextElement = overElement.nextElementSibling;
+
+ // The template element sits past the end of the last bookmark element.
+ if (!isBookmarkItem(nextElement) && !isBookmarkFolderNode(nextElement))
+ nextElement = null;
+
+ // Cannot drop below if the item below is already in the drag source.
+ if (!nextElement || !dragInfo.isDraggingBookmark(nextElement.itemId))
+ validDropPositions |= DropPosition.BELOW;
+
+ return validDropPositions;
+ },
+
+ /**
+ * Determine whether we can drop the dragged items on the drop target.
+ * @private
+ * @param {!BookmarkElement} overElement The element that we are currently
+ * dragging over.
+ * @return {boolean} Whether we can drop the dragged items on the drop
+ * target.
+ */
+ canDropOn_: function(overElement) {
+ // Allow dragging onto empty bookmark lists.
+ if (isBookmarkList(overElement)) {
+ var state = bookmarks.Store.getInstance().data;
+ return state.selectedFolder &&
+ state.nodes[state.selectedFolder].children.length == 0;
+ }
+
+ // We can only drop on a folder.
+ if (getBookmarkNode(overElement).url)
+ return false;
+
+ return !this.dragInfo_.isDraggingChildBookmark(overElement.itemId)
+ },
+ };
+
+ return {
+ DNDManager: DNDManager,
+ DragInfo: DragInfo,
+ DropIndicator: DropIndicator,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.html b/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.html
new file mode 100644
index 00000000000..9c23eceb2a4
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.html
@@ -0,0 +1,40 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+
+<dom-module id="bookmarks-edit-dialog">
+ <template>
+ <style include="cr-shared-style"></style>
+ <dialog is="cr-dialog" id="dialog">
+ <div class="title">[[getDialogTitle_(isFolder_, isEdit_)]]</div>
+ <div class="body">
+ <paper-input always-float-label id="name"
+ label="$i18n{editDialogNameInput}"
+ value="{{titleValue_}}"
+ autofocus>
+ </paper-input>
+ <paper-input always-float-label id="url"
+ type="url"
+ label="$i18n{editDialogUrlInput}"
+ error-message="$i18n{editDialogInvalidUrl}"
+ value="{{urlValue_}}"
+ hidden$="[[isFolder_]]"
+ required>
+ </paper-input>
+ </div>
+ <div class="button-container">
+ <paper-button class="cancel-button" on-tap="onCancelButtonTap_">
+ $i18n{cancelEdit}
+ </paper-button>
+ <paper-button id="saveButton" class="action-button"
+ on-tap="onSaveButtonTap_">
+ $i18n{saveEdit}
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="chrome://bookmarks/edit_dialog.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js b/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js
new file mode 100644
index 00000000000..06f916a3091
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js
@@ -0,0 +1,139 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer({
+ is: 'bookmarks-edit-dialog',
+
+ properties: {
+ /** @private */
+ isFolder_: Boolean,
+
+ /** @private */
+ isEdit_: Boolean,
+
+ /**
+ * Item that is being edited, or null when adding.
+ * @private {?BookmarkNode}
+ */
+ editItem_: Object,
+
+ /**
+ * Parent node for the item being added, or null when editing.
+ * @private {?string}
+ */
+ parentId_: String,
+
+ /** @private */
+ titleValue_: String,
+
+ /** @private */
+ urlValue_: String,
+ },
+
+ /**
+ * Show the dialog to add a new folder (if |isFolder|) or item, which will be
+ * inserted into the tree as a child of |parentId|.
+ * @param {boolean} isFolder
+ * @param {string} parentId
+ */
+ showAddDialog: function(isFolder, parentId) {
+ this.reset_();
+ this.isEdit_ = false;
+ this.isFolder_ = isFolder;
+ this.parentId_ = parentId;
+
+ this.$.dialog.showModal();
+ },
+
+ /**
+ * Show the edit dialog for |editItem|.
+ * @param {BookmarkNode} editItem
+ */
+ showEditDialog: function(editItem) {
+ this.reset_();
+ this.isEdit_ = true;
+ this.isFolder_ = !editItem.url;
+ this.editItem_ = editItem;
+
+ this.titleValue_ = editItem.title;
+ if (!this.isFolder_)
+ this.urlValue_ = assert(editItem.url);
+
+ this.$.dialog.showModal();
+ },
+
+ /**
+ * Clear out existing values from the dialog, allowing it to be reused.
+ * @private
+ */
+ reset_: function() {
+ this.editItem_ = null;
+ this.parentId_ = null;
+ this.$.url.invalid = false;
+ this.titleValue_ = '';
+ this.urlValue_ = '';
+ },
+
+ /**
+ * @param {boolean} isFolder
+ * @param {boolean} isEdit
+ * @return {string}
+ * @private
+ */
+ getDialogTitle_: function(isFolder, isEdit) {
+ var title;
+ if (isEdit)
+ title = isFolder ? 'renameFolderTitle' : 'editBookmarkTitle';
+ else
+ title = isFolder ? 'addFolderTitle' : 'addBookmarkTitle';
+
+ return loadTimeData.getString(title);
+ },
+
+ /**
+ * Validates the value of the URL field, returning true if it is a valid URL.
+ * May modify the value by prepending 'http://' in order to make it valid.
+ * @return {boolean}
+ * @private
+ */
+ validateUrl_: function() {
+ var urlInput = /** @type {PaperInputElement} */ (this.$.url);
+ var originalValue = this.urlValue_;
+
+ if (urlInput.validate())
+ return true;
+
+ this.urlValue_ = 'http://' + originalValue;
+
+ if (urlInput.validate())
+ return true;
+
+ this.urlValue_ = originalValue;
+ return false;
+ },
+
+ /** @private */
+ onSaveButtonTap_: function() {
+ var edit = {'title': this.titleValue_};
+ if (!this.isFolder_) {
+ if (!this.validateUrl_())
+ return;
+
+ edit['url'] = this.urlValue_;
+ }
+
+ if (this.isEdit_) {
+ chrome.bookmarks.update(this.editItem_.id, edit);
+ } else {
+ edit['parentId'] = this.parentId_;
+ chrome.bookmarks.create(edit);
+ }
+ this.$.dialog.close();
+ },
+
+ /** @private */
+ onCancelButtonTap_: function() {
+ this.$.dialog.cancel();
+ },
+});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/folder_node.html b/chromium/chrome/browser/resources/md_bookmarks/folder_node.html
index 6034e3ab969..6b6ac262202 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/folder_node.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/folder_node.html
@@ -3,13 +3,16 @@
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="chrome://bookmarks/actions.html">
<link rel="import" href="chrome://bookmarks/icons.html">
<link rel="import" href="chrome://bookmarks/shared_style.html">
+<link rel="import" href="chrome://bookmarks/store_client.html">
<dom-module id="bookmarks-folder-node">
<template>
<style include="shared-style">
:host {
+ --padding-start-per-depth: 36px;
display: block;
}
@@ -20,7 +23,7 @@
}
.menu-label {
- -webkit-margin-start: 24px;
+ -webkit-margin-start: 16px;
color: var(--folder-inactive-color);
font-weight: 500;
overflow: hidden;
@@ -29,23 +32,23 @@
}
#container {
+ -webkit-padding-start:
+ calc(var(--node-depth, 0) * var(--padding-start-per-depth));
+ cursor: pointer;
height: 40px;
- }
-
- #descendants {
- -webkit-padding-start: 40.5px;
+ position: relative;
}
#folder-label {
+ -webkit-padding-end: 8px;
color: var(--secondary-text-color);
- cursor: pointer;
flex-grow: 1;
overflow: hidden;
}
- :host([is-selected-folder]) .menu-label,
- :host([is-selected-folder]) #folder-label {
- color: var(--folder-active-color);
+ :host([is-selected-folder_]) .menu-label,
+ :host([is-selected-folder_]) #folder-label {
+ color: var(--interactive-color);
}
iron-icon {
@@ -54,30 +57,50 @@
min-width: 20px;
}
- paper-icon-button {
+ #arrow {
color: var(--secondary-text-color);
height: 36px;
+ margin: 0 8px;
min-width: 36px;
- padding: 8px;
+ transform: rotate(-90deg);
+ transition: transform 150ms;
width: 36px;
}
+
+ :host-context([dir='rtl']) #arrow {
+ transform: rotate(90deg);
+ }
+
+ #arrow[is-open] {
+ transform: initial;
+ }
+
+ [no-children] {
+ -webkit-padding-start: 52px; /* The width of the arrow and its margin */
+ }
</style>
- <div id="container" class="v-centered">
- <div id="folder-label" class="v-centered" on-tap="selectFolder_">
- <iron-icon icon="[[getFolderIcon_(isSelectedFolder)]]"></iron-icon>
- <div class="menu-label">[[item.title]]</div>
- </div>
- <template is="dom-if" if="[[hasChildFolder_(item.children)]]">
- <paper-icon-button icon="[[getArrowIcon_(item.isOpen)]]"
- on-tap="toggleFolder_"></paper-icon-button>
+ <div id="container" class="v-centered" on-tap="selectFolder_"
+ draggable="[[!isRootFolder_(depth)]]">
+ <template is="dom-if" if="[[hasChildFolder_(item_.children)]]">
+ <paper-icon-button id="arrow" icon="cr:arrow-drop-down"
+ is-open$="[[!isClosed_]]" on-tap="toggleFolder_">
+ </paper-icon-button>
</template>
+ <div id="folder-label" class="v-centered">
+ <iron-icon icon="[[getFolderIcon_(isSelectedFolder_)]]"
+ no-children$="[[!hasChildFolder_(item_.children)]]">
+ </iron-icon>
+ <div class="menu-label">[[item_.title]]</div>
+ </div>
</div>
- <div id="descendants" hidden$="[[!item.isOpen]]">
- <template is="dom-repeat" items="[[item.children]]"
- filter="isFolder_" observe="url" as="child">
- <bookmarks-folder-node item="[[child]]"
- is-selected-folder="[[child.isSelectedFolder]]">
+ <div id="descendants" hidden$="[[isClosed_]]">
+ <template is="dom-repeat"
+ items="[[item_.children]]"
+ as="child"
+ filter="isFolder_">
+ <bookmarks-folder-node item-id="[[child]]"
+ depth="[[getChildDepth_(depth)]]">
</bookmarks-folder-node>
</template>
</div>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/folder_node.js b/chromium/chrome/browser/resources/md_bookmarks/folder_node.js
index 6793a5e06df..2800bf00f17 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/folder_node.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/folder_node.js
@@ -5,67 +5,134 @@
Polymer({
is: 'bookmarks-folder-node',
+ behaviors: [
+ bookmarks.StoreClient,
+ ],
+
properties: {
- /** @type {BookmarkTreeNode} */
- item: Object,
+ itemId: {
+ type: String,
+ observer: 'updateFromStore',
+ },
+
+ depth: {
+ type: Number,
+ observer: 'depthChanged_',
+ },
+
+ /** @type {BookmarkNode} */
+ item_: Object,
- isSelectedFolder: {
+ /** @private */
+ isClosed_: Boolean,
+
+ /** @private */
+ selectedFolder_: String,
+
+ /** @private */
+ searchActive_: Boolean,
+
+ /** @private */
+ isSelectedFolder_: {
type: Boolean,
value: false,
reflectToAttribute: true,
+ computed: 'computeIsSelected_(itemId, selectedFolder_, searchActive_)'
},
},
+ /** @override */
+ attached: function() {
+ this.watch('item_', function(state) {
+ return state.nodes[this.itemId];
+ }.bind(this));
+ this.watch('isClosed_', function(state) {
+ return state.closedFolders.has(this.itemId);
+ }.bind(this));
+ this.watch('selectedFolder_', function(state) {
+ return state.selectedFolder;
+ });
+ this.watch('searchActive_', function(state) {
+ return bookmarks.util.isShowingSearch(state);
+ });
+
+ this.updateFromStore();
+ },
+
+ /** @return {HTMLElement} */
+ getDropTarget: function() {
+ return this.$.container;
+ },
+
/**
* @private
* @return {string}
*/
getFolderIcon_: function() {
- return this.isSelectedFolder ? 'bookmarks:folder-open' : 'cr:folder';
+ return this.isSelectedFolder_ ? 'bookmarks:folder-open' : 'cr:folder';
+ },
+
+ /** @private */
+ selectFolder_: function() {
+ this.dispatch(bookmarks.actions.selectFolder(this.item_.id));
},
/**
+ * Occurs when the drop down arrow is tapped.
* @private
- * @return {string}
+ * @param {!Event} e
+ */
+ toggleFolder_: function(e) {
+ this.dispatch(
+ bookmarks.actions.changeFolderOpen(this.item_.id, this.isClosed_));
+ e.stopPropagation();
+ },
+
+ /**
+ * @private
+ * @param {string} itemId
+ * @param {string} selectedFolder
+ * @return {boolean}
*/
- getArrowIcon_: function() {
- return this.item.isOpen ? 'cr:arrow-drop-up' : 'cr:arrow-drop-down';
+ computeIsSelected_: function(itemId, selectedFolder, searchActive) {
+ return itemId == selectedFolder && !searchActive;
+ },
+
+ /**
+ * @private
+ * @return {boolean}
+ */
+ hasChildFolder_: function() {
+ return bookmarks.util.hasChildFolders(this.itemId, this.getState().nodes);
},
/** @private */
- selectFolder_: function() {
- this.fire('selected-folder-changed', this.item.id);
+ depthChanged_: function() {
+ this.style.setProperty('--node-depth', String(this.depth));
},
/**
- * Occurs when the drop down arrow is tapped.
* @private
+ * @return {number}
*/
- toggleFolder_: function() {
- this.fire('folder-open-changed', {
- id: this.item.id,
- open: !this.item.isOpen,
- });
+ getChildDepth_: function() {
+ return this.depth + 1;
},
/**
+ * @param {string} itemId
* @private
* @return {boolean}
*/
- hasChildFolder_: function() {
- for (var i = 0; i < this.item.children.length; i++) {
- if (!this.item.children[i].url)
- return true;
- }
- return false;
+ isFolder_: function(itemId) {
+ return !this.getState().nodes[itemId].url;
},
/**
- * @param {BookmarkTreeNode} item
* @private
* @return {boolean}
*/
- isFolder_: function(item) {
- return !item.url;
- }
+ isRootFolder_: function() {
+ return this.depth == 0;
+ },
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/item.html b/chromium/chrome/browser/resources/md_bookmarks/item.html
index d98a24b3ceb..1dba8c73d03 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/item.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/item.html
@@ -3,7 +3,9 @@
<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://bookmarks/actions.html">
<link rel="import" href="chrome://bookmarks/shared_style.html">
+<link rel="import" href="chrome://bookmarks/store_client.html">
<dom-module id="bookmarks-item">
<template>
@@ -12,18 +14,19 @@
-webkit-padding-start: 20px;
-webkit-user-select: none;
align-items: center;
+ cursor: pointer;
display: flex;
flex-direction: row;
height: 40px;
+ position: relative;
}
- :host([is-selected-item]) {
+ :host([is-selected-item_]) {
background-color: rgb(225, 235, 253);
}
#website-title {
color: var(--primary-text-color);
- cursor: pointer;
flex: 1;
overflow: hidden;
text-decoration: none;
@@ -60,10 +63,10 @@
<div id="icon" hidden$="[[isFolder_]]"></div>
</div>
<div id="website-title">
- [[item.title]]
+ [[item_.title]]
</div>
<button is="paper-icon-button-light" class="more-vert-button"
- on-click="onMenuButtonOpenClick_">
+ on-click="onMenuButtonClick_" on-dblclick="onMenuButtonDblClick_">
<div></div>
<div></div>
<div></div>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/item.js b/chromium/chrome/browser/resources/md_bookmarks/item.js
index b75eb60de66..d761f653235 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/item.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/item.js
@@ -5,23 +5,34 @@
Polymer({
is: 'bookmarks-item',
+ behaviors: [
+ bookmarks.StoreClient,
+ ],
+
properties: {
- /** @type {BookmarkTreeNode} */
- item: {
+ itemId: {
+ type: String,
+ observer: 'onItemIdChanged_',
+ },
+
+ /** @private {BookmarkNode} */
+ item_: {
type: Object,
observer: 'onItemChanged_',
},
- isFolder_: Boolean,
-
- isSelectedItem: {
+ /** @private */
+ isSelectedItem_: {
type: Boolean,
reflectToAttribute: true,
},
+
+ /** @private */
+ isFolder_: Boolean,
},
observers: [
- 'updateFavicon_(item.url)',
+ 'updateFavicon_(item_.url)',
],
listeners: {
@@ -29,21 +40,56 @@ Polymer({
'dblclick': 'onDblClick_',
},
+ /** @override */
+ attached: function() {
+ this.watch('item_', function(store) {
+ return store.nodes[this.itemId];
+ }.bind(this));
+ this.watch('isSelectedItem_', function(store) {
+ return !!store.selection.items.has(this.itemId);
+ }.bind(this));
+
+ this.updateFromStore();
+ },
+
+ /** @return {BookmarksItemElement} */
+ getDropTarget: function() {
+ return this;
+ },
+
/**
* @param {Event} e
* @private
*/
- onMenuButtonOpenClick_: function(e) {
+ onMenuButtonClick_: function(e) {
e.stopPropagation();
+ this.dispatch(bookmarks.actions.selectItem(
+ this.itemId, false, false, this.getState()));
this.fire('open-item-menu', {
target: e.target,
- item: this.item,
+ item: this.item_,
});
},
+ /**
+ * @param {Event} e
+ * @private
+ */
+ onMenuButtonDblClick_: function(e) {
+ e.stopPropagation();
+ },
+
+ /** @private */
+ onItemIdChanged_: function() {
+ // TODO(tsergeant): Add a histogram to measure whether this assertion fails
+ // for real users.
+ assert(this.getState().nodes[this.itemId]);
+ this.updateFromStore();
+ },
+
/** @private */
onItemChanged_: function() {
- this.isFolder_ = !(this.item.url);
+ this.isFolder_ = !this.item_.url;
},
/**
@@ -51,11 +97,9 @@ Polymer({
* @private
*/
onClick_: function(e) {
- this.fire('select-item', {
- item: this.item,
- range: e.shiftKey,
- add: e.ctrlKey,
- });
+ this.dispatch(bookmarks.actions.selectItem(
+ this.itemId, e.ctrlKey, e.shiftKey, this.getState()));
+ e.stopPropagation();
},
/**
@@ -63,10 +107,10 @@ Polymer({
* @private
*/
onDblClick_: function(e) {
- if (!this.item.url)
- this.fire('selected-folder-changed', this.item.id);
+ if (!this.item_.url)
+ this.dispatch(bookmarks.actions.selectFolder(this.item_.id));
else
- chrome.tabs.create({url: this.item.url});
+ chrome.tabs.create({url: this.item_.url});
},
/**
diff --git a/chromium/chrome/browser/resources/md_bookmarks/list.html b/chromium/chrome/browser/resources/md_bookmarks/list.html
index 19b6d9f0710..bd48028f18b 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/list.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/list.html
@@ -1,19 +1,20 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
+<link rel="import" href="chrome://bookmarks/edit_dialog.html">
<link rel="import" href="chrome://bookmarks/item.html">
<link rel="import" href="chrome://bookmarks/shared_style.html">
+<link rel="import" href="chrome://bookmarks/store_client.html">
+<link rel="import" href="chrome://bookmarks/util.html">
<dom-module id="bookmarks-list">
<template>
- <style include="shared-style cr-shared-style">
+ <style include="shared-style">
:host {
- padding: 20px 32px;
+ overflow-y: auto;
+ padding: 20px 32px 20px calc(32px - var(--splitter-width));
}
#bookmarksCard {
@@ -21,7 +22,6 @@
background-color: #fff;
margin: 0 auto;
max-width: var(--card-max-width);
- min-width: var(--card-min-width);
padding: 8px 0;
}
@@ -47,40 +47,19 @@
$i18n{menuDelete}
</button>
</dialog>
- <dialog is="cr-dialog" id="editBookmark">
- <div class="title">[[getEditorTitle_(menuItem_)]]</div>
- <div class="body">
- <paper-input always-float-label id="name"
- label="$i18n{editDialogNameInput}"
- value="{{menuItem_.title}}">
- </paper-input>
- <paper-input always-float-label id="url"
- label="$i18n{editDialogUrlInput}"
- value="{{menuItem_.url}}"
- hidden$="[[!menuItem_.url]]">
- </paper-input>
- </div>
- <div class="button-container">
- <paper-button class="cancel-button" on-tap="onCancelEditTap_">
- $i18n{cancelEdit}
- </paper-button>
- <paper-button class="action-button" on-tap="onSaveEditTap_"
- id='saveButton'>
- $i18n{saveEdit}
- </paper-button>
- </div>
- </dialog>
- <div id="bookmarksCard" hidden$="[[isEmptyList_(displayedList.length)]]">
- <template is="dom-repeat" items="[[displayedList]]" as="item">
- <bookmarks-item item="[[item]]"
- is-selected-item="[[item.isSelectedItem]]">
+ <div id="bookmarksCard" hidden$="[[isEmptyList_(displayedList_.length)]]">
+ <template is="dom-repeat" items="[[displayedList_]]" as="id">
+ <bookmarks-item item-id="[[id]]" draggable="true">
</bookmarks-item>
</template>
</div>
- <div class="centered-message"
- hidden$="[[!isEmptyList_(displayedList.length)]]">
- [[emptyListMessage_(searchTerm)]]
+ <div id="message" class="centered-message"
+ hidden$="[[!isEmptyList_(displayedList_.length)]]">
+ [[emptyListMessage_(searchTerm_)]]
</div>
+ <template is="cr-lazy-render" id="editDialog">
+ <bookmarks-edit-dialog></bookmarks-edit-dialog>
+ </template>
</template>
<script src="chrome://bookmarks/list.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/list.js b/chromium/chrome/browser/resources/md_bookmarks/list.js
index 5d16af2d6a3..6952696a2e8 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/list.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/list.js
@@ -5,20 +5,47 @@
Polymer({
is: 'bookmarks-list',
+ behaviors: [
+ bookmarks.StoreClient,
+ ],
+
properties: {
- /** @type {BookmarkTreeNode} */
+ /** @type {BookmarkNode} */
menuItem_: Object,
- /** @type {Array<BookmarkTreeNode>} */
- displayedList: Array,
-
- searchTerm: String,
+ /** @private {Array<string>} */
+ displayedList_: {
+ type: Array,
+ value: function() {
+ // Use an empty list during initialization so that the databinding to
+ // hide #bookmarksCard takes effect.
+ return [];
+ },
+ },
+
+ /** @private */
+ searchTerm_: String,
},
listeners: {
+ 'click': 'deselectItems_',
'open-item-menu': 'onOpenItemMenu_',
},
+ attached: function() {
+ this.watch('displayedList_', function(state) {
+ return bookmarks.util.getDisplayedList(state);
+ });
+ this.watch('searchTerm_', function(state) {
+ return state.search.term;
+ });
+ this.updateFromStore();
+ },
+
+ getDropTarget: function() {
+ return this.$.message;
+ },
+
/**
* @param {Event} e
* @private
@@ -33,7 +60,8 @@ Polymer({
/** @private */
onEditTap_: function() {
this.closeDropdownMenu_();
- this.$.editBookmark.showModal();
+ /** @type {BookmarksEditDialogElement} */ (this.$.editDialog.get())
+ .showEditDialog(this.menuItem_);
},
/** @private */
@@ -60,21 +88,6 @@ Polymer({
},
/** @private */
- onSaveEditTap_: function() {
- var edit = {'title': this.menuItem_.title};
- if (this.menuItem_.url)
- edit['url'] = this.menuItem_.url;
-
- chrome.bookmarks.update(this.menuItem_.id, edit);
- this.$.editBookmark.close();
- },
-
- /** @private */
- onCancelEditTap_: function() {
- this.$.editBookmark.cancel();
- },
-
- /** @private */
closeDropdownMenu_: function() {
var menu = /** @type {!CrActionMenuElement} */ (
this.$.dropdown);
@@ -88,19 +101,18 @@ Polymer({
},
/** @private */
- getEditorTitle_: function() {
- var title = this.menuItem_.url ? 'editBookmarkTitle' : 'renameFolderTitle';
- return loadTimeData.getString(title);
- },
-
- /** @private */
emptyListMessage_: function() {
- var emptyListMessage = this.searchTerm ? 'noSearchResults' : 'emptyList';
+ var emptyListMessage = this.searchTerm_ ? 'noSearchResults' : 'emptyList';
return loadTimeData.getString(emptyListMessage);
},
/** @private */
isEmptyList_: function() {
- return this.displayedList.length == 0;
+ return this.displayedList_.length == 0;
+ },
+
+ /** @private */
+ deselectItems_: function() {
+ this.dispatch(bookmarks.actions.deselectItems());
},
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/reducers.html b/chromium/chrome/browser/resources/md_bookmarks/reducers.html
new file mode 100644
index 00000000000..ac8b8560606
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/reducers.html
@@ -0,0 +1,3 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://bookmarks/constants.html">
+<script src="chrome://bookmarks/reducers.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/reducers.js b/chromium/chrome/browser/resources/md_bookmarks/reducers.js
new file mode 100644
index 00000000000..b0d0a9267ba
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/reducers.js
@@ -0,0 +1,432 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Module of functions which produce a new page state in response
+ * to an action. Reducers (in the same sense as Array.prototype.reduce) must be
+ * pure functions: they must not modify existing state objects, or make any API
+ * calls.
+ */
+
+cr.define('bookmarks', function() {
+ var SelectionState = {};
+
+ /**
+ * @param {SelectionState} selectionState
+ * @param {Action} action
+ * @return {SelectionState}
+ */
+ SelectionState.selectItems = function(selectionState, action) {
+ var newItems = new Set();
+ if (action.add)
+ newItems = new Set(selectionState.items);
+
+ action.items.forEach(function(id) {
+ newItems.add(id);
+ });
+
+ return /** @type {SelectionState} */ (Object.assign({}, selectionState, {
+ items: newItems,
+ anchor: action.anchor,
+ }));
+ };
+
+ /**
+ * @param {SelectionState} selectionState
+ * @return {SelectionState}
+ */
+ SelectionState.deselectAll = function(selectionState) {
+ return {
+ items: new Set(),
+ anchor: null,
+ };
+ };
+
+ /**
+ * @param {SelectionState} selectionState
+ * @param {!Set<string>} deleted
+ * @return SelectionState
+ */
+ SelectionState.deselectDeletedItems = function(selectionState, deleted) {
+ return /** @type {SelectionState} */ Object.assign({}, selectionState, {
+ items: bookmarks.util.removeIdsFromSet(selectionState.items, deleted),
+ anchor: null,
+ });
+ };
+
+ /**
+ * @param {SelectionState} selection
+ * @param {Action} action
+ * @return {SelectionState}
+ */
+ SelectionState.updateSelection = function(selection, action) {
+ switch (action.name) {
+ case 'clear-search':
+ case 'finish-search':
+ case 'select-folder':
+ case 'deselect-items':
+ return SelectionState.deselectAll(selection);
+ case 'select-items':
+ return SelectionState.selectItems(selection, action);
+ case 'remove-bookmark':
+ return SelectionState.deselectDeletedItems(
+ selection, action.descendants);
+ default:
+ return selection;
+ }
+ };
+
+ var SearchState = {};
+
+ /**
+ * @param {SearchState} search
+ * @param {Action} action
+ * @return {SearchState}
+ */
+ SearchState.startSearch = function(search, action) {
+ return {
+ term: action.term,
+ inProgress: true,
+ results: [],
+ };
+ };
+
+ /**
+ * @param {SearchState} search
+ * @param {Action} action
+ * @return {SearchState}
+ */
+ SearchState.finishSearch = function(search, action) {
+ return /** @type {SearchState} */ (Object.assign({}, search, {
+ inProgress: false,
+ results: action.results,
+ }));
+ };
+
+ /** @return {SearchState} */
+ SearchState.clearSearch = function() {
+ return {
+ term: '',
+ inProgress: false,
+ results: [],
+ };
+ };
+
+ /**
+ * @param {SearchState} search
+ * @param {!Set<string>} deletedIds
+ * @return {SearchState}
+ */
+ SearchState.removeDeletedResults = function(search, deletedIds) {
+ var newResults = [];
+ search.results.forEach(function(id) {
+ if (!deletedIds.has(id))
+ newResults.push(id);
+ });
+ return /** @type {SearchState} */ (Object.assign({}, search, {
+ results: newResults,
+ }));
+ };
+
+ /**
+ * @param {SearchState} search
+ * @param {Action} action
+ * @return {SearchState}
+ */
+ SearchState.updateSearch = function(search, action) {
+ switch (action.name) {
+ case 'start-search':
+ return SearchState.startSearch(search, action);
+ case 'select-folder':
+ case 'clear-search':
+ return SearchState.clearSearch();
+ case 'finish-search':
+ return SearchState.finishSearch(search, action);
+ case 'remove-bookmark':
+ return SearchState.removeDeletedResults(search, action.descendants);
+ default:
+ return search;
+ }
+ };
+
+ var NodeState = {};
+
+ /**
+ * @param {NodeList} nodes
+ * @param {string} id
+ * @param {function(BookmarkNode):BookmarkNode} callback
+ * @return {NodeList}
+ */
+ NodeState.modifyNode_ = function(nodes, id, callback) {
+ var nodeModification = {};
+ nodeModification[id] = callback(nodes[id]);
+ return Object.assign({}, nodes, nodeModification);
+ };
+
+ /**
+ * @param {NodeList} nodes
+ * @param {Action} action
+ * @return {NodeList}
+ */
+ NodeState.createBookmark = function(nodes, action) {
+ var nodeModifications = {};
+ nodeModifications[action.id] = action.node;
+
+ var parentNode = nodes[action.parentId];
+ var newChildren = parentNode.children.slice();
+ newChildren.splice(action.parentIndex, 0, action.id);
+ nodeModifications[action.parentId] = Object.assign({}, parentNode, {
+ children: newChildren,
+ });
+
+ return Object.assign({}, nodes, nodeModifications);
+ };
+
+ /**
+ * @param {NodeList} nodes
+ * @param {Action} action
+ * @return {NodeList}
+ */
+ NodeState.editBookmark = function(nodes, action) {
+ // Do not allow folders to change URL (making them no longer folders).
+ if (!nodes[action.id].url && action.changeInfo.url)
+ delete action.changeInfo.url;
+
+ return NodeState.modifyNode_(nodes, action.id, function(node) {
+ return /** @type {BookmarkNode} */ (
+ Object.assign({}, node, action.changeInfo));
+ });
+ };
+
+ /**
+ * @param {NodeList} nodes
+ * @param {Action} action
+ * @return {NodeList}
+ */
+ NodeState.moveBookmark = function(nodes, action) {
+ var nodeModifications = {};
+ var id = action.id;
+
+ // Change node's parent.
+ nodeModifications[id] =
+ Object.assign({}, nodes[id], {parentId: action.parentId});
+
+ // Remove from old parent.
+ var oldParentId = action.oldParentId;
+ var oldParentChildren = nodes[oldParentId].children.slice();
+ oldParentChildren.splice(action.oldIndex, 1);
+ nodeModifications[oldParentId] =
+ Object.assign({}, nodes[oldParentId], {children: oldParentChildren});
+
+ // Add to new parent.
+ var parentId = action.parentId;
+ var parentChildren = oldParentId == parentId ?
+ oldParentChildren :
+ nodes[parentId].children.slice();
+ parentChildren.splice(action.index, 0, action.id);
+ nodeModifications[parentId] =
+ Object.assign({}, nodes[parentId], {children: parentChildren});
+
+ return Object.assign({}, nodes, nodeModifications);
+ };
+
+ /**
+ * @param {NodeList} nodes
+ * @param {Action} action
+ * @return {NodeList}
+ */
+ NodeState.removeBookmark = function(nodes, action) {
+ var newState =
+ NodeState.modifyNode_(nodes, action.parentId, function(node) {
+ var newChildren = node.children.slice();
+ newChildren.splice(action.index, 1);
+ return /** @type {BookmarkNode} */ (
+ Object.assign({}, node, {children: newChildren}));
+ });
+
+ return bookmarks.util.removeIdsFromMap(newState, action.descendants);
+ };
+
+ /**
+ * @param {NodeList} nodes
+ * @param {Action} action
+ * @return {NodeList}
+ */
+ NodeState.reorderChildren = function(nodes, action) {
+ return NodeState.modifyNode_(nodes, action.id, function(node) {
+ return /** @type {BookmarkNode} */ (
+ Object.assign({}, node, {children: action.children}));
+ });
+ };
+
+ /**
+ * @param {NodeList} nodes
+ * @param {Action} action
+ * @return {NodeList}
+ */
+ NodeState.updateNodes = function(nodes, action) {
+ switch (action.name) {
+ case 'create-bookmark':
+ return NodeState.createBookmark(nodes, action);
+ case 'edit-bookmark':
+ return NodeState.editBookmark(nodes, action);
+ case 'move-bookmark':
+ return NodeState.moveBookmark(nodes, action);
+ case 'remove-bookmark':
+ return NodeState.removeBookmark(nodes, action);
+ case 'reorder-children':
+ return NodeState.reorderChildren(nodes, action);
+ case 'refresh-nodes':
+ return action.nodes;
+ default:
+ return nodes;
+ }
+ };
+
+ var SelectedFolderState = {};
+
+ /**
+ * @param {NodeList} nodes
+ * @param {string} ancestorId
+ * @param {string} childId
+ * @return {boolean}
+ */
+ SelectedFolderState.isAncestorOf = function(nodes, ancestorId, childId) {
+ var currentId = childId;
+ // Work upwards through the tree from child.
+ while (currentId) {
+ if (currentId == ancestorId)
+ return true;
+ currentId = nodes[currentId].parentId;
+ }
+ return false;
+ };
+
+ /**
+ * @param {string} selectedFolder
+ * @param {Action} action
+ * @param {NodeList} nodes
+ * @return {string}
+ */
+ SelectedFolderState.updateSelectedFolder = function(
+ selectedFolder, action, nodes) {
+ switch (action.name) {
+ case 'select-folder':
+ // TODO(tsergeant): It should not be possible to select a non-folder.
+ return action.id;
+ case 'change-folder-open':
+ // When hiding the selected folder by closing its ancestor, select
+ // that ancestor instead.
+ if (!action.open && selectedFolder &&
+ SelectedFolderState.isAncestorOf(
+ nodes, action.id, selectedFolder)) {
+ return action.id;
+ }
+ return selectedFolder;
+ case 'remove-bookmark':
+ // When deleting the selected folder (or its ancestor), select the
+ // parent of the deleted node.
+ if (selectedFolder &&
+ SelectedFolderState.isAncestorOf(nodes, action.id, selectedFolder))
+ return assert(nodes[action.id].parentId);
+ return selectedFolder;
+ default:
+ return selectedFolder;
+ }
+ };
+
+ var ClosedFolderState = {};
+
+ /**
+ * @param {ClosedFolderState} closedFolders
+ * @param {string|undefined} id
+ * @param {NodeList} nodes
+ * @return {ClosedFolderState}
+ */
+ ClosedFolderState.openFolderAndAncestors = function(
+ closedFolders, id, nodes) {
+ var newClosedFolders = new Set(closedFolders);
+ var currentId = id;
+ while (currentId) {
+ if (closedFolders.has(currentId))
+ newClosedFolders.delete(currentId);
+
+ currentId = nodes[currentId].parentId;
+ }
+
+ return newClosedFolders;
+ };
+
+ /**
+ * @param {ClosedFolderState} closedFolders
+ * @param {Action} action
+ * @return {ClosedFolderState}
+ */
+ ClosedFolderState.changeFolderOpen = function(closedFolders, action) {
+ var closed = !action.open;
+ var newClosedFolders = new Set(closedFolders);
+ if (closed)
+ newClosedFolders.add(action.id);
+ else
+ newClosedFolders.delete(action.id);
+
+ return newClosedFolders;
+ };
+
+ /**
+ * @param {ClosedFolderState} closedFolders
+ * @param {Action} action
+ * @param {NodeList} nodes
+ * @return {ClosedFolderState}
+ */
+ ClosedFolderState.updateClosedFolders = function(
+ closedFolders, action, nodes) {
+ switch (action.name) {
+ case 'change-folder-open':
+ return ClosedFolderState.changeFolderOpen(closedFolders, action);
+ case 'select-folder':
+ return ClosedFolderState.openFolderAndAncestors(
+ closedFolders, nodes[action.id].parentId, nodes);
+ case 'move-bookmark':
+ if (!nodes[action.id].children)
+ return closedFolders;
+
+ return ClosedFolderState.openFolderAndAncestors(
+ closedFolders, action.parentId, nodes);
+ case 'remove-bookmark':
+ return bookmarks.util.removeIdsFromSet(
+ closedFolders, action.descendants);
+ default:
+ return closedFolders;
+ };
+ };
+
+ /**
+ * Root reducer for the Bookmarks page. This is called by the store in
+ * response to an action, and the return value is used to update the UI.
+ * @param {!BookmarksPageState} state
+ * @param {Action} action
+ * @return {!BookmarksPageState}
+ */
+ function reduceAction(state, action) {
+ return {
+ nodes: NodeState.updateNodes(state.nodes, action),
+ selectedFolder: SelectedFolderState.updateSelectedFolder(
+ state.selectedFolder, action, state.nodes),
+ closedFolders: ClosedFolderState.updateClosedFolders(
+ state.closedFolders, action, state.nodes),
+ search: SearchState.updateSearch(state.search, action),
+ selection: SelectionState.updateSelection(state.selection, action),
+ };
+ }
+
+ return {
+ reduceAction: reduceAction,
+ ClosedFolderState: ClosedFolderState,
+ NodeState: NodeState,
+ SearchState: SearchState,
+ SelectedFolderState: SelectedFolderState,
+ SelectionState: SelectionState,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/router.html b/chromium/chrome/browser/resources/md_bookmarks/router.html
index 9ad327a2876..25dfdb59f43 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/router.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/router.html
@@ -1,6 +1,8 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-location/iron-location.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-location/iron-query-params.html">
+<link rel="import" href="chrome://bookmarks/actions.html">
+<link rel="import" href="chrome://bookmarks/store_client.html">
<dom-module id="bookmarks-router">
<template>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/router.js b/chromium/chrome/browser/resources/md_bookmarks/router.js
index 38b16f1602b..11d1d40104c 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/router.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/router.js
@@ -10,45 +10,68 @@ Polymer({
*/
is: 'bookmarks-router',
+ behaviors: [
+ bookmarks.StoreClient,
+ ],
+
properties: {
- // Parameter q is routed to the searchTerm.
- // Parameter id is routed to the selectedId.
+ /**
+ * Parameter q is routed to the searchTerm.
+ * Parameter id is routed to the selectedId.
+ * @private
+ */
queryParams_: Object,
- searchTerm: {
- type: String,
- observer: 'onSearchTermChanged_',
- },
+ /** @private */
+ searchTerm_: String,
- /** @type {?string} */
- selectedId: {
- type: String,
- observer: 'onSelectedIdChanged_',
- },
+ /** @private {?string} */
+ selectedId_: String,
},
observers: [
- 'onQueryChanged_(queryParams_.*)',
+ 'onQueryChanged_(queryParams_.q)',
+ 'onFolderChanged_(queryParams_.id)',
+ 'onStateChanged_(searchTerm_, selectedId_)',
],
+ attached: function() {
+ this.watch('selectedId_', function(state) {
+ return state.selectedFolder;
+ });
+ this.watch('searchTerm_', function(state) {
+ return state.search.term;
+ });
+ },
+
/** @private */
onQueryChanged_: function() {
- this.searchTerm = this.queryParams_.q || '';
- this.selectedId = this.queryParams_.id;
+ var searchTerm = this.queryParams_.q || '';
+ if (searchTerm && searchTerm != this.searchTerm_) {
+ this.searchTerm_ = searchTerm;
+ this.dispatch(bookmarks.actions.setSearchTerm(searchTerm));
+ }
+ },
- if (this.searchTerm)
- this.fire('search-term-changed', this.searchTerm);
- else
- this.fire('selected-folder-changed', this.selectedId);
+ /** @private */
+ onFolderChanged_: function() {
+ var selectedId = this.queryParams_.id;
+ if (selectedId && selectedId != this.selectedId_) {
+ this.selectedId_ = selectedId;
+ this.dispatch(bookmarks.actions.selectFolder(selectedId));
+ }
},
/** @private */
- onSelectedIdChanged_: function() {
- this.set('queryParams_.id', this.selectedId || null);
+ onStateChanged_: function() {
+ this.debounce('updateQueryParams', this.updateQueryParams_.bind(this));
},
/** @private */
- onSearchTermChanged_: function() {
- this.set('queryParams_.q', this.searchTerm || null);
+ updateQueryParams_: function() {
+ if (this.searchTerm_)
+ this.queryParams_ = {q: this.searchTerm_};
+ else
+ this.queryParams_ = {id: this.selectedId_};
},
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/shared_style.html b/chromium/chrome/browser/resources/md_bookmarks/shared_style.html
index da883670563..f242649702e 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/shared_style.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/shared_style.html
@@ -32,6 +32,38 @@
height: 32px;
margin: 0;
}
+
+ .drag-above::before,
+ .drag-below::after {
+ background-clip: padding-box;
+ background-color: var(--interactive-color);
+ border: 3px solid var(--interactive-color);
+ border-bottom-color: transparent;
+ border-radius: 0;
+ border-top-color: transparent;
+ box-sizing: border-box;
+ content: '';
+ display: block;
+ height: 8px;
+ left: 0;
+ position: absolute;
+ right: 0;
+ z-index: 10;
+ }
+
+ .drag-above::before {
+ top: 0;
+ transform: translateY(-50%);
+ }
+
+ .drag-below::after {
+ bottom: 0;
+ transform: translateY(50%);
+ }
+
+ .drag-on {
+ background-color: rgba(66, 133, 244, 0.16);
+ }
</style>
</template>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/shared_vars.html b/chromium/chrome/browser/resources/md_bookmarks/shared_vars.html
index efae3f43cf6..987f3191398 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/shared_vars.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/shared_vars.html
@@ -1,15 +1,15 @@
<style is="custom-style">
:root {
--card-max-width: 960px;
- --card-min-width: 550px;
- --folder-active-color: #4285f4;
--folder-inactive-color: #5a5a5a;
- --paper-input-container-focus-color: var(--google-blue-500);
+ --interactive-color: var(--google-blue-500);
+ --min-sidebar-width: 256px;
+ --paper-input-container-focus-color: var(--interactive-color);
--paper-input-container-input: {
font-size: 13px;
};
- --primary-text-color: #333;
- --secondary-text-color: #757575;
- --sidebar-width: 256px;
+ --primary-text-color: var(--paper-grey-900);
+ --secondary-text-color: var(--paper-grey-600);
+ --splitter-width: 15px;
};
</style>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/sidebar.html b/chromium/chrome/browser/resources/md_bookmarks/sidebar.html
index 749bf1c0ce7..6bbbd544d16 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/sidebar.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/sidebar.html
@@ -2,24 +2,27 @@
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://bookmarks/folder_node.html">
+<link rel="import" href="chrome://bookmarks/store_client.html">
<dom-module id="bookmarks-sidebar">
<template>
<style>
:host {
display: block;
+ overflow-x: hidden;
+ overflow-y: auto;
padding-top: 8px;
+ user-select: none;
}
#folder-tree {
- -webkit-padding-start: 24px;
+ -webkit-padding-start: 3px;
}
</style>
<div id="folder-tree">
<template is="dom-repeat" items="[[rootFolders]]">
- <bookmarks-folder-node item="[[item]]"
- is-selected-folder="[[item.isSelectedFolder]]">
+ <bookmarks-folder-node item-id="[[item]]" depth="0">
</bookmarks-folder-node>
</template>
</div>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/sidebar.js b/chromium/chrome/browser/resources/md_bookmarks/sidebar.js
index 9cfeb1b3803..d704a9a1814 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/sidebar.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/sidebar.js
@@ -5,7 +5,19 @@
Polymer({
is: 'bookmarks-sidebar',
+ behaviors: [
+ bookmarks.StoreClient,
+ ],
+
properties: {
+ /** @type {Array<string>} */
rootFolders: Array,
},
+
+ attached: function() {
+ this.watch('rootFolders', function(store) {
+ return store.nodes['0'].children;
+ });
+ this.updateFromStore();
+ },
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/store.html b/chromium/chrome/browser/resources/md_bookmarks/store.html
index 05c941ce9b1..a5f7057d031 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/store.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/store.html
@@ -1,10 +1,4 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://bookmarks/router.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://bookmarks/reducers.html">
+<link rel="import" href="chrome://bookmarks/util.html">
<script src="chrome://bookmarks/store.js"></script>
-
-<dom-module id="bookmarks-store">
- <template>
- <bookmarks-router id="router" search-term="[[searchTerm]]"
- selected-id="[[selectedId]]"></bookmarks-router>
- </template>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/store.js b/chromium/chrome/browser/resources/md_bookmarks/store.js
index bb4334bc513..077c6db535a 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/store.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/store.js
@@ -1,465 +1,100 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-var BookmarksStore = Polymer({
- is: 'bookmarks-store',
-
- properties: {
- /** @type {BookmarkTreeNode} */
- rootNode: {
- type: Object,
- notify: true,
- },
-
- /** @type {?string} */
- selectedId: {
- type: String,
- observer: 'updateSelectedDisplay_',
- notify: true,
- },
+/**
+ * @fileoverview A singleton datastore for the Bookmarks page. Page state is
+ * publicly readable, but can only be modified by dispatching an Action to
+ * the store.
+ */
- searchTerm: {
- type: String,
- value: '',
- observer: 'updateSearchDisplay_',
- notify: true,
- },
+cr.define('bookmarks', function() {
+ /** @constructor */
+ function Store() {
+ /** @type {!BookmarksPageState} */
+ this.data_ = bookmarks.util.createEmptyState();
+ /** @type {boolean} */
+ this.initialized_ = false;
+ /** @type {!Array<!Action>} */
+ this.queuedActions_ = [];
+ /** @type {!Array<!StoreObserver>} */
+ this.observers_ = [];
+ }
+ Store.prototype = {
/**
- * This updates to either the result of a search or the contents of the
- * selected folder.
- * @type {Array<BookmarkTreeNode>}
+ * @param {!BookmarksPageState} initialState
*/
- displayedList: {
- type: Array,
- notify: true,
- readOnly: true,
- },
-
- /** @type {Object<?string, !BookmarkTreeNode>} */
- idToNodeMap_: Object,
-
- /** @type {?number} */
- anchorIndex_: Number,
-
- /** @type {Set<string>} */
- searchResultSet_: Object,
- },
-
- /** @private {Object} */
- documentListeners_: null,
-
- /** @override */
- attached: function() {
- this.documentListeners_ = {
- 'folder-open-changed': this.onFolderOpenChanged_.bind(this),
- 'search-term-changed': this.onSearchTermChanged_.bind(this),
- 'select-item': this.onItemSelected_.bind(this),
- 'selected-folder-changed': this.onSelectedFolderChanged_.bind(this),
- };
- for (var event in this.documentListeners_)
- document.addEventListener(event, this.documentListeners_[event]);
- },
-
- /** @override */
- detached: function() {
- for (var event in this.documentListeners_)
- document.removeEventListener(event, this.documentListeners_[event]);
- },
-
- /**
- * Initializes the store with data from the bookmarks API.
- * Called by app on attached.
- */
- initializeStore: function() {
- chrome.bookmarks.getTree(function(results) {
- this.setupStore_(results[0]);
- }.bind(this));
- // Attach bookmarks API listeners.
- chrome.bookmarks.onRemoved.addListener(this.onBookmarkRemoved_.bind(this));
- chrome.bookmarks.onChanged.addListener(this.onBookmarkChanged_.bind(this));
- chrome.bookmarks.onImportBegan.addListener(this.onImportBegan_.bind(this));
- chrome.bookmarks.onImportEnded.addListener(this.onImportEnded_.bind(this));
- },
-
- //////////////////////////////////////////////////////////////////////////////
- // bookmarks-store, private:
-
- /**
- * @param {BookmarkTreeNode} rootNode
- * @private
- */
- setupStore_: function(rootNode) {
- this.rootNode = rootNode;
- this.idToNodeMap_ = {};
- this.rootNode.path = 'rootNode';
- BookmarksStore.generatePaths(rootNode, 0);
- BookmarksStore.initNodes(this.rootNode, this.idToNodeMap_);
-
- // Initialize the store's fields from the router.
- if (this.$.router.searchTerm)
- this.searchTerm = this.$.router.searchTerm;
- else
- this.fire('selected-folder-changed', this.$.router.selectedId);
- },
-
- /** @private */
- deselectFolders_: function() {
- this.unlinkPaths('displayedList');
- this.set(
- this.idToNodeMap_[this.selectedId].path + '.isSelectedFolder', false);
- this.selectedId = null;
- },
+ init: function(initialState) {
+ this.data_ = initialState;
- /**
- * @param {BookmarkTreeNode} folder
- * @private
- * @return {boolean}
- */
- isAncestorOfSelected_: function(folder) {
- if (!this.selectedId)
- return false;
-
- var selectedNode = this.idToNodeMap_[this.selectedId];
- return selectedNode.path.startsWith(folder.path);
- },
-
- /** @private */
- updateSearchDisplay_: function() {
- if (!this.rootNode)
- return;
-
- if (!this.searchTerm) {
- this.fire('selected-folder-changed', this.rootNode.children[0].id);
- } else {
- chrome.bookmarks.search(this.searchTerm, function(results) {
- this.anchorIndex_ = null;
- this.clearSelectedItems_();
- this.searchResultSet_ = new Set();
-
- if (this.selectedId)
- this.deselectFolders_();
-
- this.setupSearchResults_(results);
+ this.queuedActions_.forEach(function(action) {
+ this.reduce_(action);
}.bind(this));
- }
- },
-
- /** @private */
- updateSelectedDisplay_: function() {
- // Don't change to the selected display if ID was cleared.
- if (!this.selectedId)
- return;
-
- this.clearSelectedItems_();
- this.anchorIndex_ = null;
-
- var selectedNode = this.idToNodeMap_[this.selectedId];
- this.linkPaths('displayedList', selectedNode.path + '.children');
- this._setDisplayedList(
- /** @type {Array<BookmarkTreeNode>} */ (selectedNode.children));
- },
-
- /**
- * Remove all descendants of a given node from the map.
- * @param {string} id
- * @private
- */
- removeDescendantsFromMap_: function(id) {
- var node = this.idToNodeMap_[id];
- if (!node)
- return;
-
- if (node.children) {
- for (var i = 0; i < node.children.length; i++)
- this.removeDescendantsFromMap_(node.children[i].id);
- }
- delete this.idToNodeMap_[id];
- },
- /**
- * Remove all selected items in the list.
- * @private
- */
- clearSelectedItems_: function() {
- if (!this.displayedList)
- return;
-
- for (var i = 0; i < this.displayedList.length; i++) {
- if (!this.displayedList[i].isSelectedItem)
- continue;
-
- this.set('displayedList.#' + i + '.isSelectedItem', false);
- }
- },
-
- /**
- * Return the index in the search result of an item.
- * @param {BookmarkTreeNode} item
- * @return {number}
- * @private
- */
- getIndexInList_: function(item) {
- return this.searchTerm ? item.searchResultIndex : item.index;
- },
-
- /**
- * @param {string} id
- * @return {boolean}
- * @private
- */
- isInDisplayedList_: function(id) {
- return this.searchTerm ? this.searchResultSet_.has(id) :
- this.idToNodeMap_[id].parentId == this.selectedId;
- },
-
- /**
- * Initializes the search results returned by the API as follows:
- * - Populates |searchResultSet_| with a mapping of all result ids to
- * their corresponding result.
- * - Sets up the |searchResultIndex|.
- * @param {Array<BookmarkTreeNode>} results
- * @private
- */
- setupSearchResults_: function(results) {
- for (var i = 0; i < results.length; i++) {
- results[i].searchResultIndex = i;
- results[i].isSelectedItem = false;
- this.searchResultSet_.add(results[i].id);
- }
-
- this._setDisplayedList(results);
- },
-
- /**
- * Select multiple items based on |anchorIndex_| and the selected
- * item. If |anchorIndex_| is not set, single select the item.
- * @param {BookmarkTreeNode} item
- * @private
- */
- selectRange_: function(item) {
- var startIndex, endIndex;
- if (this.anchorIndex_ == null) {
- this.anchorIndex_ = this.getIndexInList_(item);
- startIndex = this.anchorIndex_;
- endIndex = this.anchorIndex_;
- } else {
- var selectedIndex = this.getIndexInList_(item);
- startIndex = Math.min(this.anchorIndex_, selectedIndex);
- endIndex = Math.max(this.anchorIndex_, selectedIndex);
- }
- for (var i = startIndex; i <= endIndex; i++)
- this.set('displayedList.#' + i + '.isSelectedItem', true);
- },
-
- /**
- * Selects a single item in the displayedList.
- * @param {BookmarkTreeNode} item
- * @private
- */
- selectItem_: function(item) {
- this.anchorIndex_ = this.getIndexInList_(item);
- this.set('displayedList.#' + this.anchorIndex_ + '.isSelectedItem', true);
- },
+ this.initialized_ = true;
+ this.notifyObservers_(this.data_);
+ },
- //////////////////////////////////////////////////////////////////////////////
- // bookmarks-store, bookmarks API event listeners:
+ /** @type {!BookmarksPageState} */
+ get data() {
+ return this.data_;
+ },
- /**
- * Callback for when a bookmark node is removed.
- * If a folder is selected or is an ancestor of a selected folder, the parent
- * of the removed folder will be selected.
- * @param {string} id The id of the removed bookmark node.
- * @param {!{index: number,
- * parentId: string,
- * node: BookmarkTreeNode}} removeInfo
- */
- onBookmarkRemoved_: function(id, removeInfo) {
- chrome.bookmarks.getSubTree(removeInfo.parentId, function(parentNodes) {
- var parentNode = parentNodes[0];
- var isAncestor = this.isAncestorOfSelected_(this.idToNodeMap_[id]);
- var wasInDisplayedList = this.isInDisplayedList_(id);
+ /** @return {boolean} */
+ isInitialized: function() {
+ return this.initialized_;
+ },
- // Refresh the parent node's data from the backend as its children's
- // indexes will have changed and Polymer doesn't update them.
- this.removeDescendantsFromMap_(id);
- parentNode.path = this.idToNodeMap_[parentNode.id].path;
- BookmarksStore.generatePaths(parentNode, 0);
- BookmarksStore.initNodes(parentNode, this.idToNodeMap_);
- this.set(parentNode.path, parentNode);
+ /** @param {!StoreObserver} observer */
+ addObserver: function(observer) {
+ this.observers_.push(observer);
+ },
- // Updates selectedId if the removed node is an ancestor of the current
- // selected node.
- if (isAncestor)
- this.fire('selected-folder-changed', removeInfo.parentId);
+ /** @param {!StoreObserver} observer */
+ removeObserver: function(observer) {
+ var index = this.observers_.indexOf(observer);
+ this.observers_.splice(index, 1);
+ },
- // Only update the displayedList if the removed node is in the
- // displayedList.
- if (!wasInDisplayedList)
+ /**
+ * Transition to a new UI state based on the supplied |action|, and notify
+ * observers of the change. If the Store has not yet been initialized, the
+ * action will be queued and performed upon initialization.
+ * @param {Action} action
+ */
+ handleAction: function(action) {
+ if (!this.initialized_) {
+ this.queuedActions_.push(action);
return;
-
- this.anchorIndex_ = null;
-
- // Update the currently displayed list.
- if (this.searchTerm) {
- this.updateSearchDisplay_();
- } else {
- if (!isAncestor)
- this.fire('selected-folder-changed', this.selectedId);
-
- this._setDisplayedList(parentNode.children);
}
- }.bind(this));
- },
-
- /**
- * Called when the title of a bookmark changes.
- * @param {string} id The id of changed bookmark node.
- * @param {!Object} changeInfo
- */
- onBookmarkChanged_: function(id, changeInfo) {
- if (changeInfo.title)
- this.set(this.idToNodeMap_[id].path + '.title', changeInfo.title);
- if (changeInfo.url)
- this.set(this.idToNodeMap_[id].path + '.url', changeInfo.url);
-
- if (this.searchTerm)
- this.updateSearchDisplay_();
- },
-
- /**
- * Called when importing bookmark is started.
- */
- onImportBegan_: function() {
- // TODO(rongjie): pause onCreated once this event is used.
- },
-
- /**
- * Called when importing bookmark node is finished.
- */
- onImportEnded_: function() {
- chrome.bookmarks.getTree(function(results) {
- this.setupStore_(results[0]);
- this.updateSelectedDisplay_();
- }.bind(this));
- },
-
- //////////////////////////////////////////////////////////////////////////////
- // bookmarks-store, bookmarks app event listeners:
-
- /**
- * @param {Event} e
- * @private
- */
- onSearchTermChanged_: function(e) {
- this.searchTerm = /** @type {string} */ (e.detail);
- },
-
- /**
- * Selects the folder specified by the event and deselects the previously
- * selected folder.
- * @param {CustomEvent} e
- * @private
- */
- onSelectedFolderChanged_: function(e) {
- if (this.searchTerm)
- this.searchTerm = '';
-
- // Deselect the old folder if defined.
- if (this.selectedId && this.idToNodeMap_[this.selectedId])
- this.set(
- this.idToNodeMap_[this.selectedId].path + '.isSelectedFolder', false);
-
- // Check if the selected id is that of a defined folder.
- var id = /** @type {string} */ (e.detail);
- if (!this.idToNodeMap_[id] || this.idToNodeMap_[id].url)
- id = this.rootNode.children[0].id;
-
- var folder = this.idToNodeMap_[id];
- this.set(folder.path + '.isSelectedFolder', true);
- this.selectedId = id;
-
- if (folder.id == this.rootNode.id)
- return;
- var parent = this.idToNodeMap_[/** @type {?string} */ (folder.parentId)];
- while (parent) {
- if (!parent.isOpen) {
- this.fire('folder-open-changed', {
- id: parent.id,
- open: true,
- });
- }
+ this.reduce_(action);
+ this.notifyObservers_(this.data_);
+ },
- parent = this.idToNodeMap_[/** @type {?string} */ (parent.parentId)];
- }
- },
+ /**
+ * @param {Action} action
+ * @private
+ */
+ reduce_: function(action) {
+ this.data_ = bookmarks.reduceAction(this.data_, action);
+ },
- /**
- * Handles events that open and close folders.
- * @param {CustomEvent} e
- * @private
- */
- onFolderOpenChanged_: function(e) {
- var folder = this.idToNodeMap_[e.detail.id];
- this.set(folder.path + '.isOpen', e.detail.open);
- if (!folder.isOpen && this.isAncestorOfSelected_(folder))
- this.fire('selected-folder-changed', folder.id);
- },
+ /**
+ * @param {!BookmarksPageState} state
+ * @private
+ */
+ notifyObservers_: function(state) {
+ this.observers_.forEach(function(o) {
+ o.onStateChanged(state);
+ });
+ },
+ };
- /**
- * Selects items according to keyboard behaviours.
- * @param {CustomEvent} e
- * @private
- */
- onItemSelected_: function(e) {
- if (!e.detail.add)
- this.clearSelectedItems_();
+ cr.addSingletonGetter(Store);
- if (e.detail.range)
- this.selectRange_(e.detail.item);
- else
- this.selectItem_(e.detail.item);
- },
+ return {
+ Store: Store,
+ };
});
-
-////////////////////////////////////////////////////////////////////////////////
-// bookmarks-store, static methods:
-
-/**
- * Stores the path from the store to a node inside the node.
- * @param {BookmarkTreeNode} bookmarkNode
- * @param {number} startIndex
- */
-BookmarksStore.generatePaths = function(bookmarkNode, startIndex) {
- if (!bookmarkNode.children)
- return;
-
- for (var i = startIndex; i < bookmarkNode.children.length; i++) {
- bookmarkNode.children[i].path = bookmarkNode.path + '.children.#' + i;
- BookmarksStore.generatePaths(bookmarkNode.children[i], 0);
- }
-};
-
-/**
- * Initializes the nodes in the bookmarks tree as follows:
- * - Populates |idToNodeMap_| with a mapping of all node ids to their
- * corresponding BookmarkTreeNode.
- * - Sets all the nodes to not selected and open by default.
- * @param {BookmarkTreeNode} bookmarkNode
- * @param {Object=} idToNodeMap
- */
-BookmarksStore.initNodes = function(bookmarkNode, idToNodeMap) {
- bookmarkNode.isSelectedItem = false;
- if (idToNodeMap)
- idToNodeMap[bookmarkNode.id] = bookmarkNode;
-
- if (bookmarkNode.url)
- return;
-
- bookmarkNode.isSelectedFolder = false;
- bookmarkNode.isOpen = true;
- for (var i = 0; i < bookmarkNode.children.length; i++)
- BookmarksStore.initNodes(bookmarkNode.children[i], idToNodeMap);
-};
diff --git a/chromium/chrome/browser/resources/md_bookmarks/store_client.html b/chromium/chrome/browser/resources/md_bookmarks/store_client.html
new file mode 100644
index 00000000000..3c5fb29d0b1
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/store_client.html
@@ -0,0 +1,4 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://bookmarks/store.html">
+
+<script src="chrome://bookmarks/store_client.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/store_client.js b/chromium/chrome/browser/resources/md_bookmarks/store_client.js
new file mode 100644
index 00000000000..7d151273496
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/store_client.js
@@ -0,0 +1,98 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Defines StoreClient, a Polymer behavior to tie a front-end
+ * element to back-end data from the store.
+ */
+
+cr.define('bookmarks', function() {
+ /**
+ * @polymerBehavior
+ * @implements {StoreObserver}
+ */
+ var StoreClient = {
+ created: function() {
+ /**
+ * @type {!Array<{
+ * localProperty: string,
+ * valueGetter: function(!BookmarksPageState)
+ * }>}
+ */
+ this.watches_ = [];
+ },
+
+ attached: function() {
+ bookmarks.Store.getInstance().addObserver(this);
+ },
+
+ detached: function() {
+ bookmarks.Store.getInstance().removeObserver(this);
+ },
+
+ /**
+ * Watches a particular part of the state tree, updating |localProperty|
+ * to the return value of |valueGetter| whenever the state changes. Eg, to
+ * keep |this.item| updated with the value of a node:
+ * watch('item', (state) => state.nodes[this.itemId]);
+ *
+ * Note that object identity is used to determine if the value has changed
+ * before updating the UI, rather than Polymer-style deep equality. If the
+ * getter function returns |undefined|, no changes will propagate to the UI.
+ *
+ * Typechecking is supressed because this conflicts with
+ * Object.prototype.watch, which is a Gecko-only method that is recognized
+ * by Closure.
+ * @suppress {checkTypes}
+ * @param {string} localProperty
+ * @param {function(!BookmarksPageState)} valueGetter
+ */
+ watch: function(localProperty, valueGetter) {
+ // TODO(tsergeant): Warn if localProperty is not a defined property.
+ this.watches_.push({
+ localProperty: localProperty,
+ valueGetter: valueGetter,
+ });
+ },
+
+ /**
+ * Helper to dispatch an action to the store, which will update the store
+ * data and then (possibly) flow through to the UI.
+ * @param {Action} action
+ */
+ dispatch: function(action) {
+ bookmarks.Store.getInstance().handleAction(action);
+ },
+
+ /** @param {string} newState */
+ onStateChanged: function(newState) {
+ this.watches_.forEach(function(watch) {
+ var oldValue = this[watch.localProperty];
+ var newValue = watch.valueGetter(newState);
+
+ // Avoid poking Polymer unless something has actually changed. Reducers
+ // must return new objects rather than mutating existing objects, so
+ // any real changes will pass through correctly.
+ if (oldValue == newValue || newValue == undefined)
+ return;
+
+ this[watch.localProperty] = newValue;
+ }.bind(this));
+ },
+
+ updateFromStore: function() {
+ if (bookmarks.Store.getInstance().isInitialized())
+ this.onStateChanged(bookmarks.Store.getInstance().data);
+ },
+
+ /** @return {!BookmarksPageState} */
+ getState: function() {
+ return bookmarks.Store.getInstance().data;
+ },
+ };
+
+ return {
+ StoreClient: StoreClient,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/toolbar.html b/chromium/chrome/browser/resources/md_bookmarks/toolbar.html
index 75f566fbd5d..90d4655bc97 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/toolbar.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/toolbar.html
@@ -1,7 +1,9 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://bookmarks/edit_dialog.html">
<link rel="import" href="chrome://bookmarks/shared_style.html">
<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
@@ -17,22 +19,23 @@
}
cr-toolbar {
- --cr-toolbar-field-margin: var(--sidebar-width);
+ --cr-toolbar-field-margin:
+ calc(var(--sidebar-width) + var(--splitter-width));
background: var(--md-toolbar-color);
}
</style>
<dialog is="cr-action-menu" id="dropdown">
- <button class="dropdown-item" on-tap="onBulkEditTap_">
- $i18n{menuBulkEdit}
- </button>
- <button class="dropdown-item" on-tap="onSortTap_">
+ <button class="dropdown-item" on-tap="onSortTap_"
+ disabled="[[hasSearchTerm_(searchTerm_)]]">
$i18n{menuSort}
</button>
<hr>
- <button class="dropdown-item" on-tap="onAddBookmarkTap_">
+ <button class="dropdown-item" on-tap="onAddBookmarkTap_"
+ disabled="[[hasSearchTerm_(searchTerm_)]]">
$i18n{menuAddBookmark}
</button>
- <button class="dropdown-item" on-tap="onAddFolderTap_">
+ <button class="dropdown-item" on-tap="onAddFolderTap_"
+ disabled="[[hasSearchTerm_(searchTerm_)]]">
$i18n{menuAddFolder}
</button>
<hr>
@@ -54,6 +57,9 @@
<div></div>
</button>
</cr-toolbar>
+ <template is="cr-lazy-render" id="addDialog">
+ <bookmarks-edit-dialog></bookmarks-edit-dialog>
+ </template>
</template>
<script src="chrome://bookmarks/toolbar.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/toolbar.js b/chromium/chrome/browser/resources/md_bookmarks/toolbar.js
index 5b80c74fbef..8dacb67e248 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/toolbar.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/toolbar.js
@@ -5,11 +5,27 @@
Polymer({
is: 'bookmarks-toolbar',
+ behaviors: [
+ bookmarks.StoreClient,
+ ],
+
properties: {
- searchTerm: {
+ /** @private */
+ searchTerm_: {
type: String,
observer: 'onSearchTermChanged_',
},
+
+ sidebarWidth: {
+ type: String,
+ observer: 'onSidebarWidthChanged_',
+ },
+ },
+
+ attached: function() {
+ this.watch('searchTerm_', function(state) {
+ return state.search.term;
+ });
},
/** @return {CrToolbarSearchFieldElement} */
@@ -28,17 +44,24 @@ Polymer({
},
/** @private */
- onBulkEditTap_: function() {
+ onSortTap_: function() {
+ chrome.bookmarkManagerPrivate.sortChildren(
+ assert(this.getState().selectedFolder));
this.closeDropdownMenu_();
},
/** @private */
- onSortTap_: function() {
+ onAddBookmarkTap_: function() {
+ var dialog =
+ /** @type {BookmarksEditDialogElement} */ (this.$.addDialog.get());
+ dialog.showAddDialog(false, assert(this.getState().selectedFolder));
this.closeDropdownMenu_();
},
- /** @private */
- onAddBookmarkTap_: function() {
+ onAddFolderTap_: function() {
+ var dialog =
+ /** @type {BookmarksEditDialogElement} */ (this.$.addDialog.get());
+ dialog.showAddDialog(true, assert(this.getState().selectedFolder));
this.closeDropdownMenu_();
},
@@ -66,11 +89,24 @@ Polymer({
*/
onSearchChanged_: function(e) {
var searchTerm = /** @type {string} */ (e.detail);
- this.fire('search-term-changed', searchTerm);
+ if (searchTerm != this.searchTerm_)
+ this.dispatch(bookmarks.actions.setSearchTerm(searchTerm));
+ },
+
+ onSidebarWidthChanged_: function() {
+ this.style.setProperty('--sidebar-width', this.sidebarWidth);
},
/** @private */
onSearchTermChanged_: function() {
- this.searchField.setValue(this.searchTerm || '');
+ this.searchField.setValue(this.searchTerm_ || '');
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ hasSearchTerm_: function() {
+ return !!this.searchTerm_;
},
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/types.js b/chromium/chrome/browser/resources/md_bookmarks/types.js
new file mode 100644
index 00000000000..8eb1a37c08b
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/types.js
@@ -0,0 +1,92 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Closure typedefs for MD Bookmarks.
+ */
+
+/**
+ * A normalized version of chrome.bookmarks.BookmarkTreeNode.
+ * @typedef {{
+ * id: string,
+ * parentId: (string|undefined),
+ * url: (string|undefined),
+ * title: string,
+ * dateAdded: (number|undefined),
+ * dateGroupModified: (number|undefined),
+ * unmodifiable: (string|undefined),
+ * children: (!Array<string>|undefined),
+ * }}
+ */
+var BookmarkNode;
+
+/**
+ * @typedef {!Object<string, BookmarkNode>}
+ */
+var NodeList;
+
+/**
+ * @typedef {{
+ * items: !Set<string>,
+ * anchor: ?string,
+ * }}
+ *
+ * |items| is used as a set and all values in the map are true.
+ */
+var SelectionState;
+
+/**
+ * @typedef {{
+ * term: string,
+ * inProgress: boolean,
+ * results: !Array<string>,
+ * }}
+ */
+var SearchState;
+
+/** @typedef {!Set<string>} */
+var ClosedFolderState;
+
+/**
+ * @typedef {{
+ * nodes: NodeList,
+ * selectedFolder: string,
+ * closedFolders: ClosedFolderState,
+ * search: SearchState,
+ * selection: SelectionState,
+ * }}
+ */
+var BookmarksPageState;
+
+/** @typedef {{name: string}} */
+var Action;
+
+/** @typedef {{element: BookmarkElement, position: DropPosition}} */
+var DropDestination;
+
+/**
+ * @record
+ */
+function BookmarkElement() {}
+
+/** @type {string} */
+BookmarkElement.itemId;
+
+/** @return {HTMLElement} */
+BookmarkElement.getDropTarget = function() {};
+
+/** @constructor */
+function DragData() {
+ /** @type {Array<BookmarkTreeNode>} */
+ this.elements = null;
+
+ /** @type {boolean} */
+ this.sameProfile = false;
+}
+
+/** @interface */
+function StoreObserver(){};
+
+/** @param {!BookmarksPageState} newState */
+StoreObserver.prototype.onStateChanged = function(newState) {};
diff --git a/chromium/chrome/browser/resources/md_bookmarks/util.html b/chromium/chrome/browser/resources/md_bookmarks/util.html
new file mode 100644
index 00000000000..cd198424063
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/util.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://bookmarks/util.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/util.js b/chromium/chrome/browser/resources/md_bookmarks/util.js
new file mode 100644
index 00000000000..c6e4c001bb3
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/util.js
@@ -0,0 +1,176 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Utility functions for the Bookmarks page.
+ */
+
+cr.define('bookmarks.util', function() {
+ /**
+ * Returns the list of bookmark IDs to be displayed in the UI, taking into
+ * account search and the currently selected folder.
+ * @param {!BookmarksPageState} state
+ * @return {!Array<string>}
+ */
+ function getDisplayedList(state) {
+ if (!isShowingSearch(state))
+ return assert(state.nodes[state.selectedFolder].children);
+
+ return state.search.results;
+ }
+
+ /**
+ * @param {BookmarkTreeNode} treeNode
+ * @return {BookmarkNode}
+ */
+ function normalizeNode(treeNode) {
+ var node = Object.assign({}, treeNode);
+ // Node index is not necessary and not kept up-to-date. Remove it from the
+ // data structure so we don't accidentally depend on the incorrect
+ // information.
+ delete node.index;
+
+ if (!('url' in node)) {
+ // The onCreated API listener returns folders without |children| defined.
+ node.children = (node.children || []).map(function(child) {
+ return child.id;
+ });
+ }
+ return /** @type {BookmarkNode} */ (node);
+ }
+
+ /**
+ * @param {BookmarkTreeNode} rootNode
+ * @return {NodeList}
+ */
+ function normalizeNodes(rootNode) {
+ /** @type {NodeList} */
+ var nodeList = {};
+ var stack = [];
+ stack.push(rootNode);
+
+ while (stack.length > 0) {
+ var node = stack.pop();
+ nodeList[node.id] = normalizeNode(node);
+ if (!node.children)
+ continue;
+
+ node.children.forEach(function(child) {
+ stack.push(child);
+ });
+ }
+
+ return nodeList;
+ }
+
+ /** @return {!BookmarksPageState} */
+ function createEmptyState() {
+ return {
+ nodes: {},
+ selectedFolder: '0',
+ closedFolders: new Set(),
+ search: {
+ term: '',
+ inProgress: false,
+ results: [],
+ },
+ selection: {
+ items: new Set(),
+ anchor: null,
+ },
+ };
+ }
+
+ /**
+ * @param {BookmarksPageState} state
+ * @return {boolean}
+ */
+ function isShowingSearch(state) {
+ return !!state.search.term && !state.search.inProgress;
+ }
+
+ /**
+ * @param {string} id
+ * @param {NodeList} nodes
+ * @return {boolean}
+ */
+ function hasChildFolders(id, nodes) {
+ var children = nodes[id].children;
+ for (var i = 0; i < children.length; i++) {
+ if (nodes[children[i]].children)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get all descendants of a node, including the node itself.
+ * @param {NodeList} nodes
+ * @param {string} baseId
+ * @return {!Set<string>}
+ */
+ function getDescendants(nodes, baseId) {
+ var descendants = new Set();
+ var stack = [];
+ stack.push(baseId);
+
+ while (stack.length > 0) {
+ var id = stack.pop();
+ var node = nodes[id];
+
+ if (!node)
+ continue;
+
+ descendants.add(id);
+
+ if (!node.children)
+ continue;
+
+ node.children.forEach(function(childId) {
+ stack.push(childId);
+ });
+ }
+
+ return descendants;
+ }
+
+ /**
+ * @param {!Object<string, T>} map
+ * @param {!Set<string>} ids
+ * @return {!Object<string, T>}
+ * @template T
+ */
+ function removeIdsFromMap(map, ids) {
+ var newMap = Object.assign({}, map);
+ ids.forEach(function(id) {
+ delete newMap[id];
+ });
+ return newMap;
+ }
+
+ /**
+ * @param {!Set<string>} set
+ * @param {!Set<string>} ids
+ * @return {!Set<string>}
+ */
+ function removeIdsFromSet(set, ids) {
+ var difference = new Set(set);
+ ids.forEach(function(id) {
+ difference.delete(id);
+ });
+ return difference;
+ }
+
+ return {
+ createEmptyState: createEmptyState,
+ getDescendants: getDescendants,
+ getDisplayedList: getDisplayedList,
+ hasChildFolders: hasChildFolders,
+ isShowingSearch: isShowingSearch,
+ normalizeNode: normalizeNode,
+ normalizeNodes: normalizeNodes,
+ removeIdsFromMap: removeIdsFromMap,
+ removeIdsFromSet: removeIdsFromSet,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_downloads/OWNERS b/chromium/chrome/browser/resources/md_downloads/OWNERS
index cba869d6b8a..455bfb52fad 100644
--- a/chromium/chrome/browser/resources/md_downloads/OWNERS
+++ b/chromium/chrome/browser/resources/md_downloads/OWNERS
@@ -1 +1,3 @@
dbeam@chromium.org
+
+# COMPONENT: UI>Browser>Downloads
diff --git a/chromium/chrome/browser/resources/md_downloads/downloads.html b/chromium/chrome/browser/resources/md_downloads/downloads.html
index 19873360d12..789c1d5fdcf 100644
--- a/chromium/chrome/browser/resources/md_downloads/downloads.html
+++ b/chromium/chrome/browser/resources/md_downloads/downloads.html
@@ -1,16 +1,22 @@
<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading">
<head>
<meta charset="utf-8">
<title>$i18n{title}</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
<style>
html {
- background: var(--md-background-color);
+ --downloads-card-margin: 24px;
+ --downloads-card-width: 640px;
+ background: #f1f1f1;
+ }
+
+ .loading {
+ /* --google-blue-700 disguised. Replaced when downloads-toolbar loads. */
+ border-top: 56px solid rgb(51, 103, 214);
}
- html,
+ html:not(.loading),
body {
height: 100%;
}
@@ -19,11 +25,6 @@
display: flex;
margin: 0;
}
-
- :root {
- --downloads-card-margin: 24px;
- --downloads-card-width: 640px;
- }
</style>
</head>
<body>
diff --git a/chromium/chrome/browser/resources/md_downloads/focus_row.js b/chromium/chrome/browser/resources/md_downloads/focus_row.js
deleted file mode 100644
index 7963c4037a3..00000000000
--- a/chromium/chrome/browser/resources/md_downloads/focus_row.js
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('downloads', function() {
- /**
- * @param {!Element} root
- * @param {?Node} boundary
- * @constructor
- * @extends {cr.ui.FocusRow}
- */
- function FocusRow(root, boundary) {
- cr.ui.FocusRow.call(this, root, boundary);
- this.addItems();
- }
-
- FocusRow.prototype = {
- __proto__: cr.ui.FocusRow.prototype,
-
- addItems: function() {
- this.destroy();
-
- this.addItem('name-file-link',
- 'content.is-active:not(.show-progress):not(.dangerous) #name');
- assert(this.addItem('name-file-link', '#file-link'));
- assert(this.addItem('url', '#url'));
- this.addItem('show-retry', '#show');
- this.addItem('show-retry', '#retry');
- this.addItem('pause-resume', '#pause');
- this.addItem('pause-resume', '#resume');
- this.addItem('cancel', '#cancel');
- this.addItem('controlled-by', '#controlled-by a');
- this.addItem('danger-remove-discard', '#discard');
- this.addItem('restore-save', '#save');
- this.addItem('danger-remove-discard', '#danger-remove');
- this.addItem('restore-save', '#restore');
- assert(this.addItem('remove', '#remove'));
-
- // TODO(dbeam): it would be nice to do this asynchronously (so if multiple
- // templates get rendered we only re-add once), but Manager#updateItem_()
- // relies on the DOM being re-rendered synchronously.
- this.eventTracker.add(this.root, 'dom-change', this.addItems.bind(this));
- },
- };
-
- return {FocusRow: FocusRow};
-});
diff --git a/chromium/chrome/browser/resources/md_downloads/item.html b/chromium/chrome/browser/resources/md_downloads/item.html
index 98d711f9b76..f0577352179 100644
--- a/chromium/chrome/browser/resources/md_downloads/item.html
+++ b/chromium/chrome/browser/resources/md_downloads/item.html
@@ -7,6 +7,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
<link rel="import" href="chrome://downloads/action_service.html">
<link rel="import" href="chrome://downloads/constants.html">
diff --git a/chromium/chrome/browser/resources/md_downloads/manager.html b/chromium/chrome/browser/resources/md_downloads/manager.html
index fa6a52955c9..34aa9e984c6 100644
--- a/chromium/chrome/browser/resources/md_downloads/manager.html
+++ b/chromium/chrome/browser/resources/md_downloads/manager.html
@@ -10,7 +10,6 @@
<link rel="import" href="chrome://downloads/i18n_setup.html">
<link rel="import" href="chrome://downloads/item.html">
<link rel="import" href="chrome://downloads/toolbar.html">
-<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
<dom-module id="downloads-manager">
<template>
@@ -94,7 +93,8 @@
}
</style>
- <downloads-toolbar id="toolbar" spinner-active="{{spinnerActive_}}">
+ <downloads-toolbar id="toolbar" spinner-active="{{spinnerActive_}}"
+ role="none">
</downloads-toolbar>
<iron-list id="downloads-list" items="{{items_}}"
hidden="[[!hasDownloads_]]">
diff --git a/chromium/chrome/browser/resources/md_downloads/manager.js b/chromium/chrome/browser/resources/md_downloads/manager.js
index d01c3d336a9..ec56d515419 100644
--- a/chromium/chrome/browser/resources/md_downloads/manager.js
+++ b/chromium/chrome/browser/resources/md_downloads/manager.js
@@ -40,6 +40,7 @@ cr.define('downloads', function() {
},
hostAttributes: {
+ // TODO(dbeam): this should use a class instead.
loading: true,
},
@@ -52,6 +53,10 @@ cr.define('downloads', function() {
'itemsChanged_(items_.*)',
],
+ attached: function() {
+ document.documentElement.classList.remove('loading');
+ },
+
/** @private {!PromiseResolver} */
loaded_: new PromiseResolver,
diff --git a/chromium/chrome/browser/resources/md_downloads/toolbar.html b/chromium/chrome/browser/resources/md_downloads/toolbar.html
index da1cb35f110..bda557e498f 100644
--- a/chromium/chrome/browser/resources/md_downloads/toolbar.html
+++ b/chromium/chrome/browser/resources/md_downloads/toolbar.html
@@ -5,6 +5,7 @@
<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -14,7 +15,7 @@
<style>
:host {
align-items: center;
- background: var(--md-toolbar-color);
+ background: var(--google-blue-700);
color: white;
display: flex;
min-height: 56px;
diff --git a/chromium/chrome/browser/resources/md_extensions/OWNERS b/chromium/chrome/browser/resources/md_extensions/OWNERS
index 209719ed1cf..9f0111412ab 100644
--- a/chromium/chrome/browser/resources/md_extensions/OWNERS
+++ b/chromium/chrome/browser/resources/md_extensions/OWNERS
@@ -1,2 +1,5 @@
rdevlin.cronin@chromium.org
dbeam@chromium.org
+
+# TEAM: extensions-dev@chromium.org
+# COMPONENT: Platform>Extensions
diff --git a/chromium/chrome/browser/resources/md_extensions/animation_helper.js b/chromium/chrome/browser/resources/md_extensions/animation_helper.js
index be9f9651823..a429f18475a 100644
--- a/chromium/chrome/browser/resources/md_extensions/animation_helper.js
+++ b/chromium/chrome/browser/resources/md_extensions/animation_helper.js
@@ -37,52 +37,57 @@ cr.define('extensions', function() {
AnimationHelper.prototype = {
/**
* Set the entry animation for the element.
- * @param {extensions.Animation} animation
+ * @param {!Array<extensions.Animation>} animations
*/
- setEntryAnimation: function(animation) {
- var config;
- switch (animation) {
- case extensions.Animation.HERO:
- config = {name: 'hero-animation', id: 'hero', toPage: this.element_};
- break;
- case extensions.Animation.FADE_IN:
- assert(this.node_);
- config = {name: 'fade-in-animation', node: this.node_};
- break;
- default:
- assertNotReached();
+ setEntryAnimations: function(animations) {
+ var configs = [];
+ for (let animation of animations) {
+ switch (animation) {
+ case extensions.Animation.HERO:
+ configs.push(
+ {name: 'hero-animation', id: 'hero', toPage: this.element_});
+ break;
+ case extensions.Animation.FADE_IN:
+ assert(this.node_);
+ configs.push({name: 'fade-in-animation', node: this.node_});
+ break;
+ default:
+ assertNotReached();
+ }
}
- this.element_.animationConfig.entry = [config];
+ this.element_.animationConfig.entry = configs;
},
/**
* Set the exit animation for the element.
- * @param {extensions.Animation} animation
+ * @param {!Array<extensions.Animation>} animations
*/
- setExitAnimation: function(animation) {
- var config;
- switch (animation) {
- case extensions.Animation.HERO:
- config =
- {name: 'hero-animation', id: 'hero', fromPage: this.element_};
- break;
- case extensions.Animation.FADE_OUT:
- assert(this.node_);
- config = {name: 'fade-out-animation', node: this.node_};
- break;
- case extensions.Animation.SCALE_DOWN:
- assert(this.node_);
- config = {
- name: 'scale-down-animation',
- node: this.node_,
- transformOrigin: '50% 50%',
- axis: 'y',
- };
- break;
- default:
- assertNotReached();
+ setExitAnimations: function(animations) {
+ var configs = [];
+ for (let animation of animations) {
+ switch (animation) {
+ case extensions.Animation.HERO:
+ configs.push(
+ {name: 'hero-animation', id: 'hero', fromPage: this.element_});
+ break;
+ case extensions.Animation.FADE_OUT:
+ assert(this.node_);
+ configs.push({name: 'fade-out-animation', node: this.node_});
+ break;
+ case extensions.Animation.SCALE_DOWN:
+ assert(this.node_);
+ configs.push({
+ name: 'scale-down-animation',
+ node: this.node_,
+ transformOrigin: '50% 50%',
+ axis: 'y',
+ });
+ break;
+ default:
+ assertNotReached();
+ }
}
- this.element_.animationConfig.exit = [config];
+ this.element_.animationConfig.exit = configs;
},
};
diff --git a/chromium/chrome/browser/resources/md_extensions/code_section.html b/chromium/chrome/browser/resources/md_extensions/code_section.html
index 207eb1540e1..88d32c6b124 100644
--- a/chromium/chrome/browser/resources/md_extensions/code_section.html
+++ b/chromium/chrome/browser/resources/md_extensions/code_section.html
@@ -40,7 +40,7 @@
text-align: center;
}
</style>
- <div id="main" hidden$="[[isMainHidden_(code)]]">
+ <div id="main" hidden$="[[isEmpty(code)]]">
<div id="line-numbers">
<span>[[computeLineNumbersContent_(code.*)]]</span>
</div>
@@ -51,7 +51,7 @@
--></span>[[code.afterHighlight]]</span>
</div>
</div>
- <div id="no-code" hidden$="[[!isMainHidden_(code)]]">[[noCodeError]]</div>
+ <div id="no-code" hidden$="[[!isEmpty(code)]]">[[couldNotDisplayCode]]</div>
</template>
<script src="chrome://extensions/code_section.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/code_section.js b/chromium/chrome/browser/resources/md_extensions/code_section.js
index d0a93e2aac2..502c86dc1ff 100644
--- a/chromium/chrome/browser/resources/md_extensions/code_section.js
+++ b/chromium/chrome/browser/resources/md_extensions/code_section.js
@@ -21,10 +21,22 @@ cr.define('extensions', function() {
},
/**
- * The string to display if no code is set.
+ * The string to display if no |code| is set (e.g. because we couldn't
+ * load the relevant source file).
* @type {string}
*/
- noCodeError: String,
+ couldNotDisplayCode: String,
+ },
+
+ /**
+ * Returns true if no code could be displayed (e.g. because the file could
+ * not be loaded).
+ * @return {boolean}
+ */
+ isEmpty: function() {
+ return !this.code ||
+ (!this.code.beforeHighlight && !this.code.highlight &&
+ !this.code.afterHighlight);
},
/**
@@ -46,14 +58,6 @@ cr.define('extensions', function() {
textContent += i + '\n';
return textContent;
},
-
- /**
- * @return {boolean}
- * @private
- */
- isMainHidden_: function() {
- return !this.code;
- },
});
return {CodeSection: CodeSection};
diff --git a/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
index b6e9227852a..90c0c0029b3 100644
--- a/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
@@ -30,7 +30,7 @@
'<(EXTERNS_GYP):developer_private',
'animation_helper',
'item',
- 'item_source',
+ 'item_util',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -73,7 +73,7 @@
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(EXTERNS_GYP):developer_private',
- 'item_source',
+ 'item_util',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -92,7 +92,7 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'item_source',
+ 'target_name': 'item_util',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
@@ -113,8 +113,18 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'load_error',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):developer_private',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'manager',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_drawer/compiled_resources2.gyp:cr_drawer',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
@@ -123,8 +133,10 @@
'detail_view',
'item',
'item_list',
+ 'load_error',
'keyboard_shortcuts',
'sidebar',
+ 'toolbar',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -154,9 +166,10 @@
'<(EXTERNS_GYP):management',
'error_page',
'item',
+ 'load_error',
'manager',
'pack_dialog',
- 'sidebar',
+ 'toolbar',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -180,5 +193,14 @@
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'toolbar',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
]
}
diff --git a/chromium/chrome/browser/resources/md_extensions/detail_view.html b/chromium/chrome/browser/resources/md_extensions/detail_view.html
index 3d792cbf6db..d9fb22ad877 100644
--- a/chromium/chrome/browser/resources/md_extensions/detail_view.html
+++ b/chromium/chrome/browser/resources/md_extensions/detail_view.html
@@ -1,13 +1,14 @@
<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html">
<link rel="import" href="chrome://extensions/animation_helper.html">
-<link rel="import" href="chrome://extensions/item_source.html">
+<link rel="import" href="chrome://extensions/item_util.html">
<dom-module id="extensions-detail-view">
<style include="iron-flex"></style>
@@ -17,21 +18,34 @@
display: none !important;
}
+ :host {
+ display: flex;
+ justify-content: center;
+ }
+
#main {
background-color: white;
- height: 800px;
- width: 90%;
+ height: 100%;
+ width: 640px;
}
#top-bar {
align-items: center;
- color: var(--paper-grey-600);
+ color: #5a5a5a;
display: flex;
+ font-size: 14px;
height: 40px;
- margin-bottom: 30px;
+ margin-bottom: 12px;
padding: 8px 12px 0;
}
+ #icon {
+ -webkit-margin-end: 8px;
+ -webkit-margin-start: 20px;
+ height: 24px;
+ width: 24px;
+ }
+
a paper-icon-button {
color: var(--paper-grey-600);
}
@@ -40,9 +54,26 @@
flex-grow: 1;
}
+ .control-line {
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .control-line span {
+ color: #333;
+ }
+
+ #enable-section {
+ height: 48px;
+ margin-bottom: 8px;
+ padding: 0 20px;
+ }
+
.section {
border-bottom: 1px solid var(--paper-grey-400);
- padding: 12px 20px;
+ font-size: 13px;
+ padding: 16px 20px;
}
.section:last-child {
@@ -50,42 +81,62 @@
}
.section-title {
- color: var(--paper-grey-800);
+ color: #333;
+ margin-bottom: 12px;
}
.section-content {
- color: var(--paper-grey-600);
+ color: #646464;
}
- .section paper-checkbox {
- align-items: center;
- display: flex;
- min-height: 40px;
+ #options-section {
+ padding: 7px 20px;
+ }
+
+ #options-section .control-line {
+ height: 52px;
}
- paper-checkbox {
- --paper-checkbox-checked-color: var(--google-blue-500);
- --primary-text-color: var(--paper-grey-800);
+ .actionable {
+ cursor: pointer;
+ }
+
+ .inspectable-view {
+ color: var(--google-blue-700);
+ height: 20px;
+ width: auto; /* override the default button size of 24x24 */
}
ul {
-webkit-padding-start: 20px;
margin: 0;
}
+
+ button[is='paper-icon-button-light'].action-arrow {
+ background-image: url(chrome://resources/images/arrow_right.svg);
+ }
+
+ button[is='paper-icon-button-light'].open-in-new {
+ background-image: url(chrome://resources/images/open_in_new.svg);
+ background-size: contain;
+ height: 20px;
+ width: 20px;
+ }
</style>
<div id="main">
<div id="top-bar">
<paper-icon-button id="close-button" icon="arrow-back"
on-tap="onCloseButtonTap_"></paper-icon-button>
+ <img alt="" id="icon" src="[[data.iconUrl]]">
<span id="name">[[data.name]]</span>
- <a id="open-homepage" href="[[data.homePage.url]]" tabindex="-1"
- target="_blank" hidden$="[[!shouldShowHomepageButton_(data.*)]]">
- <paper-icon-button icon="open-in-new"></paper-icon-button>
- </a>
- <paper-icon-button id="options" icon="settings"
- on-tap="onOptionsButtonTap_"
- hidden$="[[!shouldShowOptionsButton_(data.*)]]">
- </paper-icon-button>
+ </div>
+ <div class="control-line" id="enable-section">
+ <span>[[computeEnabledText_(data.*)]]</span>
+ <paper-toggle-button id="enable-toggle"
+ checked="[[isEnabled_(data.state)]]"
+ on-change="onEnableChange_"
+ enabled="[[isEnableToggleEnabled_(data)]]">
+ </paper-toggle-button>
</div>
<div class="section">
<div class="section-title">$i18n{itemDescriptionLabel}</div>
@@ -95,6 +146,25 @@
<div class="section-title">$i18n{itemVersion}</div>
<div class="section-content">[[data.version]]</div>
</div>
+ <div class="section" id="id-section" hidden$="[[!inDevMode]]">
+ <div class="section-title">$i18n{itemIdHeading}</div>
+ <div class="section-content">[[data.id]]</div>
+ </div>
+ <div class="section" id="inspectable-views" hidden$="[[!inDevMode]]">
+ <div class="section-title">$i18n{itemInspectViews}</div>
+ <div class="section-content">
+ <ul id="inspect-views">
+ <template is="dom-repeat" items="[[data.views]]">
+ <li>
+ <button class="inspectable-view" on-tap="onInspectTap_"
+ is="paper-icon-button-light">
+ [[computeInspectLabel_(item)]]
+ </button>
+ </li>
+ </template>
+ </ul>
+ </div>
+ </div>
<div class="section">
<div class="section-title">$i18n{itemPermissions}</div>
<div class="section-content">
@@ -124,37 +194,56 @@
</div>
</template>
<template is="dom-if" if="[[shouldShowOptionsSection_(data.*)]]">
- <div class="section layout vertical">
+ <div class="section layout vertical" id="options-section">
<template is="dom-if" if="[[data.incognitoAccess.isEnabled]]">
- <paper-checkbox id="allow-incognito" class="checkbox"
- checked="[[data.incognitoAccess.isActive]]"
- on-change="onAllowIncognitoChange_">
- $i18n{itemAllowIncognito}
- </paper-checkbox>
+ <div class="control-line">
+ <span>$i18n{itemAllowIncognito}</span>
+ <paper-toggle-button id="allow-incognito"
+ checked="[[data.incognitoAccess.isActive]]"
+ on-change="onAllowIncognitoChange_"></paper-toggle-button>
+ </div>
</template>
<template is="dom-if" if="[[data.fileAccess.isEnabled]]">
- <paper-checkbox id="allow-on-file-urls" class="checkbox"
- checked="[[data.fileAccess.isActive]]"
- on-change="onAllowOnFileUrlsChange_">
- $i18n{itemAllowOnFileUrls}
- </paper-checkbox>
+ <div class="control-line">
+ <span>$i18n{itemAllowOnFileUrls}</span>
+ <paper-toggle-button id="allow-on-file-urls"
+ checked="[[data.fileAccess.isActive]]"
+ on-change="onAllowOnFileUrlsChange_"></paper-toggle-button>
+ </div>
</template>
<template is="dom-if" if="[[data.runOnAllUrls.isEnabled]]">
- <paper-checkbox id="allow-on-all-sites" class="checkbox"
- checked="[[data.runOnAllUrls.isActive]]"
- on-change="onAllowOnAllSitesChange_">
- $i18n{itemAllowOnAllSites}
- </paper-checkbox>
+ <div class="control-line">
+ <span>$i18n{itemAllowOnAllSites}</span>
+ <paper-toggle-button id="allow-on-all-sites"
+ checked="[[data.runOnAllUrls.isActive]]"
+ on-change="onAllowOnAllSitesChange_"></paper-toggle-button>
+ </div>
</template>
<template is="dom-if" if="[[data.errorCollection.isEnabled]]">
- <paper-checkbox id="collect-errors" class="checkbox"
- checked="[[data.errorCollection.isActive]]"
- on-change="onCollectErrorsChange_">
- $i18n{itemCollectErrors}
- </paper-checkbox>
+ <div class="control-line">
+ <span>$i18n{itemCollectErrors}</span>
+ <paper-toggle-button id="collect-errors"
+ checked="[[data.errorCollection.isActive]]"
+ on-change="onCollectErrorsChange_"></paper-toggle-button>
+ </div>
</template>
</div>
</template>
+ <div class="section"
+ hidden$="[[!shouldShowOptionsLink_(data.*)]]">
+ <div class="control-line actionable" id="extensions-options"
+ on-tap="onOptionsTap_">
+ <span>$i18n{itemOptions}</span>
+ <button class="open-in-new" is="paper-icon-button-light"></button>
+ </div>
+ </div>
+ <div class="section">
+ <div class="control-line actionable" id="remove-extension"
+ on-tap="onRemoveTap_">
+ <span>$i18n{itemRemoveExtension}</span>
+ <button class="action-arrow" is="paper-icon-button-light"></button>
+ </div>
+ </div>
<div class="section">
<div class="section-title">$i18n{itemSource}</div>
<div class="section-content">
diff --git a/chromium/chrome/browser/resources/md_extensions/detail_view.js b/chromium/chrome/browser/resources/md_extensions/detail_view.js
index 5183e2efee2..e8b733e51df 100644
--- a/chromium/chrome/browser/resources/md_extensions/detail_view.js
+++ b/chromium/chrome/browser/resources/md_extensions/detail_view.js
@@ -8,7 +8,7 @@ cr.define('extensions', function() {
var DetailView = Polymer({
is: 'extensions-detail-view',
- behaviors: [Polymer.NeonAnimatableBehavior],
+ behaviors: [I18nBehavior, Polymer.NeonAnimatableBehavior],
properties: {
/**
@@ -19,6 +19,9 @@ cr.define('extensions', function() {
/** @type {!extensions.ItemDelegate} */
delegate: Object,
+
+ /** Whether the user has enabled the UI's developer mode. */
+ inDevMode: Boolean,
},
ready: function() {
@@ -36,6 +39,20 @@ cr.define('extensions', function() {
* @return {boolean}
* @private
*/
+ isEnabled_: function() { return extensions.isEnabled(this.data.state); },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isEnableToggleEnabled_: function() {
+ return extensions.userCanChangeEnablement(this.data);
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
hasDependentExtensions_: function() {
return this.data.dependentExtensions.length > 0;
},
@@ -49,6 +66,24 @@ cr.define('extensions', function() {
},
/**
+ * @return {string}
+ * @private
+ */
+ computeEnabledText_: function() {
+ // TODO(devlin): Get the full spectrum of these strings from bettes.
+ return this.isEnabled_() ? this.i18n('itemOn') : this.i18n('itemOff');
+ },
+
+ /**
+ * @param {!chrome.developerPrivate.ExtensionView} view
+ * @return {string}
+ * @private
+ */
+ computeInspectLabel_: function(view) {
+ return extensions.computeInspectableViewLabel(view);
+ },
+
+ /**
* @return {boolean}
* @private
*/
@@ -64,7 +99,7 @@ cr.define('extensions', function() {
* @return {boolean}
* @private
*/
- shouldShowOptionsButton_: function() {
+ shouldShowOptionsLink_: function() {
return !!this.data.optionsPage;
},
@@ -80,11 +115,30 @@ cr.define('extensions', function() {
},
/** @private */
- onOptionsButtonTap_: function() {
+ onEnableChange_: function() {
+ this.delegate.setItemEnabled(this.data.id,
+ this.$['enable-toggle'].checked);
+ },
+
+ /**
+ * @param {!{model: !{item: !chrome.developerPrivate.ExtensionView}}} e
+ * @private
+ */
+ onInspectTap_: function(e) {
+ this.delegate.inspectItemView(this.data.id, e.model.item);
+ },
+
+ /** @private */
+ onOptionsTap_: function() {
this.delegate.showItemOptionsPage(this.data.id);
},
/** @private */
+ onRemoveTap_: function() {
+ this.delegate.deleteItem(this.data.id);
+ },
+
+ /** @private */
onAllowIncognitoChange_: function() {
this.delegate.setItemAllowedIncognito(
this.data.id, this.$$('#allow-incognito').checked);
diff --git a/chromium/chrome/browser/resources/md_extensions/error_page.html b/chromium/chrome/browser/resources/md_extensions/error_page.html
index 8b1d1973518..10bcd508ee9 100644
--- a/chromium/chrome/browser/resources/md_extensions/error_page.html
+++ b/chromium/chrome/browser/resources/md_extensions/error_page.html
@@ -84,7 +84,7 @@
</iron-list>
<div id="content-view">
<extensions-code-section id="code-section"
- no-code-error="$i18n{noErrorsToShow}">
+ could-not-display-code="$i18n{noErrorsToShow}">
</extensions-code-section>
</div>
<div id="devtools-controls">
diff --git a/chromium/chrome/browser/resources/md_extensions/error_page.js b/chromium/chrome/browser/resources/md_extensions/error_page.js
index 9b812a7744b..da607103b98 100644
--- a/chromium/chrome/browser/resources/md_extensions/error_page.js
+++ b/chromium/chrome/browser/resources/md_extensions/error_page.js
@@ -52,8 +52,8 @@ cr.define('extensions', function() {
ready: function() {
/** @type {!extensions.AnimationHelper} */
this.animationHelper = new extensions.AnimationHelper(this, this.$.main);
- this.animationHelper.setEntryAnimation(extensions.Animation.FADE_IN);
- this.animationHelper.setExitAnimation(extensions.Animation.SCALE_DOWN);
+ this.animationHelper.setEntryAnimations([extensions.Animation.FADE_IN]);
+ this.animationHelper.setExitAnimations([extensions.Animation.SCALE_DOWN]);
this.sharedElements = {hero: this.$.main};
},
diff --git a/chromium/chrome/browser/resources/md_extensions/item.html b/chromium/chrome/browser/resources/md_extensions/item.html
index e4687314713..6709a81e514 100644
--- a/chromium/chrome/browser/resources/md_extensions/item.html
+++ b/chromium/chrome/browser/resources/md_extensions/item.html
@@ -4,11 +4,12 @@
<link rel="import" href="chrome://resources/html/load_time_data.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://extensions/icons.html">
-<link rel="import" href="chrome://extensions/item_source.html">
+<link rel="import" href="chrome://extensions/item_util.html">
<link rel="import" href="chrome://extensions/strings.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/communication-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
@@ -115,11 +116,24 @@
position: absolute;
}
- #source-indicator iron-icon {
+ .source-icon-wrapper {
+ align-items: center;
+ background: rgb(241, 89, 43);
+ border-radius: 50%; /* 50% border radius == a circle */
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.22),
+ 0 2px 2px 0 rgba(0, 0, 0, 0.12);
+ display: flex;
height: 22px;
+ justify-content: center;
width: 22px;
}
+ #source-indicator iron-icon {
+ color: white;
+ height: 16px;
+ width: 16px;
+ }
+
#source-indicator-text {
-webkit-margin-start: 11px; /* To align with the center of the icon. */
background: black;
@@ -156,6 +170,13 @@
color: var(--google-blue-500);
}
+ #dev-reload-button {
+ -webkit-margin-end: 20px;
+ height: 20px;
+ padding: 0;
+ width: 20px;
+ }
+
#warnings {
color: var(--google-red-700);
}
@@ -169,8 +190,10 @@
<template is="dom-if"
if="[[computeSourceIndicatorIcon_(data.*)]]">
<div id="source-indicator">
- <iron-icon icon="[[computeSourceIndicatorIcon_(data.*)]]">
- </iron-icon>
+ <div class="source-icon-wrapper">
+ <iron-icon icon="[[computeSourceIndicatorIcon_(data.*)]]">
+ </iron-icon>
+ </div>
<div id="source-indicator-text">
[[computeSourceIndicatorText_(data.*)]]
</div>
@@ -221,7 +244,7 @@
</template>
</div>
</div>
- <div id="button-strip" class="layout horizontal">
+ <div id="button-strip" class="layout horizontal center">
<div class="layout flex horizontal center">
<paper-button id="details-button" on-tap="onDetailsTap_">
$i18n{itemDetails}
@@ -234,18 +257,24 @@
$i18n{itemErrors}
</paper-button>
</div>
+ <template is="dom-if" if="[[!computeDevReloadButtonHidden_(data.*)]]">
+ <paper-icon-button id="dev-reload-button"
+ on-tap="onReloadTap_" icon="refresh">
+ </paper-icon-button>
+ </template>
<paper-button id="repair-button" class="action-button"
on-tap="onRepairTap_"
hidden$="[[!data.disableReasons.corruptInstall]]">
$i18n{itemRepair}
</paper-button>
- <paper-button id="reload-button" on-tap="onReloadTap_"
+ <paper-button id="terminated-reload-button" on-tap="onReloadTap_"
class="action-button"
hidden$="[[!isTerminated_(data.state)]]">
$i18n{itemReload}
</paper-button>
<paper-toggle-button id="enable-toggle" class="action-button"
checked="[[isEnabled_(data.state)]]" on-change="onEnableChange_"
+ enabled="[[isEnableToggleEnabled_(data)]]"
hidden$="[[!showEnableToggle_(data.*)]]">
</paper-toggle-button>
</div>
diff --git a/chromium/chrome/browser/resources/md_extensions/item.js b/chromium/chrome/browser/resources/md_extensions/item.js
index cd03c28475e..83dd8f557cd 100644
--- a/chromium/chrome/browser/resources/md_extensions/item.js
+++ b/chromium/chrome/browser/resources/md_extensions/item.js
@@ -157,20 +157,17 @@ cr.define('extensions', function() {
},
/**
- * Returns true if the extension is enabled, including terminated
- * extensions.
* @return {boolean}
* @private
*/
- isEnabled_: function() {
- switch (this.data.state) {
- case chrome.developerPrivate.ExtensionState.ENABLED:
- case chrome.developerPrivate.ExtensionState.TERMINATED:
- return true;
- case chrome.developerPrivate.ExtensionState.DISABLED:
- return false;
- }
- assertNotReached(); // FileNotFound.
+ isEnabled_: function() { return extensions.isEnabled(this.data.state); },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isEnableToggleEnabled_: function() {
+ return extensions.userCanChangeEnablement(this.data);
},
/**
@@ -244,22 +241,15 @@ cr.define('extensions', function() {
* @private
*/
computeFirstInspectLabel_: function() {
- var view = this.data.views[0];
- // Trim the "chrome-extension://<id>/".
- var url = new URL(view.url);
- var label = view.url;
- if (url.protocol == 'chrome-extension:')
- label = url.pathname.substring(1);
- if (label == '_generated_background_page.html')
- label = this.i18n('viewBackgroundPage');
- // Add any qualifiers.
- label += (view.incognito ? ' ' + this.i18n('viewIncognito') : '') +
- (view.renderProcessId == -1 ?
- ' ' + this.i18n('viewInactive') : '') +
- (view.isIframe ? ' ' + this.i18n('viewIframe') : '');
- var index = this.data.views.indexOf(view);
- assert(index >= 0);
- if (index < this.data.views.length - 1)
+ // Note: theoretically, this wouldn't be called without any inspectable
+ // views (because it's in a dom-if="!computeInspectViewsHidden_()").
+ // However, due to the recycling behavior of iron list, it seems that
+ // sometimes it can. Even when it is, the UI behaves properly, but we
+ // need to handle the case gracefully.
+ if (this.data.views.length == 0)
+ return '';
+ var label = extensions.computeInspectableViewLabel(this.data.views[0]);
+ if (this.data.views.length > 1)
label += ',';
return label;
},
@@ -273,6 +263,20 @@ cr.define('extensions', function() {
},
/**
+ * @return {boolean}
+ * @private
+ */
+ computeDevReloadButtonHidden_: function() {
+ // Only display the reload spinner if the extension is unpacked and
+ // not terminated (since if it's terminated, we'll show a crashed reload
+ // buton).
+ var showIcon =
+ this.data.location == chrome.developerPrivate.Location.UNPACKED &&
+ this.data.state != chrome.developerPrivate.ExtensionState.TERMINATED;
+ return !showIcon;
+ },
+
+ /**
* @return {string}
* @private
*/
diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.js b/chromium/chrome/browser/resources/md_extensions/item_list.js
index 74d9faa0b79..2da081cdd82 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_list.js
+++ b/chromium/chrome/browser/resources/md_extensions/item_list.js
@@ -33,8 +33,8 @@ cr.define('extensions', function() {
ready: function() {
/** @type {extensions.AnimationHelper} */
this.animationHelper = new extensions.AnimationHelper(this, this.$.list);
- this.animationHelper.setEntryAnimation(extensions.Animation.FADE_IN);
- this.animationHelper.setExitAnimation(extensions.Animation.HERO);
+ this.animationHelper.setEntryAnimations([extensions.Animation.FADE_IN]);
+ this.animationHelper.setExitAnimations([extensions.Animation.HERO]);
},
/**
diff --git a/chromium/chrome/browser/resources/md_extensions/item_source.js b/chromium/chrome/browser/resources/md_extensions/item_source.js
deleted file mode 100644
index 3b16ea9bbd3..00000000000
--- a/chromium/chrome/browser/resources/md_extensions/item_source.js
+++ /dev/null
@@ -1,52 +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.
-
-// Closure compiler won't let this be declared inside cr.define().
-/** @enum {string} */
-var SourceType = {
- WEBSTORE: 'webstore',
- POLICY: 'policy',
- SIDELOADED: 'sideloaded',
- UNPACKED: 'unpacked',
-};
-
-cr.define('extensions', function() {
- /**
- * @param {chrome.developerPrivate.ExtensionInfo} item
- * @return {SourceType}
- */
- function getItemSource(item) {
- if (item.controlledInfo &&
- item.controlledInfo.type ==
- chrome.developerPrivate.ControllerType.POLICY) {
- return SourceType.POLICY;
- }
- if (item.location == chrome.developerPrivate.Location.THIRD_PARTY)
- return SourceType.SIDELOADED;
- if (item.location == chrome.developerPrivate.Location.UNPACKED)
- return SourceType.UNPACKED;
- return SourceType.WEBSTORE;
- }
-
- /**
- * @param {SourceType} source
- * @return {string}
- */
- function getItemSourceString(source) {
- switch (source) {
- case SourceType.POLICY:
- return loadTimeData.getString('itemSourcePolicy');
- case SourceType.SIDELOADED:
- return loadTimeData.getString('itemSourceSideloaded');
- case SourceType.UNPACKED:
- return loadTimeData.getString('itemSourceUnpacked');
- case SourceType.WEBSTORE:
- return loadTimeData.getString('itemSourceWebstore');
- }
- assertNotReached();
- }
-
- return {getItemSource: getItemSource,
- getItemSourceString: getItemSourceString};
-});
diff --git a/chromium/chrome/browser/resources/md_extensions/item_source.html b/chromium/chrome/browser/resources/md_extensions/item_util.html
index 6d2e0dc91b1..6429c3f459a 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_source.html
+++ b/chromium/chrome/browser/resources/md_extensions/item_util.html
@@ -1,4 +1,4 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/load_time_data.html">
-<script src="chrome://extensions/item_source.js"></script>
+<script src="chrome://extensions/item_util.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/item_util.js b/chromium/chrome/browser/resources/md_extensions/item_util.js
new file mode 100644
index 00000000000..46ad2423392
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/item_util.js
@@ -0,0 +1,123 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Closure compiler won't let this be declared inside cr.define().
+/** @enum {string} */
+var SourceType = {
+ WEBSTORE: 'webstore',
+ POLICY: 'policy',
+ SIDELOADED: 'sideloaded',
+ UNPACKED: 'unpacked',
+};
+
+cr.define('extensions', function() {
+ /**
+ * Returns true if the extension is enabled, including terminated
+ * extensions.
+ * @param {!chrome.developerPrivate.ExtensionState} state
+ * @return {boolean}
+ */
+ function isEnabled(state) {
+ switch (state) {
+ case chrome.developerPrivate.ExtensionState.ENABLED:
+ case chrome.developerPrivate.ExtensionState.TERMINATED:
+ return true;
+ case chrome.developerPrivate.ExtensionState.DISABLED:
+ return false;
+ }
+ assertNotReached();
+ }
+
+ /**
+ * Returns true if the user can change whether or not the extension is
+ * enabled.
+ * @param {!chrome.developerPrivate.ExtensionInfo} item
+ * @return {boolean}
+ */
+ function userCanChangeEnablement(item) {
+ // User doesn't have permission.
+ if (!item.userMayModify)
+ return false;
+ // Item is forcefully disabled.
+ if (item.disableReasons.corruptInstall ||
+ item.disableReasons.suspiciousInstall ||
+ item.disableReasons.updateRequired) {
+ return false;
+ }
+ // An item with dependent extensions can't be disabled (it would bork the
+ // dependents).
+ if (item.dependentExtensions.length > 0)
+ return false;
+ // Blacklisted can't be enabled, either.
+ if (item.state == chrome.developerPrivate.ExtensionState.BLACKLISTED)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * @param {!chrome.developerPrivate.ExtensionInfo} item
+ * @return {SourceType}
+ */
+ function getItemSource(item) {
+ if (item.controlledInfo &&
+ item.controlledInfo.type ==
+ chrome.developerPrivate.ControllerType.POLICY) {
+ return SourceType.POLICY;
+ }
+ if (item.location == chrome.developerPrivate.Location.THIRD_PARTY)
+ return SourceType.SIDELOADED;
+ if (item.location == chrome.developerPrivate.Location.UNPACKED)
+ return SourceType.UNPACKED;
+ return SourceType.WEBSTORE;
+ }
+
+ /**
+ * @param {SourceType} source
+ * @return {string}
+ */
+ function getItemSourceString(source) {
+ switch (source) {
+ case SourceType.POLICY:
+ return loadTimeData.getString('itemSourcePolicy');
+ case SourceType.SIDELOADED:
+ return loadTimeData.getString('itemSourceSideloaded');
+ case SourceType.UNPACKED:
+ return loadTimeData.getString('itemSourceUnpacked');
+ case SourceType.WEBSTORE:
+ return loadTimeData.getString('itemSourceWebstore');
+ }
+ assertNotReached();
+ }
+
+ /**
+ * Computes the human-facing label for the given inspectable view.
+ * @param {!chrome.developerPrivate.ExtensionView} view
+ * @return {string}
+ */
+ function computeInspectableViewLabel(view) {
+ // Trim the "chrome-extension://<id>/".
+ var url = new URL(view.url);
+ var label = view.url;
+ if (url.protocol == 'chrome-extension:')
+ label = url.pathname.substring(1);
+ if (label == '_generated_background_page.html')
+ label = loadTimeData.getString('viewBackgroundPage');
+ // Add any qualifiers.
+ if (view.incognito)
+ label += ' ' + loadTimeData.getString('viewIncognito');
+ if (view.renderProcessId == -1)
+ label += ' ' + loadTimeData.getString('viewInactive');
+ if (view.isIframe)
+ label += ' ' + loadTimeData.getString('viewIframe');
+
+ return label;
+ }
+
+ return {isEnabled: isEnabled,
+ userCanChangeEnablement: userCanChangeEnablement,
+ getItemSource: getItemSource,
+ getItemSourceString: getItemSourceString,
+ computeInspectableViewLabel: computeInspectableViewLabel};
+});
diff --git a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
index 45ae9d37ee1..a0fe904b459 100644
--- a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
+++ b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
@@ -19,8 +19,8 @@ cr.define('extensions', function() {
ready: function() {
/** @type {!extensions.AnimationHelper} */
this.animationHelper = new extensions.AnimationHelper(this, this.$.main);
- this.animationHelper.setEntryAnimation(extensions.Animation.FADE_IN);
- this.animationHelper.setExitAnimation(extensions.Animation.SCALE_DOWN);
+ this.animationHelper.setEntryAnimations([extensions.Animation.FADE_IN]);
+ this.animationHelper.setExitAnimations([extensions.Animation.SCALE_DOWN]);
this.sharedElements = {hero: this.$.main};
},
diff --git a/chromium/chrome/browser/resources/md_extensions/load_error.html b/chromium/chrome/browser/resources/md_extensions/load_error.html
new file mode 100644
index 00000000000..c2fd7d17cb3
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/load_error.html
@@ -0,0 +1,119 @@
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
+<link rel="import" href="chrome://extensions/code_section.html">
+
+<dom-module id="extensions-load-error">
+ <template>
+ <style>
+ dialog {
+ @apply(--shadow-elevation-2dp);
+ border: none;
+ border-radius: 2px;
+ padding: 0;
+ width: 512px;
+ }
+
+ header {
+ -webkit-padding-end: 20px;
+ -webkit-padding-start: 24px;
+ align-items: center;
+ border-bottom: 1px solid var(--paper-grey-200);
+ color: #333;
+ display: flex;
+ font-size: 16px;
+ justify-content: space-between;
+ padding-bottom: 16px;
+ padding-top: 16px;
+ }
+
+ #close-button {
+ height: 20px;
+ padding: 0;
+ width: 20px;
+ }
+
+ #main {
+ -webkit-margin-end: 16px;
+ -webkit-margin-start: 24px;
+ font-size: 13px;
+ line-height: 20px;
+ max-width: 800px;
+ padding-bottom: 16px;
+ padding-top: 20px;
+ }
+
+ .description-row {
+ color: #333;
+ display: flex;
+ }
+
+ .row-label {
+ display: block;
+ width: 104px; /* Magic number from the specs. */
+ }
+
+ paper-button {
+ align-items: center;
+ border-radius: 2px;
+ cursor: pointer;
+ display: flex;
+ font-size: 13px;
+ justify-content: center;
+ padding: 8px 12px;
+ text-transform: uppercase;
+ }
+
+ #buttons-container {
+ display: flex;
+ justify-content: flex-end;
+ padding: 20px;
+ }
+
+ #dismiss {
+ color: #5a5a5a;
+ }
+
+ #retry {
+ -webkit-margin-start: 12px;
+ background-color: var(--google-blue-500);
+ color: white;
+ }
+ </style>
+ <dialog>
+ <header>
+ <span>$i18n{loadErrorHeading}</span>
+ <paper-icon-button id="close-button" icon="close" on-tap="close">
+ </paper-icon-button>
+ </header>
+ <div id="main">
+ <div id="info">
+ <div id="file" class="description-row">
+ <span class="row-label">$i18n{loadErrorFileLabel}</span>
+ <span class="row-value">[[loadError.path]]</span>
+ </div>
+ <div id="error" class="description-row">
+ <span class="row-label">$i18n{loadErrorErrorLabel}</span>
+ <span class="row-value">[[loadError.error]]</span>
+ </div>
+ </div>
+ <extensions-code-section id="code"
+ could-not-display-code="$i18n{loadErrorCouldNotLoadManifest}">
+ </extensions-code-section>
+ </div>
+ <div id="buttons-container">
+ <paper-button id="dismiss" on-tap="close">
+ $i18n{loadErrorCancel}
+ </paper-button>
+ <paper-button id="retry" on-tap="onRetryTap_">
+ $i18n{loadErrorRetry}
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="chrome://extensions/load_error.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/load_error.js b/chromium/chrome/browser/resources/md_extensions/load_error.js
new file mode 100644
index 00000000000..eaba34c8b60
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/load_error.js
@@ -0,0 +1,69 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('extensions', function() {
+ 'use strict';
+
+ /** @interface */
+ function LoadErrorDelegate() {}
+
+ LoadErrorDelegate.prototype = {
+ /**
+ * Attempts to load the previously-attempted unpacked extension.
+ * @param {string} retryId
+ */
+ retryLoadUnpacked: assertNotReached,
+ };
+
+ var LoadError = Polymer({
+ is: 'extensions-load-error',
+ properties: {
+ /** @type {extensions.LoadErrorDelegate} */
+ delegate: Object,
+
+ /** @type {chrome.developerPrivate.LoadError} */
+ loadError: Object,
+ },
+
+ observers: [
+ 'observeLoadErrorChanges_(loadError)',
+ ],
+
+ show: function() {
+ this.$$('dialog').showModal();
+ },
+
+ close: function() {
+ this.$$('dialog').close();
+ },
+
+ /** @private */
+ onRetryTap_: function() {
+ this.delegate.retryLoadUnpacked(this.loadError.retryGuid);
+ this.close();
+ },
+
+ /** @private */
+ observeLoadErrorChanges_: function() {
+ assert(this.loadError);
+ var source = this.loadError.source;
+ // CodeSection expects a RequestFileSourceResponse, rather than an
+ // ErrorFileSource. Massage into place.
+ // TODO(devlin): Make RequestFileSourceResponse use ErrorFileSource.
+ /** @type {!chrome.developerPrivate.RequestFileSourceResponse} */
+ var codeSectionProperties = {
+ beforeHighlight: source ? source.beforeHighlight : '',
+ highlight: source ? source.highlight : '',
+ afterHighlight: source ? source.afterHighlight : '',
+ title: '',
+ message: this.loadError.error,
+ };
+
+ this.$.code.code = codeSectionProperties;
+ },
+ });
+
+ return {LoadError: LoadError,
+ LoadErrorDelegate: LoadErrorDelegate};
+});
diff --git a/chromium/chrome/browser/resources/md_extensions/manager.html b/chromium/chrome/browser/resources/md_extensions/manager.html
index df941edb8f8..e5dab6604f5 100644
--- a/chromium/chrome/browser/resources/md_extensions/manager.html
+++ b/chromium/chrome/browser/resources/md_extensions/manager.html
@@ -1,9 +1,11 @@
+<link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/promise_resolver.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animated-pages.html">
<link rel="import" href="chrome://extensions/detail_view.html">
@@ -11,10 +13,12 @@
<link rel="import" href="chrome://extensions/error_page.html">
<link rel="import" href="chrome://extensions/item_list.html">
<link rel="import" href="chrome://extensions/keyboard_shortcuts.html">
+<link rel="import" href="chrome://extensions/load_error.html">
<link rel="import" href="chrome://extensions/options_dialog.html">
<link rel="import" href="chrome://extensions/pack_dialog.html">
<link rel="import" href="chrome://extensions/service.html">
<link rel="import" href="chrome://extensions/sidebar.html">
+<link rel="import" href="chrome://extensions/toolbar.html">
<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
<dom-module id="extensions-manager">
@@ -39,34 +43,32 @@
}
#pages {
- -webkit-margin-start: 30px;
flex-grow: 1;
overflow-y: auto;
- padding-bottom: 30px;
}
extensions-item {
display: inline-block;
}
- cr-toolbar {
- /* TODO(tsergeant): Remove the extra 30px margin from #pages so the
- search field aligns with History. */
- --cr-toolbar-field-margin: 286px;
+ extensions-toolbar {
background: var(--md-toolbar-color);
font-size: 13px;
}
</style>
<extensions-drop-overlay></extensions-drop-overlay>
<paper-header-panel id="panel">
- <cr-toolbar class="paper-header"
- page-name="$i18n{toolbarTitle}"
- search-prompt="$i18n{search}"
- clear-label="$i18n{clearSearch}"
+ <extensions-toolbar class="paper-header" in-dev-mode="[[inDevMode]]"
+ on-pack-tap="onPackTap_"
+ on-cr-toolbar-menu-tap="onMenuButtonTap_"
on-search-changed="onFilterChanged_">
- </cr-toolbar>
- <extensions-sidebar in-dev-mode="[[inDevMode]]">
- </extensions-sidebar>
+ </extensions-toolbar>
+ <dialog id="drawer" is="cr-drawer">
+ <div class="drawer-header">$i18n{toolbarTitle}</div>
+ <div class="drawer-content">
+ <extensions-sidebar></extensions-sidebar>
+ </div>
+ </dialog>
<neon-animated-pages id="pages" selected="0">
<extensions-item-list id="items-list" items="[[extensions]]"
delegate="[[itemDelegate]]" in-dev-mode="[[inDevMode]]"
@@ -74,7 +76,8 @@
hidden$="[[computeListHidden_(extensions, extensions.splices, apps, apps.splices)]]">
</extensions-item-list>
<extensions-detail-view id="details-view" delegate="[[itemDelegate]]"
- data="[[detailViewItem_]]" on-close="onDetailsViewClose_">
+ in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]"
+ on-close="onDetailsViewClose_">
</extensions-detail-view>
<extensions-keyboard-shortcuts id="keyboard-shortcuts"
items="[[extensions]]">
@@ -86,6 +89,7 @@
<extensions-options-dialog id="options-dialog">
</extensions-options-dialog>
<extensions-pack-dialog id="pack-dialog"></extensions-pack-dialog>
+ <extensions-load-error id="load-error"></extensions-load-error>
</paper-header-panel>
</template>
<script src="chrome://extensions/manager.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/manager.js b/chromium/chrome/browser/resources/md_extensions/manager.js
index 5bd91bb27e3..390944de0a7 100644
--- a/chromium/chrome/browser/resources/md_extensions/manager.js
+++ b/chromium/chrome/browser/resources/md_extensions/manager.js
@@ -50,6 +50,9 @@ cr.define('extensions', function() {
/** @type {extensions.Sidebar} */
sidebar: Object,
+ /** @type {extensions.Toolbar} */
+ toolbar: Object,
+
/** @type {extensions.ItemDelegate} */
itemDelegate: Object,
@@ -106,6 +109,8 @@ cr.define('extensions', function() {
/** @type {extensions.Sidebar} */
this.sidebar =
/** @type {extensions.Sidebar} */(this.$$('extensions-sidebar'));
+ this.toolbar =
+ /** @type {extensions.Toolbar} */(this.$$('extensions-toolbar'));
this.listHelper_ = new ListHelper(this);
this.sidebar.setListDelegate(this.listHelper_);
this.readyPromiseResolver.resolve();
@@ -119,6 +124,10 @@ cr.define('extensions', function() {
return this.$['pack-dialog'];
},
+ get loadError() {
+ return this.$['load-error'];
+ },
+
get optionsDialog() {
return this.$['options-dialog'];
},
@@ -145,6 +154,10 @@ cr.define('extensions', function() {
this.filter = /** @type {string} */ (event.detail);
},
+ onMenuButtonTap_: function() {
+ this.$.drawer.toggle();
+ },
+
/**
* @param {chrome.developerPrivate.ExtensionType} type The type of item.
* @return {string} The ID of the list that the item belongs in.
@@ -273,6 +286,7 @@ cr.define('extensions', function() {
* @param {Page} toPage
*/
changePage: function(toPage) {
+ this.$.drawer.closeDrawer();
var fromPage = this.$.pages.selected;
if (fromPage == toPage)
return;
@@ -280,19 +294,21 @@ cr.define('extensions', function() {
var exit;
if (fromPage == Page.ITEM_LIST && (toPage == Page.DETAIL_VIEW ||
toPage == Page.ERROR_PAGE)) {
- entry = extensions.Animation.HERO;
- exit = extensions.Animation.HERO;
+ entry = [extensions.Animation.HERO];
+ // The item grid can be larger than the detail view that we're
+ // hero'ing into, so we want to also fade out to avoid any jarring.
+ exit = [extensions.Animation.HERO, extensions.Animation.FADE_OUT];
} else if (toPage == Page.ITEM_LIST) {
- entry = extensions.Animation.FADE_IN;
- exit = extensions.Animation.SCALE_DOWN;
+ entry = [extensions.Animation.FADE_IN];
+ exit = [extensions.Animation.SCALE_DOWN];
} else {
assert(toPage == Page.DETAIL_VIEW ||
toPage == Page.KEYBOARD_SHORTCUTS);
- entry = extensions.Animation.FADE_IN;
- exit = extensions.Animation.FADE_OUT;
+ entry = [extensions.Animation.FADE_IN];
+ exit = [extensions.Animation.FADE_OUT];
}
- this.getPage_(fromPage).animationHelper.setExitAnimation(exit);
- this.getPage_(toPage).animationHelper.setEntryAnimation(entry);
+ this.getPage_(fromPage).animationHelper.setExitAnimations(exit);
+ this.getPage_(toPage).animationHelper.setEntryAnimations(entry);
this.$.pages.selected = toPage;
},
@@ -329,6 +345,11 @@ cr.define('extensions', function() {
// Note: we don't reset errorPageItem_ here because doing so just causes
// extra work for the data-bound error page.
this.changePage(Page.ITEM_LIST);
+ },
+
+ /** @private */
+ onPackTap_: function() {
+ this.$['pack-dialog'].show();
}
});
@@ -362,11 +383,6 @@ cr.define('extensions', function() {
showKeyboardShortcuts: function() {
this.manager_.changePage(Page.KEYBOARD_SHORTCUTS);
},
-
- /** @override */
- showPackDialog: function() {
- this.manager_.packDialog.show();
- }
};
return {Manager: Manager};
diff --git a/chromium/chrome/browser/resources/md_extensions/pack_dialog.html b/chromium/chrome/browser/resources/md_extensions/pack_dialog.html
index e21e5f64360..218057e7a54 100644
--- a/chromium/chrome/browser/resources/md_extensions/pack_dialog.html
+++ b/chromium/chrome/browser/resources/md_extensions/pack_dialog.html
@@ -15,22 +15,39 @@
border: none;
border-radius: 2px;
padding: 0;
+ width: 512px;
}
header {
+ -webkit-padding-end: 20px;
+ -webkit-padding-start: 24px;
align-items: center;
border-bottom: 1px solid var(--paper-grey-200);
- color: var(--paper-grey-800);
+ color: #333;
display: flex;
+ font-size: 16px;
justify-content: space-between;
- padding: 12px 20px;
+ padding-bottom: 16px;
+ padding-top: 16px;
+ }
+
+ #close-button {
+ height: 20px;
+ padding: 0;
+ width: 20px;
}
#main {
- color: var(--paper-grey-800);
+ -webkit-margin-end: 16px;
+ -webkit-margin-start: 24px;
+ font-size: 13px;
max-width: 800px;
- padding: 20px;
- width: 512px;
+ padding-bottom: 16px;
+ padding-top: 20px;
+ }
+
+ #description {
+ color: #333;
}
paper-button {
@@ -38,6 +55,7 @@
border-radius: 2px;
cursor: pointer;
display: flex;
+ font-size: 13px;
justify-content: center;
padding: 8px 12px;
text-transform: uppercase;
@@ -45,6 +63,9 @@
.file-input {
display: flex;
+ --paper-input-container-input: {
+ font-size: inherit;
+ };
}
.file-input paper-input {
@@ -62,6 +83,10 @@
padding: 20px;
}
+ #dismiss {
+ color: #5a5a5a;
+ }
+
#confirm {
-webkit-margin-start: 12px;
background-color: var(--google-blue-500);
@@ -78,7 +103,7 @@
<div id="description">$i18n{packDialogContent}</div>
<div class="file-input">
<paper-input id="root-dir" label="$i18n{packDialogExtensionRoot}"
- value="[[packDirectory_]]">
+ always-float-label value="[[packDirectory_]]">
</paper-input>
<paper-button id="root-dir-browse" on-tap="onRootBrowse_">
$i18n{packDialogBrowse}
@@ -86,7 +111,7 @@
</div>
<div class="file-input">
<paper-input id="key-file" label="$i18n{packDialogKeyFile}"
- value="[[keyFile_]]">
+ always-float-label value="[[keyFile_]]">
</paper-input>
<paper-button id="key-file-browse" on-tap="onKeyBrowse_">
$i18n{packDialogBrowse}
diff --git a/chromium/chrome/browser/resources/md_extensions/service.js b/chromium/chrome/browser/resources/md_extensions/service.js
index 147e09d468a..3855db8ceaf 100644
--- a/chromium/chrome/browser/resources/md_extensions/service.js
+++ b/chromium/chrome/browser/resources/md_extensions/service.js
@@ -7,10 +7,11 @@ cr.define('extensions', function() {
/**
* @constructor
+ * @implements {extensions.ErrorPageDelegate}
* @implements {extensions.ItemDelegate}
- * @implements {extensions.SidebarDelegate}
+ * @implements {extensions.LoadErrorDelegate}
* @implements {extensions.PackDialogDelegate}
- * @implements {extensions.ErrorPageDelegate}
+ * @implements {extensions.ToolbarDelegate}
*/
function Service() {}
@@ -22,9 +23,10 @@ cr.define('extensions', function() {
managerReady: function(manager) {
/** @private {extensions.Manager} */
this.manager_ = manager;
- this.manager_.sidebar.setDelegate(this);
+ this.manager_.toolbar.setDelegate(this);
this.manager_.set('itemDelegate', this);
this.manager_.packDialog.set('delegate', this);
+ this.manager_.loadError.set('delegate', this);
this.manager_.errorPage.delegate = this;
var keyboardShortcuts = this.manager_.keyboardShortcuts;
keyboardShortcuts.addEventListener(
@@ -160,6 +162,28 @@ cr.define('extensions', function() {
chrome.developerPrivate.setShortcutHandlingSuspended(isCapturing);
},
+ /**
+ * Attempts to load an unpacked extension, optionally as another attempt at
+ * a previously-specified load.
+ * @param {string=} opt_retryGuid
+ * @private
+ */
+ loadUnpackedHelper_: function(opt_retryGuid) {
+ chrome.developerPrivate.loadUnpacked(
+ {failQuietly: true, populateError: true, retryGuid: opt_retryGuid},
+ (loadError) => {
+ if (chrome.runtime.lastError &&
+ chrome.runtime.lastError.message !=
+ 'File selection was canceled.') {
+ throw new Error(chrome.runtime.lastError.message);
+ }
+ if (loadError) {
+ this.manager_.loadError.loadError = loadError;
+ this.manager_.loadError.show();
+ }
+ });
+ },
+
/** @override */
deleteItem: function(id) {
if (this.isDeleting_)
@@ -251,7 +275,12 @@ cr.define('extensions', function() {
/** @override */
loadUnpacked: function() {
- chrome.developerPrivate.loadUnpacked({failQuietly: true});
+ this.loadUnpackedHelper_();
+ },
+
+ /** @override */
+ retryLoadUnpacked: function(retryGuid) {
+ this.loadUnpackedHelper_(retryGuid);
},
/** @override */
diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.html b/chromium/chrome/browser/resources/md_extensions/sidebar.html
index 2bf0f8e2012..925f4c9ac56 100644
--- a/chromium/chrome/browser/resources/md_extensions/sidebar.html
+++ b/chromium/chrome/browser/resources/md_extensions/sidebar.html
@@ -1,26 +1,20 @@
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/hardware-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://extensions/icons.html">
<dom-module id="extensions-sidebar">
<template>
<style>
:host {
- margin-top: 30px;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
white-space: nowrap;
}
- #section-menu,
- .section-item {
- -webkit-margin-start: 20px;
- }
-
#section-menu {
--paper-menu-background-color: transparent;
--paper-menu-selected-item: {
@@ -33,85 +27,47 @@
}
#more-extensions {
+ -webkit-padding-end: 16px;
+ align-items: center;
display: flex;
+ justify-content: space-between;
text-decoration: none;
}
- paper-item {
+ .section-item {
+ -webkit-padding-start: 24px;
color: #5A5A5A;
cursor: pointer;
- font-size: 88%;
- padding: 0;
- }
-
- .section-menu-item iron-icon,
- .section-item iron-icon {
- -webkit-margin-end: 15px;
+ font-size: 13px;
+ height: 48px;
}
- #developer-mode-checkbox {
- --paper-checkbox-checked-color: var(--google-blue-700);
- --primary-text-color: #5a5a5a;
- }
-
- #developer-mode {
- display: flex;
- }
-
- #developer-mode span {
- flex-grow: 1;
- }
-
- #devtools-controls {
- border-top: 1px solid grey;
+ button[is='paper-icon-button-light'].open-in-new {
+ background-image: url(chrome://resources/images/open_in_new.svg);
+ background-size: contain;
+ height: 15px;
+ width: 15px;
}
</style>
<paper-menu id="section-menu" selected="0">
- <paper-item class="section-menu-item" id="sections-extensions"
+ <paper-item class="section-item" id="sections-extensions"
on-tap="onExtensionsTap_">
- <iron-icon icon="extension"></iron-icon>
<span>$i18n{sidebarExtensions}</span>
</paper-item>
- <paper-item class="section-menu-item" id="sections-apps"
+ <paper-item class="section-item" id="sections-apps"
on-tap="onAppsTap_">
- <iron-icon icon="apps"></iron-icon>
<span>$i18n{sidebarApps}</span>
</paper-item>
- <paper-item class="section-menu-item" id="sections-shortcuts"
+ <paper-item class="section-item" id="sections-shortcuts"
on-tap="onKeyboardShortcutsTap_">
- <iron-icon icon="hardware:keyboard"></iron-icon>
<span>$i18n{keyboardShortcuts}</span>
</paper-item>
</paper-menu>
<a class="section-item" id="more-extensions" target="_blank"
href="$i18n{getMoreExtensionsUrl}">
- <paper-item>
- <iron-icon icon="extensions-icons:store"></iron-icon>
- <span>$i18n{getMoreExtensions}</span>
- </paper-item>
+ <span>$i18n{getMoreExtensions}</span>
+ <button class="open-in-new" is="paper-icon-button-light"></button>
</a>
- <div id="devtools-controls">
- <paper-item class="section-item" id="developer-mode">
- <span>$i18n{developerMode}</span>
- <paper-checkbox id="developer-mode-checkbox"
- checked="[[inDevMode]]"
- on-change="onDevModeChange_"></paper-checkbox>
- </paper-item>
- <template is="dom-if" if="[[inDevMode]]">
- <paper-item class="section-item" id="load-unpacked"
- on-tap="onLoadUnpackedTap_">
- <span>$i18n{sidebarLoadUnpacked}</span>
- </paper-item>
- <paper-item class="section-item" id="pack-extensions"
- on-tap="onPackTap_">
- <span>$i18n{sidebarPack}</span>
- </paper-item>
- <paper-item class="section-item" id="update-now"
- on-tap="onUpdateNowTap_">
- <span>$i18n{sidebarUpdateNow}</span>
- </paper-item>
- </template>
- </div>
</template>
<script src="chrome://extensions/sidebar.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.js b/chromium/chrome/browser/resources/md_extensions/sidebar.js
index 55e62fac45d..76244d45907 100644
--- a/chromium/chrome/browser/resources/md_extensions/sidebar.js
+++ b/chromium/chrome/browser/resources/md_extensions/sidebar.js
@@ -13,23 +13,6 @@ extensions.ShowingType = {
cr.define('extensions', function() {
/** @interface */
- var SidebarDelegate = function() {};
-
- SidebarDelegate.prototype = {
- /**
- * Toggles whether or not the profile is in developer mode.
- * @param {boolean} inDevMode
- */
- setProfileInDevMode: assertNotReached,
-
- /** Opens the dialog to load unpacked extensions. */
- loadUnpacked: assertNotReached,
-
- /** Updates all extensions. */
- updateAllExtensions: assertNotReached,
- };
-
- /** @interface */
var SidebarListDelegate = function() {};
SidebarListDelegate.prototype = {
@@ -41,9 +24,6 @@ cr.define('extensions', function() {
/** Shows the keyboard shortcuts page. */
showKeyboardShortcuts: assertNotReached,
-
- /** Shows the pack extension dialog. */
- showPackDialog: assertNotReached,
};
var Sidebar = Polymer({
@@ -51,19 +31,6 @@ cr.define('extensions', function() {
behaviors: [I18nBehavior],
- properties: {
- inDevMode: {
- type: Boolean,
- value: false,
- },
- },
-
- /** @param {extensions.SidebarDelegate} delegate */
- setDelegate: function(delegate) {
- /** @private {extensions.SidebarDelegate} */
- this.delegate_ = delegate;
- },
-
/** @param {extensions.SidebarListDelegate} listDelegate */
setListDelegate: function(listDelegate) {
/** @private {extensions.SidebarListDelegate} */
@@ -81,27 +48,6 @@ cr.define('extensions', function() {
},
/** @private */
- onDevModeChange_: function() {
- this.delegate_.setProfileInDevMode(
- this.$['developer-mode-checkbox'].checked);
- },
-
- /** @private */
- onLoadUnpackedTap_: function() {
- this.delegate_.loadUnpacked();
- },
-
- /** @private */
- onPackTap_: function() {
- this.listDelegate_.showPackDialog();
- },
-
- /** @private */
- onUpdateNowTap_: function() {
- this.delegate_.updateAllExtensions();
- },
-
- /** @private */
onKeyboardShortcutsTap_: function() {
this.listDelegate_.showKeyboardShortcuts();
},
@@ -109,7 +55,6 @@ cr.define('extensions', function() {
return {
Sidebar: Sidebar,
- SidebarDelegate: SidebarDelegate,
SidebarListDelegate: SidebarListDelegate,
};
});
diff --git a/chromium/chrome/browser/resources/md_extensions/toolbar.html b/chromium/chrome/browser/resources/md_extensions/toolbar.html
new file mode 100644
index 00000000000..d496c9b1fb8
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/toolbar.html
@@ -0,0 +1,86 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="chrome://extensions/icons.html">
+<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
+
+<dom-module id="extensions-toolbar">
+ <template>
+ <style>
+ :host {
+ --toolbar-width: 580px;
+ --toolbar-color: var(--md-toolbar-color);
+ }
+
+ [hidden] {
+ display: none !important;
+ }
+
+ cr-toolbar {
+ --cr-toolbar-field-width: var(--toolbar-width);
+ background: var(--toolbar-color);
+ font-size: 13px;
+ }
+
+ .dev-controls {
+ background: var(--toolbar-color);
+ display: flex;
+ justify-content: center;
+ width: 100%;
+ }
+
+ #button-strip {
+ /* We left-align the text of the left button with the left edge of the
+ search field. Since the buttons have 12px padding, add 24px to the
+ width of the button strip (12px each side) to make centering easy. */
+ width: calc(var(--toolbar-width) + 2 * 12px);
+ }
+
+ #button-strip paper-button {
+ -webkit-margin-end: 16px;
+ -webkit-margin-start: 0;
+ color: white;
+ font-size: 13px;
+ padding: 12px 9px;
+ }
+
+ .more-actions {
+ align-items: center;
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ .more-actions span {
+ -webkit-margin-end: 16px;
+ }
+ </style>
+ <cr-toolbar class="paper-header"
+ page-name="$i18n{toolbarTitle}"
+ search-prompt="$i18n{search}"
+ clear-label="$i18n{clearSearch}"
+ show-menu>
+ <div class="more-actions">
+ <span>$i18n{toolbarDevMode}</span>
+ <paper-toggle-button id="dev-mode" on-change="onDevModeChange_"
+ checked="[[inDevMode]]">
+ </paper-toggle-button>
+ </div>
+ </cr-toolbar>
+ <div class="dev-controls" hidden$="[[!inDevMode]]">
+ <div id="button-strip">
+ <paper-button id="load-unpacked" on-tap="onLoadUnpackedTap_">
+ $i18n{toolbarLoadUnpacked}
+ </paper-button>
+ <paper-button id="pack-extensions" on-tap="onPackTap_">
+ $i18n{toolbarPack}
+ </paper-button>
+ <paper-button id="update-now" on-tap="onUpdateNowTap_">
+ $i18n{toolbarUpdateNow}
+ </paper-button>
+ </div>
+ </div>
+ </template>
+ <script src="chrome://extensions/toolbar.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/toolbar.js b/chromium/chrome/browser/resources/md_extensions/toolbar.js
new file mode 100644
index 00000000000..be11f251882
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/toolbar.js
@@ -0,0 +1,68 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.exportPath('extensions');
+
+cr.define('extensions', function() {
+ /** @interface */
+ var ToolbarDelegate = function() {};
+
+ ToolbarDelegate.prototype = {
+ /**
+ * Toggles whether or not the profile is in developer mode.
+ * @param {boolean} inDevMode
+ */
+ setProfileInDevMode: assertNotReached,
+
+ /** Opens the dialog to load unpacked extensions. */
+ loadUnpacked: assertNotReached,
+
+ /** Updates all extensions. */
+ updateAllExtensions: assertNotReached,
+ };
+
+ var Toolbar = Polymer({
+ is: 'extensions-toolbar',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ inDevMode: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
+ /** @param {extensions.ToolbarDelegate} delegate */
+ setDelegate: function(delegate) {
+ /** @private {extensions.ToolbarDelegate} */
+ this.delegate_ = delegate;
+ },
+
+ /** @private */
+ onDevModeChange_: function() {
+ this.delegate_.setProfileInDevMode(this.$['dev-mode'].checked);
+ },
+
+ /** @private */
+ onLoadUnpackedTap_: function() {
+ this.delegate_.loadUnpacked();
+ },
+
+ /** @private */
+ onPackTap_: function() {
+ this.fire('pack-tap');
+ },
+
+ /** @private */
+ onUpdateNowTap_: function() {
+ this.delegate_.updateAllExtensions();
+ },
+ });
+
+ return {
+ Toolbar: Toolbar,
+ ToolbarDelegate: ToolbarDelegate,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_history/OWNERS b/chromium/chrome/browser/resources/md_history/OWNERS
index 793f7b9dc7a..68e023a6b9b 100644
--- a/chromium/chrome/browser/resources/md_history/OWNERS
+++ b/chromium/chrome/browser/resources/md_history/OWNERS
@@ -1,3 +1,5 @@
calamity@chromium.org
dbeam@chromium.org
tsergeant@chromium.org
+
+# COMPONENT: UI>Browser>History
diff --git a/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp
index daf2ec50beb..e372e5a8c4c 100644
--- a/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp
@@ -58,6 +58,7 @@
'target_name': 'history_toolbar',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar',
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar_selection_overlay',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
'constants',
diff --git a/chromium/chrome/browser/resources/md_history/history.html b/chromium/chrome/browser/resources/md_history/history.html
index e9e4b1c06ea..cc221baf1bd 100644
--- a/chromium/chrome/browser/resources/md_history/history.html
+++ b/chromium/chrome/browser/resources/md_history/history.html
@@ -12,6 +12,7 @@
body {
height: 100%;
margin: 0;
+ overflow: hidden;
}
body {
diff --git a/chromium/chrome/browser/resources/md_history/history_item.html b/chromium/chrome/browser/resources/md_history/history_item.html
index 30f91fcc6b3..8bbdbdae64c 100644
--- a/chromium/chrome/browser/resources/md_history/history_item.html
+++ b/chromium/chrome/browser/resources/md_history/history_item.html
@@ -231,7 +231,7 @@
<span id="domain">[[item.domain]]</span>
</div>
<div id="star-container">
- <template is="dom-if" if="[[item.starred]]">
+ <template is="dom-if" if="[[item.starred]]" notify-dom-change>
<button is="paper-icon-button-light" id="bookmark-star"
title="$i18n{removeBookmark}" on-click="onRemoveBookmarkTap_">
<iron-icon icon="cr:star"></iron-icon>
diff --git a/chromium/chrome/browser/resources/md_history/history_list.html b/chromium/chrome/browser/resources/md_history/history_list.html
index 4c0d96c0cec..b8bad9a63c6 100644
--- a/chromium/chrome/browser/resources/md_history/history_list.html
+++ b/chromium/chrome/browser/resources/md_history/history_list.html
@@ -32,7 +32,7 @@
</style>
<div id="no-results" class="centered-message"
hidden$="[[hasResults_(historyData_.length)]]">
- [[noResultsMessage_(searchedTerm, queryState.querying)]]
+ [[noResultsMessage_(searchedTerm)]]
</div>
<iron-list items="{{historyData_}}" as="item" id="infinite-list"
diff --git a/chromium/chrome/browser/resources/md_history/history_list.js b/chromium/chrome/browser/resources/md_history/history_list.js
index 85dafe0e0be..d850ad634a2 100644
--- a/chromium/chrome/browser/resources/md_history/history_list.js
+++ b/chromium/chrome/browser/resources/md_history/history_list.js
@@ -460,14 +460,10 @@ Polymer({
/**
* @param {string} searchedTerm
- * @param {boolean} isLoading
* @return {string}
* @private
*/
- noResultsMessage_: function(searchedTerm, isLoading) {
- if (isLoading)
- return '';
-
+ noResultsMessage_: function(searchedTerm) {
var messageId = searchedTerm !== '' ? 'noSearchResults' : 'noResults';
return loadTimeData.getString(messageId);
},
diff --git a/chromium/chrome/browser/resources/md_history/history_toolbar.html b/chromium/chrome/browser/resources/md_history/history_toolbar.html
index 8cebe69e6e2..2a69ab5a559 100644
--- a/chromium/chrome/browser/resources/md_history/history_toolbar.html
+++ b/chromium/chrome/browser/resources/md_history/history_toolbar.html
@@ -1,51 +1,43 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
<link rel="import" href="chrome://history/browser_service.html">
<link rel="import" href="chrome://history/icons.html">
<link rel="import" href="chrome://history/shared_style.html">
-<!-- Lazy loaded: iron-dropdown, paper-button, paper-icon-button-light. -->
+<!-- Lazy loaded: cr-toolbar-selection-overlay. -->
<dom-module id="history-toolbar">
<template>
<style include="shared-style">
:host {
color: #fff;
- display: block;
+ display: flex;
transition: background-color 150ms;
- width: 100%;
}
/* General toolbar layout. */
- cr-toolbar,
- #overlay-buttons,
- #overlay-wrapper,
- #toolbar-container {
- align-items: center;
- display: flex;
- width: 100%;
- }
-
:host([items-selected_]) {
background: var(--interactive-color);
}
- #toolbar-container {
- height: var(--toolbar-height);
- }
-
- cr-toolbar {
+ cr-toolbar,
+ cr-toolbar-selection-overlay {
--cr-toolbar-field-margin: var(--side-bar-width);
+ flex: 1;
}
- :host([has-drawer]) cr-toolbar {
+ :host([has-drawer]) cr-toolbar,
+ :host([has-drawer]) cr-toolbar-selection-overlay {
--cr-toolbar-field-margin: 0;
}
+ cr-toolbar-selection-overlay {
+ --selection-overlay-max-width: var(--card-max-width);
+ }
+
/* Info button and dropdown. */
#info-button {
@@ -79,83 +71,44 @@
}
:host-context([dir=rtl]) #sync-notice {
- right: auto;
left: 24px;
- }
-
- /* Selection overlay. */
-
- :host(:not([has-drawer])) #overlay-wrapper {
- -webkit-margin-start: var(--side-bar-width);
- }
-
- #overlay-buttons {
- margin: 0 auto;
- max-width: var(--card-max-width);
- padding: 0 var(--card-padding-side);
- }
-
- paper-button {
- font-weight: 500;
- }
-
- #number-selected {
- flex: 1;
- }
-
- #cancel-icon-button {
- -webkit-margin-end: 24px;
- -webkit-margin-start: 2px;
+ right: auto;
}
</style>
- <div id="toolbar-container">
- <cr-toolbar id="main-toolbar"
- page-name="$i18n{title}"
- clear-label="$i18n{clearSearch}"
- search-prompt="$i18n{searchPrompt}"
- hidden$="[[itemsSelected_]]"
- spinner-active="[[spinnerActive]]"
- show-menu="[[hasDrawer]]"
- show-menu-promo="[[showMenuPromo]]"
- menu-label="$i18n{historyMenuButton}"
- menu-promo="$i18n{menuPromo}"
- close-menu-promo="$i18n{closeMenuPromo}"
- on-search-changed="onSearchChanged_">
- <div class="more-actions">
- <template is="dom-if" if="[[showSyncNotice]]">
- <button is="paper-icon-button-light" id="info-button"
- on-click="onInfoButtonTap_"
- aria-label="$i18n{hasSyncedResultsDescription}">
- <iron-icon icon="history:info-outline" id="info-button-icon">
- </iron-icon>
- </button>
- </template>
- </div>
- </cr-toolbar>
- <div id="sync-notice" hidden="[[!syncNoticeVisible_]]">
- $i18nRaw{hasSyncedResults}
+ <cr-toolbar id="main-toolbar"
+ page-name="$i18n{title}"
+ clear-label="$i18n{clearSearch}"
+ search-prompt="$i18n{searchPrompt}"
+ hidden$="[[itemsSelected_]]"
+ spinner-active="[[spinnerActive]]"
+ show-menu="[[hasDrawer]]"
+ show-menu-promo="[[showMenuPromo]]"
+ menu-label="$i18n{historyMenuButton}"
+ menu-promo="$i18n{menuPromo}"
+ close-menu-promo="$i18n{closeMenuPromo}"
+ on-search-changed="onSearchChanged_">
+ <div class="more-actions">
+ <template is="dom-if" if="[[showSyncNotice]]">
+ <button is="paper-icon-button-light" id="info-button"
+ on-click="onInfoButtonTap_"
+ aria-label="$i18n{hasSyncedResultsDescription}">
+ <iron-icon icon="history:info-outline" id="info-button-icon">
+ </iron-icon>
+ </button>
+ </template>
</div>
- <template is="dom-if" if="[[itemsSelected_]]">
- <div id="overlay-wrapper" hidden$="[[!itemsSelected_]]">
- <div id="overlay-buttons">
- <button is="paper-icon-button-light"
- id="cancel-icon-button"
- class="icon-button"
- on-tap="onClearSelectionTap_"
- title="$i18n{cancel}">
- <iron-icon icon="cr:clear"></iron-icon>
- </button>
- <div id="number-selected">[[numberOfItemsSelected_(count)]]</div>
- <paper-button id="cancel-button" on-tap="onClearSelectionTap_">
- $i18n{cancel}
- </paper-button>
- <paper-button id="delete-button" on-tap="onDeleteTap_">
- $i18n{delete}
- </paper-button>
- </div>
- </div>
- </template>
+ </cr-toolbar>
+ <div id="sync-notice" hidden="[[!syncNoticeVisible_]]">
+ $i18nRaw{hasSyncedResults}
</div>
+ <template is="dom-if" if="[[itemsSelected_]]">
+ <cr-toolbar-selection-overlay delete-label="$i18n{delete}"
+ cancel-label="$i18n{cancel}"
+ selection-label="[[numberOfItemsSelected_(count)]]"
+ on-clear-selected-items="clearSelectedItems"
+ on-delete-selected-items="deleteSelectedItems">
+ </cr-toolbar-selection-overlay>
+ </template>
</template>
<script src="chrome://history/history_toolbar.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_history/history_toolbar.js b/chromium/chrome/browser/resources/md_history/history_toolbar.js
index 2a42bd58ebb..62da493f7ab 100644
--- a/chromium/chrome/browser/resources/md_history/history_toolbar.js
+++ b/chromium/chrome/browser/resources/md_history/history_toolbar.js
@@ -96,6 +96,14 @@ Polymer({
this.searchField.showAndFocus();
},
+ deleteSelectedItems: function() {
+ this.fire('delete-selected');
+ },
+
+ clearSelectedItems: function() {
+ this.fire('unselect-all');
+ },
+
/**
* Changes the toolbar background color depending on whether any history items
* are currently selected.
@@ -169,16 +177,6 @@ Polymer({
},
/** @private */
- onClearSelectionTap_: function() {
- this.fire('unselect-all');
- },
-
- /** @private */
- onDeleteTap_: function() {
- this.fire('delete-selected');
- },
-
- /** @private */
numberOfItemsSelected_: function(count) {
return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
},
diff --git a/chromium/chrome/browser/resources/md_history/lazy_load.html b/chromium/chrome/browser/resources/md_history/lazy_load.html
index 7a5a1c0aa0e..666fd68a3ac 100644
--- a/chromium/chrome/browser/resources/md_history/lazy_load.html
+++ b/chromium/chrome/browser/resources/md_history/lazy_load.html
@@ -2,5 +2,6 @@
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
diff --git a/chromium/chrome/browser/resources/md_history/shared_vars.html b/chromium/chrome/browser/resources/md_history/shared_vars.html
index 5c419991660..2be07afcf76 100644
--- a/chromium/chrome/browser/resources/md_history/shared_vars.html
+++ b/chromium/chrome/browser/resources/md_history/shared_vars.html
@@ -21,7 +21,7 @@
--interactive-color: var(--google-blue-500);
--item-height: 44px;
--link-color: var(--google-blue-700);
- --primary-text-color: var(--paper-grey-800);
+ --primary-text-color: var(--paper-grey-900);
--secondary-text-color: var(--paper-grey-600);
--separator-color: rgba(0, 0, 0, 0.08);
--side-bar-width: 256px;
diff --git a/chromium/chrome/browser/resources/md_history/side_bar.html b/chromium/chrome/browser/resources/md_history/side_bar.html
index 79a518043d0..d26b03c3434 100644
--- a/chromium/chrome/browser/resources/md_history/side_bar.html
+++ b/chromium/chrome/browser/resources/md_history/side_bar.html
@@ -67,6 +67,11 @@
color: var(--link-color);
}
+ iron-selector > a[disabled] {
+ opacity: 0.65;
+ pointer-events: none;
+ }
+
#spacer {
flex: 1;
}
@@ -101,8 +106,11 @@
<paper-ripple></paper-ripple>
</a>
<div class="separator"></div>
- <a href="chrome://settings/clearBrowserData"
- on-tap="onClearBrowsingDataTap_" id="clear-browsing-data">
+ <a id="clear-browsing-data"
+ href="chrome://settings/clearBrowserData"
+ on-tap="onClearBrowsingDataTap_"
+ disabled$="[[guestSession_]]"
+ tabindex$="[[computeClearBrowsingDataTabIndex_(guestSession_)]]">
$i18n{clearBrowsingData}
<iron-icon icon="cr:open-in-new"></iron-icon>
<paper-ripple id="cbd-ripple"></paper-ripple>
diff --git a/chromium/chrome/browser/resources/md_history/side_bar.js b/chromium/chrome/browser/resources/md_history/side_bar.js
index e0f7e13ad31..cfc0b943489 100644
--- a/chromium/chrome/browser/resources/md_history/side_bar.js
+++ b/chromium/chrome/browser/resources/md_history/side_bar.js
@@ -13,6 +13,12 @@ Polymer({
notify: true,
},
+ /** @private */
+ guestSession_: {
+ type: Boolean,
+ value: loadTimeData.getBoolean('isGuestSession'),
+ },
+
showFooter: Boolean,
},
@@ -49,6 +55,14 @@ Polymer({
},
/**
+ * @return {number}
+ * @private
+ */
+ computeClearBrowsingDataTabIndex_: function() {
+ return this.guestSession_ ? -1 : 0;
+ },
+
+ /**
* Prevent clicks on sidebar items from navigating. These are only links for
* accessibility purposes, taps are handled separately by <iron-selector>.
* @private
diff --git a/chromium/chrome/browser/resources/md_history/synced_device_card.html b/chromium/chrome/browser/resources/md_history/synced_device_card.html
index e36c0e06bdd..6aa1c745c0e 100644
--- a/chromium/chrome/browser/resources/md_history/synced_device_card.html
+++ b/chromium/chrome/browser/resources/md_history/synced_device_card.html
@@ -107,7 +107,8 @@
<iron-collapse opened="{{opened}}" id="collapse">
<div id="tab-item-list">
- <template is="dom-repeat" items="[[tabs]]" as="tab" id="tab-list">
+ <template is="dom-repeat" items="[[tabs]]" as="tab" id="tab-list"
+ notify-dom-change>
<div class="item-container">
<div class="website-icon"></div>
<a href="[[tab.url]]" class="website-title" title="[[tab.title]]"
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js b/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
index 6580294638b..ff9296814a7 100644
--- a/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
@@ -896,6 +896,8 @@ Polymer({
return 'media-router:tv';
case media_router.SinkIconType.HANGOUT:
return 'media-router:hangout';
+ case media_router.SinkIconType.MEETING:
+ return 'media-router:meeting';
default:
return 'media-router:tv';
}
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.css b/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.css
index d2207455dee..9f1f1dbf6dd 100644
--- a/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.css
+++ b/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.css
@@ -2,7 +2,6 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-
#custom-controller {
display: inline-block;
height: 142px;
@@ -12,14 +11,12 @@
#route-action-buttons {
@apply(--layout-horizontal);
@apply(--layout-end-justified);
- margin: 0;
+ margin: 0 10px;
padding: 0;
white-space: nowrap;
}
.route-button {
- -webkit-padding-end: 24px;
- -webkit-padding-start: 0;
background-color: white;
line-height: 12px;
margin: 12px 0;
diff --git a/chromium/chrome/browser/resources/media_router/icons/media_router_icons.html b/chromium/chrome/browser/resources/media_router/icons/media_router_icons.html
index 900284ef515..aad793c7898 100644
--- a/chromium/chrome/browser/resources/media_router/icons/media_router_icons.html
+++ b/chromium/chrome/browser/resources/media_router/icons/media_router_icons.html
@@ -28,5 +28,6 @@
<g id="chromecast"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z"></path></g>
<!-- copy of third_party/polymer/v1_0/components-chromium/iron-icons/hardware-icons.html communication:message icon -->
<g id="hangout"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"></path></g>
+ <g id="meeting"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"></path></g>
</defs></svg>
</iron-iconset-svg>
diff --git a/chromium/chrome/browser/resources/media_router/media_router_data.js b/chromium/chrome/browser/resources/media_router/media_router_data.js
index 2c034acff2a..d51414707a3 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_data.js
+++ b/chromium/chrome/browser/resources/media_router/media_router_data.js
@@ -83,8 +83,9 @@ media_router.SinkIconType = {
CAST: 0,
CAST_AUDIO_GROUP: 1,
CAST_AUDIO: 2,
- HANGOUT: 3,
- GENERIC: 4,
+ MEETING: 3,
+ HANGOUT: 4,
+ GENERIC: 5,
};
/**
diff --git a/chromium/chrome/browser/resources/net_internals/dns_view.html b/chromium/chrome/browser/resources/net_internals/dns_view.html
index 0786cad0a26..07e3927f9c3 100644
--- a/chromium/chrome/browser/resources/net_internals/dns_view.html
+++ b/chromium/chrome/browser/resources/net_internals/dns_view.html
@@ -29,6 +29,7 @@
<ul>
<li>Active entries: <span id=dns-view-cache-active></span></li>
<li>Expired entries: <span id=dns-view-cache-expired></span></li>
+ <li>Network changes: <span id=dns-view-network-changes></span></li>
</ul>
<table class="styled-table">
@@ -37,7 +38,9 @@
<th>Hostname</th>
<th>Family</th>
<th>Addresses</th>
+ <th>TTL</th>
<th>Expires</th>
+ <th>Network changes</th>
</tr>
</thead>
<tbody id=dns-view-cache-tbody>
diff --git a/chromium/chrome/browser/resources/net_internals/dns_view.js b/chromium/chrome/browser/resources/net_internals/dns_view.js
index 05bb521f92a..dc03a9d23ab 100644
--- a/chromium/chrome/browser/resources/net_internals/dns_view.js
+++ b/chromium/chrome/browser/resources/net_internals/dns_view.js
@@ -55,6 +55,7 @@ var DnsView = (function() {
DnsView.ACTIVE_SPAN_ID = 'dns-view-cache-active';
DnsView.EXPIRED_SPAN_ID = 'dns-view-cache-expired';
+ DnsView.NETWORK_SPAN_ID = 'dns-view-network-changes';
DnsView.CACHE_TBODY_ID = 'dns-view-cache-tbody';
cr.addSingletonGetter(DnsView);
@@ -73,6 +74,7 @@ var DnsView = (function() {
$(DnsView.CACHE_TBODY_ID).innerHTML = '';
$(DnsView.ACTIVE_SPAN_ID).innerHTML = '0';
$(DnsView.EXPIRED_SPAN_ID).innerHTML = '0';
+ $(DnsView.NETWORK_SPAN_ID).innerHTML = '0';
// Update fields containing async DNS configuration information.
displayAsyncDnsConfig_(hostResolverInfo);
@@ -84,6 +86,8 @@ var DnsView = (function() {
// Fill in the basic cache information.
var hostResolverCache = hostResolverInfo.cache;
$(DnsView.CAPACITY_SPAN_ID).innerText = hostResolverCache.capacity;
+ $(DnsView.NETWORK_SPAN_ID).innerText =
+ valueOrDefault(hostResolverCache.network_changes, '');
var expiredEntries = 0;
// Date the cache was logged. This will be either now, when actively
@@ -99,6 +103,7 @@ var DnsView = (function() {
for (var i = 0; i < hostResolverCache.entries.length; ++i) {
var e = hostResolverCache.entries[i];
var tr = addNode($(DnsView.CACHE_TBODY_ID), 'tr');
+ var expired = false;
var hostnameCell = addNode(tr, 'td');
addTextNode(hostnameCell, e.hostname);
@@ -116,15 +121,35 @@ var DnsView = (function() {
addListToNode_(addNode(addressesCell, 'div'), e.addresses);
}
+ var ttlCell = addNode(tr, 'td');
+ addTextNode(ttlCell, valueOrDefault(e.ttl, ''));
+
var expiresDate = timeutil.convertTimeTicksToDate(e.expiration);
var expiresCell = addNode(tr, 'td');
timeutil.addNodeWithDate(expiresCell, expiresDate);
if (logDate > timeutil.convertTimeTicksToDate(e.expiration)) {
- ++expiredEntries;
+ expired = true;
var expiredSpan = addNode(expiresCell, 'span');
expiredSpan.classList.add('warning-text');
addTextNode(expiredSpan, ' [Expired]');
}
+
+ // HostCache keeps track of how many network changes have happened since
+ // it was created, and entries store what that number was at the time
+ // they were created. If more network changes have happened since an
+ // entry was created, the entry is expired.
+ var networkChangesCell = addNode(tr, 'td');
+ addTextNode(networkChangesCell, valueOrDefault(e.network_changes, ''));
+ if (e.network_changes < hostResolverCache.network_changes) {
+ expired = true;
+ var expiredSpan = addNode(networkChangesCell, 'span');
+ expiredSpan.classList.add('warning-text');
+ addTextNode(expiredSpan, ' [Expired]');
+ }
+
+ if (expired) {
+ expiredEntries++;
+ }
}
$(DnsView.ACTIVE_SPAN_ID).innerText =
@@ -192,5 +217,13 @@ var DnsView = (function() {
addNodeWithText(node, 'div', list[i]);
}
+ // TODO(mgersh): The |ttl| and |network_changes| properties were introduced in
+ // M59 and may not exist when loading older logs. This can be removed in M62.
+ function valueOrDefault(value, defaultValue) {
+ if (value != undefined)
+ return value;
+ return defaultValue;
+ }
+
return DnsView;
})();
diff --git a/chromium/chrome/browser/resources/net_internals/sdch_view.js b/chromium/chrome/browser/resources/net_internals/sdch_view.js
index f42ec4609dd..6f5191e4c79 100644
--- a/chromium/chrome/browser/resources/net_internals/sdch_view.js
+++ b/chromium/chrome/browser/resources/net_internals/sdch_view.js
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// TODO(rdsmith) Note that SDCH has been disabled in Chrome as of M59.
+// This code is being retained for examining dumps generated before that
+// milestone. It's probably fine to remove it in M64 or later.
+
/**
* This view displays information related to SDCH.
*
diff --git a/chromium/chrome/browser/resources/net_internals/source_entry.js b/chromium/chrome/browser/resources/net_internals/source_entry.js
index 25f0e81b402..126750c8cfe 100644
--- a/chromium/chrome/browser/resources/net_internals/source_entry.js
+++ b/chromium/chrome/browser/resources/net_internals/source_entry.js
@@ -82,6 +82,7 @@ var SourceEntry = (function() {
case EventSourceType.SOCKET_STREAM:
case EventSourceType.HTTP_STREAM_JOB:
case EventSourceType.HTTP_STREAM_JOB_CONTROLLER:
+ case EventSourceType.BIDIRECTIONAL_STREAM:
this.description_ = e.params.url;
break;
// TODO(davidben): Remove CONNECT_JOB after M57 is released.
diff --git a/chromium/chrome/browser/resources/ntp4/OWNERS b/chromium/chrome/browser/resources/ntp4/OWNERS
index 387af303635..f4065b6388d 100644
--- a/chromium/chrome/browser/resources/ntp4/OWNERS
+++ b/chromium/chrome/browser/resources/ntp4/OWNERS
@@ -1,3 +1,6 @@
estade@chromium.org
rbyers@chromium.org
dbeam@chromium.org
+
+# TEAM: ntp-dev@chromium.org
+# COMPONENT: UI>Browser>NewTabPage
diff --git a/chromium/chrome/browser/resources/options/browser_options.js b/chromium/chrome/browser/resources/options/browser_options.js
index 92d5a88f2eb..2266bdbe0b6 100644
--- a/chromium/chrome/browser/resources/options/browser_options.js
+++ b/chromium/chrome/browser/resources/options/browser_options.js
@@ -724,7 +724,7 @@ cr.define('options', function() {
// CUPS Print section (CrOS only).
if (cr.isChromeOS) {
- if (loadTimeData.getBoolean('cupsPrintEnabled')) {
+ if (!loadTimeData.getBoolean('cupsPrintDisabled')) {
$('cups-printers-section').hidden = false;
$('cupsPrintersManageButton').onclick = function() {
chrome.send('showCupsPrintDevicesPage');
diff --git a/chromium/chrome/browser/resources/options/compiled_resources.gyp b/chromium/chrome/browser/resources/options/compiled_resources.gyp
index 4ec0fcd2a3e..269ab040a84 100644
--- a/chromium/chrome/browser/resources/options/compiled_resources.gyp
+++ b/chromium/chrome/browser/resources/options/compiled_resources.gyp
@@ -44,7 +44,9 @@
'../../../../ui/webui/resources/js/util.js',
'../../../../chrome/browser/resources/chromeos/keyboard/keyboard_utils.js',
'../../../../ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '../../../../ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'../settings/compiled_resources2.gyp:route',
+ '../settings/people_page/compiled_resources2.gyp:easy_unlock_browser_proxy',
'../settings/people_page/compiled_resources2.gyp:fingerprint_browser_proxy',
'../settings/people_page/compiled_resources2.gyp:lock_screen_constants',
'../settings/people_page/compiled_resources2.gyp:lock_state_behavior',
diff --git a/chromium/chrome/browser/resources/options/controlled_setting.js b/chromium/chrome/browser/resources/options/controlled_setting.js
index fc5b960ab33..7b383215ac4 100644
--- a/chromium/chrome/browser/resources/options/controlled_setting.js
+++ b/chromium/chrome/browser/resources/options/controlled_setting.js
@@ -174,9 +174,13 @@ cr.define('options', function() {
'.controlled-setting-bubble-extension-manage-link');
var extensionId = this.extensionId;
manageLink.onclick = function() {
- uber.invokeMethodOnWindow(
- window.top, 'showPage',
- {pageId: 'extensions', path: '?id=' + extensionId});
+ if (window != window.top) {
+ uber.invokeMethodOnWindow(
+ window.top, 'showPage',
+ {pageId: 'extensions', path: '?id=' + extensionId});
+ } else {
+ window.open('chrome://extensions/?id=' + extensionId);
+ }
};
var disableButton = extensionContainer.querySelector(
diff --git a/chromium/chrome/browser/resources/options/i18n_setup.html b/chromium/chrome/browser/resources/options/i18n_setup.html
new file mode 100644
index 00000000000..cec2322227e
--- /dev/null
+++ b/chromium/chrome/browser/resources/options/i18n_setup.html
@@ -0,0 +1,6 @@
+<!-- This file is intentionally empty.
+ settings-lock-screen element will import i18n_setup.html file in settings.
+ The scripts included by i18n_setup.html is already included in options.html,
+ including the same script again seems to throw some errors. So creating an
+ empty file here just for options.
+-->
diff --git a/chromium/chrome/browser/resources/options/import_data_overlay.html b/chromium/chrome/browser/resources/options/import_data_overlay.html
index 89761e52f85..7524577dc9d 100644
--- a/chromium/chrome/browser/resources/options/import_data_overlay.html
+++ b/chromium/chrome/browser/resources/options/import_data_overlay.html
@@ -14,10 +14,12 @@
<div class="checkbox controlled-setting-with-label"
id="import-history-with-label">
<label>
- <input id="import-history" type="checkbox" pref="import_history">
+ <input id="import-history" type="checkbox"
+ pref="import_dialog_history">
<span>
<span i18n-content="importHistory"></span>
- <span class="controlled-setting-indicator" pref="import_history">
+ <span class="controlled-setting-indicator"
+ pref="import_dialog_history">
</span>
</span>
</label>
@@ -26,11 +28,11 @@
id="import-favorites-with-label">
<label>
<input id="import-favorites" type="checkbox"
- pref="import_bookmarks">
+ pref="import_dialog_bookmarks">
<span>
<span i18n-content="importFavorites"></span>
<span class="controlled-setting-indicator"
- pref="import_bookmarks"></span>
+ pref="import_dialog_bookmarks"></span>
</span>
</label>
</div>
@@ -38,11 +40,11 @@
id="import-passwords-with-label">
<label>
<input id="import-passwords" type="checkbox"
- pref="import_saved_passwords">
+ pref="import_dialog_saved_passwords">
<span>
<span i18n-content="importPasswords"></span>
<span class="controlled-setting-indicator"
- pref="import_saved_passwords"></span>
+ pref="import_dialog_saved_passwords"></span>
</span>
</label>
</div>
@@ -50,11 +52,11 @@
id="import-search-with-label">
<label>
<input id="import-search" type="checkbox"
- pref="import_search_engine">
+ pref="import_dialog_search_engine">
<span>
<span i18n-content="importSearch"></span>
<span class="controlled-setting-indicator"
- pref="import_search_engine"></span>
+ pref="import_dialog_search_engine"></span>
</span>
</label>
</div>
@@ -62,11 +64,11 @@
id="import-autofill-form-data-with-label">
<label>
<input id="import-autofill-form-data" type="checkbox"
- pref="import_autofill_form_data">
+ pref="import_dialog_autofill_form_data">
<span i18n-content="importAutofillFormData"></span>
</label>
<span class="controlled-setting-indicator"
- pref="import_autofill_form_data"></span>
+ pref="import_dialog_autofill_form_data"></span>
</div>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/options/import_data_overlay.js b/chromium/chrome/browser/resources/options/import_data_overlay.js
index c526fb1c188..2d9fd60dc8d 100644
--- a/chromium/chrome/browser/resources/options/import_data_overlay.js
+++ b/chromium/chrome/browser/resources/options/import_data_overlay.js
@@ -179,11 +179,11 @@ cr.define('options', function() {
* @private
*/
clearUserPrefs_: function() {
- var importPrefs = ['import_history',
- 'import_bookmarks',
- 'import_saved_passwords',
- 'import_search_engine',
- 'import_autofill_form_data'];
+ var importPrefs = [
+ 'import_dialog_history', 'import_dialog_bookmarks',
+ 'import_dialog_saved_passwords', 'import_dialog_search_engine',
+ 'import_dialog_autofill_form_data'
+ ];
for (var i = 0; i < importPrefs.length; i++)
Preferences.clearPref(importPrefs[i], true);
},
diff --git a/chromium/chrome/browser/resources/options/options.html b/chromium/chrome/browser/resources/options/options.html
index efb9633f083..948096d1530 100644
--- a/chromium/chrome/browser/resources/options/options.html
+++ b/chromium/chrome/browser/resources/options/options.html
@@ -72,7 +72,7 @@
<link rel="stylesheet" href="certificate_manager.css">
<link rel="stylesheet" href="certificate_tree.css">
</if>
-<script src="chrome://resources/js/action_link.js"></script>
+<link rel="import" href="chrome://resources/html/action_link.html">
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/event_tracker.js"></script>
<script src="chrome://resources/js/cr/event_target.js"></script>
diff --git a/chromium/chrome/browser/resources/options/options.js b/chromium/chrome/browser/resources/options/options.js
index 821d7eaf5b7..cdfb732b1ad 100644
--- a/chromium/chrome/browser/resources/options/options.js
+++ b/chromium/chrome/browser/resources/options/options.js
@@ -290,6 +290,9 @@ function load() {
window.setTimeout(function() {
document.documentElement.classList.remove('loading');
chrome.send('onFinishedLoadingOptions');
+ chrome.send(
+ 'metricsHandler:recordTime',
+ ['Settings.TimeUntilInteractive', window.performance.now()]);
}, 0);
}
diff --git a/chromium/chrome/browser/resources/options_resources.grd b/chromium/chrome/browser/resources/options_resources.grd
index 71abcdaee0f..4ddc0f1a382 100644
--- a/chromium/chrome/browser/resources/options_resources.grd
+++ b/chromium/chrome/browser/resources/options_resources.grd
@@ -21,49 +21,51 @@
<structure name="IDR_OPTIONS_ICONS_HTML"
file="settings/icons.html"
type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OPTIONS_PIN_KEYBOARD_HTML"
file="chromeos/quick_unlock/pin_keyboard.html"
type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OPTIONS_PIN_KEYBOARD_JS"
file="chromeos/quick_unlock/pin_keyboard.js"
type="chrome_html"
- flattenhtml="true" />
+ preprocess="true" />
<structure name="IDR_OPTIONS_PASSWORD_PROMPT_DIALOG_JS"
file="settings/people_page/password_prompt_dialog.js"
type="chrome_html" />
<structure name="IDR_OPTIONS_PASSWORD_PROMPT_DIALOG_HTML"
file="settings/people_page/password_prompt_dialog.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OPTIONS_LOCK_SCREEN_CONSTANTS_JS"
file="settings/people_page/lock_screen_constants.js"
type="chrome_html" />
<structure name="IDR_OPTIONS_LOCK_SCREEN_CONSTANTS_HTML"
file="settings/people_page/lock_screen_constants.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OPTIONS_LOCK_STATE_BEHAVIOR_JS"
file="settings/people_page/lock_state_behavior.js"
type="chrome_html" />
<structure name="IDR_OPTIONS_LOCK_STATE_BEHAVIOR_HTML"
file="settings/people_page/lock_state_behavior.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OPTIONS_SETUP_PIN_DIALOG_JS"
file="settings/people_page/setup_pin_dialog.js"
type="chrome_html" />
<structure name="IDR_OPTIONS_SETUP_PIN_DIALOG_HTML"
file="settings/people_page/setup_pin_dialog.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
+ <structure name="IDR_OPTIONS_EASY_UNLOCK_BROWSER_PROXY_JS"
+ file="settings/people_page/easy_unlock_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_OPTIONS_EASY_UNLOCK_BROWSER_PROXY_HTML"
+ file="settings/people_page/easy_unlock_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_OPTIONS_EASY_UNLOCK_TURN_OFF_DIALOG_JS"
+ file="settings/people_page/easy_unlock_turn_off_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_OPTIONS_EASY_UNLOCK_TURN_OFF_DIALOG_HTML"
+ file="settings/people_page/easy_unlock_turn_off_dialog.html"
+ type="chrome_html" />
<structure name="IDR_OPTIONS_FINGERPRINT_LIST_JS"
file="settings/people_page/fingerprint_list.js"
type="chrome_html" />
@@ -93,78 +95,68 @@
type="chrome_html" />
<structure name="IDR_OPTIONS_LOCK_SCREEN_HTML"
file="settings/people_page/lock_screen.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OPTIONS_ROUTE_HTML"
file="settings/route.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OPTIONS_ROUTE_JS"
file="settings/route.js"
type="chrome_html"
- flattenhtml="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_SHARED_CSS_HTML"
file="settings/settings_shared_css.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SLIDER_HTML"
+ file="settings/controls/settings_slider.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SLIDER_JS"
+ file="settings/controls/settings_slider.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_TOGGLE_BUTTON_HTML"
file="settings/controls/settings_toggle_button.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_TOGGLE_BUTTON_JS"
file="settings/controls/settings_toggle_button.js"
- type="chrome_html"
- flattenhtml="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_BOOLEAN_CONTROL_BEHAVIOR_HTML"
file="settings/controls/settings_boolean_control_behavior.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_BOOLEAN_CONTROL_BEHAVIOR_JS"
file="settings/controls/settings_boolean_control_behavior.js"
- type="chrome_html"
- flattenhtml="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PREF_CONTROL_BEHAVIOR_HTML"
file="settings/controls/pref_control_behavior.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PREF_CONTROL_BEHAVIOR_JS"
file="settings/controls/pref_control_behavior.js"
- type="chrome_html"
- flattenhtml="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_VARS_CSS_HTML"
file="settings/settings_vars_css.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PREFS_BEHAVIOR_HTML"
file="settings/prefs/prefs_behavior.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PREFS_BEHAVIOR_JS"
file="settings/prefs/prefs_behavior.js"
- type="chrome_html"
- flattenhtml="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PREFS_TYPES_HTML"
file="settings/prefs/prefs_types.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PREFS_TYPES_JS"
file="settings/prefs/prefs_types.js"
- type="chrome_html"
- flattenhtml="true" />
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PREFS_HTML"
+ file="settings/prefs/prefs.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PREFS_JS"
+ file="settings/prefs/prefs.js"
+ type="chrome_html" />
+ <structure name="IDR_OPTIONS_I18N_SETUP_HTML"
+ file="options/i18n_setup.html"
+ type="chrome_html" />
<structure name="IDR_OPTIONS_POLYMER_ELEMENTS_HTML"
file="options/options_polymer.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
</if>
</structures>
</release>
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
index 29310477b32..bc016197575 100644
--- a/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
+++ b/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
@@ -1,5 +1,5 @@
{
- "x-version": 21,
+ "x-version": 22,
"google-talk": {
"mime_types": [
],
@@ -80,9 +80,9 @@
],
"versions": [
{
- "version": "25.0.0.148",
+ "version": "25.0.0.171",
"status": "up_to_date",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-15.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json
index a07eb278763..338dd128ec9 100644
--- a/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json
+++ b/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json
@@ -1,5 +1,5 @@
{
- "x-version": 27,
+ "x-version": 28,
"google-talk": {
"mime_types": [
],
@@ -115,9 +115,9 @@
],
"versions": [
{
- "version": "25.0.0.148",
+ "version": "25.0.0.171",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-15.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json
index 0f4a9286e83..a46965f4455 100644
--- a/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json
+++ b/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json
@@ -1,5 +1,5 @@
{
- "x-version": 36,
+ "x-version": 37,
"google-talk": {
"mime_types": [
],
@@ -137,9 +137,9 @@
],
"versions": [
{
- "version": "25.0.0.148",
+ "version": "25.0.0.171",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-10.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-15.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/predictors/predictors.css b/chromium/chrome/browser/resources/predictors/predictors.css
index fb70515eff2..e1380e4e291 100644
--- a/chromium/chrome/browser/resources/predictors/predictors.css
+++ b/chromium/chrome/browser/resources/predictors/predictors.css
@@ -37,6 +37,10 @@ td {
padding: 3px;
}
+tr td:first-child[rowspan] {
+ background-color: rgb(215, 215, 215);
+}
+
tbody > td:first-child {
white-space: nowrap;
}
diff --git a/chromium/chrome/browser/resources/predictors/resource_prefetch_predictor.js b/chromium/chrome/browser/resources/predictors/resource_prefetch_predictor.js
index f725105441d..35e59385a0d 100644
--- a/chromium/chrome/browser/resources/predictors/resource_prefetch_predictor.js
+++ b/chromium/chrome/browser/resources/predictors/resource_prefetch_predictor.js
@@ -72,12 +72,11 @@ function renderCacheData(body, database) {
var t = document.createElement('td');
t.rowSpan = main.resources.length;
t.textContent = truncateString(main.main_frame_url);
- t.className = 'last';
row.appendChild(t);
}
- if (j == main.resources.length - 1)
- row.className = 'last';
+ row.className = resource.is_prefetchable ? 'action-prerender'
+ : 'action-none';
row.appendChild(document.createElement('td')).textContent =
truncateString(resource.resource_url);
diff --git a/chromium/chrome/browser/resources/print_preview/common/search_box.css b/chromium/chrome/browser/resources/print_preview/common/search_box.css
index 3b5ba301d86..bbc82e1b976 100644
--- a/chromium/chrome/browser/resources/print_preview/common/search_box.css
+++ b/chromium/chrome/browser/resources/print_preview/common/search_box.css
@@ -10,15 +10,15 @@
.search-box-icon {
-webkit-user-select: none;
display: inline-block;
- height: 12px;
+ height: 1em;
left: 8px;
position: absolute;
right: 8px;
top: 6px;
- width: 12px;
+ width: 1em;
}
.search-box-input {
- text-indent: 24px;
+ text-indent: 2em;
width: 100%;
}
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination_store.js b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
index 548a437af10..34021ccf7b6 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
@@ -312,8 +312,6 @@ cr.define('print_preview', function() {
'print_preview.DestinationStore.CACHED_SELECTED_DESTINATION_INFO_READY',
SELECTED_DESTINATION_CAPABILITIES_READY:
'print_preview.DestinationStore.SELECTED_DESTINATION_CAPABILITIES_READY',
- PRINTER_CONFIGURED:
- 'print_preview.DestinationStore.PRINTER_CONFIGURED',
};
/**
@@ -1109,28 +1107,11 @@ cr.define('print_preview', function() {
* Attempt to resolve the capabilities for a Chrome OS printer.
* @param {!print_preview.Destination} destination The destination which
* requires resolution.
+ * @return {!Promise<!print_preview.PrinterSetupResponse>}
*/
resolveCrosDestination: function(destination) {
assert(destination.origin == print_preview.Destination.Origin.CROS);
- this.nativeLayer_.setupPrinter(destination.id).then(
- /**
- * Handle the result of a successful PRINTER_SETUP request.
- * @param {!print_preview.PrinterSetupResponse} response.
- */
- function(response) {
- this.dispatchEvent(new CustomEvent(
- DestinationStore.EventType.PRINTER_CONFIGURED, {
- detail: response
- }));
- }.bind(this),
- /**
- * Calling printer setup failed.
- */
- function() {
- this.dispatchEvent(new CustomEvent(
- DestinationStore.EventType.PRINTER_CONFIGURED,
- {detail: {printerId: destination.id, success: false}}));
- }.bind(this));
+ return this.nativeLayer_.setupPrinter(destination.id);
},
/**
diff --git a/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js b/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js
index 007419c8d6a..9bc13f0846f 100644
--- a/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js
+++ b/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js
@@ -174,7 +174,9 @@ cr.define('print_preview', function() {
this.appState_,
this.documentInfo_,
this.marginsType_,
- this.customMargins_);
+ this.customMargins_,
+ this.mediaSize_,
+ this.landscape_);
/**
* Fit-to-page ticket item.
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js
index 38ffc00b5fe..c756981db7d 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js
@@ -148,16 +148,14 @@ cr.define('print_preview.ticket_items', function() {
* @private
*/
getMarginMax_: function(orientation, oppositeMargin) {
- var max;
- if (orientation == CustomMargins.Orientation.TOP ||
- orientation == CustomMargins.Orientation.BOTTOM) {
- max = this.getDocumentInfoInternal().pageSize.height - oppositeMargin -
- CustomMargins.MINIMUM_MARGINS_DISTANCE_;
- } else {
- max = this.getDocumentInfoInternal().pageSize.width - oppositeMargin -
- CustomMargins.MINIMUM_MARGINS_DISTANCE_;
- }
- return Math.round(max);
+ var dimensionLength = (orientation == CustomMargins.Orientation.TOP ||
+ orientation == CustomMargins.Orientation.BOTTOM) ?
+ this.getDocumentInfoInternal().pageSize.height :
+ this.getDocumentInfoInternal().pageSize.width;
+
+ var totalMargin = dimensionLength -
+ CustomMargins.MINIMUM_MARGINS_DISTANCE_;
+ return Math.round(totalMargin > 0 ? totalMargin - oppositeMargin : 0);
}
};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js
index 4f0840693f6..093fc6e6bf1 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js
@@ -16,10 +16,15 @@ cr.define('print_preview.ticket_items', function() {
* that stores which predefined margins to print with.
* @param {!print_preview.ticket_items.CustomMargins} customMargins Ticket
* item that stores custom margin values.
+ * @param {!print_preview.ticket_items.MediaSize} mediaSize Ticket item that
+ * stores media size values.
+ * @param {!print_preview.ticket_items.Landscape} landscape Ticket item that
+ * stores landscape values.
* @constructor
* @extends {print_preview.ticket_items.TicketItem}
*/
- function HeaderFooter(appState, documentInfo, marginsType, customMargins) {
+ function HeaderFooter(appState, documentInfo, marginsType, customMargins,
+ mediaSize, landscape) {
print_preview.ticket_items.TicketItem.call(
this,
appState,
@@ -29,21 +34,40 @@ cr.define('print_preview.ticket_items', function() {
/**
* Ticket item that stores which predefined margins to print with.
- * @type {!print_preview.ticket_items.MarginsType}
- * @private
+ * @private {!print_preview.ticket_items.MarginsType}
*/
this.marginsType_ = marginsType;
/**
* Ticket item that stores custom margin values.
- * @type {!print_preview.ticket_items.CustomMargins}
- * @private
+ * @private {!print_preview.ticket_items.CustomMargins}
*/
this.customMargins_ = customMargins;
+ /**
+ * Ticket item that stores media size values.
+ * @private {!print_preview.ticket_items.MediaSize}
+ */
+ this.mediaSize_ = mediaSize;
+
+ /**
+ * Ticket item that stores landscape values.
+ * @private {!print_preview.ticket_items.Landscape}
+ */
+ this.landscape_ = landscape;
+
this.addEventListeners_();
};
+ /**
+ * Minimum height of page in microns to allow headers and footers. Should
+ * match the value for min_size_printer_units in printing/print_settings.cc
+ * so that we do not request header/footer for margins that will be zero.
+ * @private {number}
+ * @const
+ */
+ HeaderFooter.MINIMUM_HEIGHT_MICRONS_ = 25400;
+
HeaderFooter.prototype = {
__proto__: print_preview.ticket_items.TicketItem.prototype,
@@ -56,10 +80,20 @@ cr.define('print_preview.ticket_items', function() {
isCapabilityAvailable: function() {
if (!this.getDocumentInfoInternal().isModifiable) {
return false;
- } else if (this.marginsType_.getValue() ==
+ }
+ if (this.marginsType_.getValue() ==
print_preview.ticket_items.MarginsType.Value.NO_MARGINS) {
return false;
- } else if (this.marginsType_.getValue() ==
+ }
+ var microns = this.landscape_.getValue() ?
+ this.mediaSize_.getValue().width_microns :
+ this.mediaSize_.getValue().height_microns;
+ if (microns < HeaderFooter.MINIMUM_HEIGHT_MICRONS_) {
+ // If this is a small paper size, there is not space for headers
+ // and footers regardless of the margins.
+ return false;
+ }
+ if (this.marginsType_.getValue() ==
print_preview.ticket_items.MarginsType.Value.MINIMUM) {
return true;
}
@@ -102,6 +136,14 @@ cr.define('print_preview.ticket_items', function() {
this.customMargins_,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.dispatchChangeEventInternal.bind(this));
+ this.getTrackerInternal().add(
+ this.mediaSize_,
+ print_preview.ticket_items.TicketItem.EventType.CHANGE,
+ this.dispatchChangeEventInternal.bind(this));
+ this.getTrackerInternal().add(
+ this.landscape_,
+ print_preview.ticket_items.TicketItem.EventType.CHANGE,
+ this.dispatchChangeEventInternal.bind(this));
}
};
diff --git a/chromium/chrome/browser/resources/print_preview/native_layer.js b/chromium/chrome/browser/resources/print_preview/native_layer.js
index 6b522fe1988..652c87cc879 100644
--- a/chromium/chrome/browser/resources/print_preview/native_layer.js
+++ b/chromium/chrome/browser/resources/print_preview/native_layer.js
@@ -312,6 +312,10 @@ cr.define('print_preview', function() {
'copies': 1,
'collate': true,
'rasterizePDF': false,
+ 'dpiHorizontal': "horizontal_dpi" in printTicketStore.dpi.getValue() ?
+ printTicketStore.dpi.getValue().horizontal_dpi : 0,
+ 'dpiVertical': "vertical_dpi" in printTicketStore.dpi.getValue() ?
+ printTicketStore.dpi.getValue().vertical_dpi : 0,
'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),
'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue()
};
@@ -387,6 +391,10 @@ cr.define('print_preview', function() {
'printWithExtension': destination.isExtension,
'rasterizePDF': printTicketStore.rasterize.getValue(),
'scaleFactor': printTicketStore.scaling.getValueAsNumber(),
+ 'dpiHorizontal': "horizontal_dpi" in printTicketStore.dpi.getValue() ?
+ printTicketStore.dpi.getValue().horizontal_dpi : 0,
+ 'dpiVertical': "vertical_dpi" in printTicketStore.dpi.getValue() ?
+ printTicketStore.dpi.getValue().vertical_dpi : 0,
'deviceName': destination.id,
'isFirstRequest': false,
'requestID': -1,
diff --git a/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js b/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js
index ca553a7c7a1..522995c805f 100644
--- a/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js
+++ b/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js
@@ -602,14 +602,21 @@ cr.define('print_preview', function() {
},
/**
- * Called when the generation of a preview fails. Shows an error message.
- * @private
+ * Cancels the timeout so that an error message can be shown.
*/
- onPreviewGenerationFail_: function() {
+ cancelTimeout: function() {
if (this.loadingTimeout_) {
clearTimeout(this.loadingTimeout_);
this.loadingTimeout_ = null;
}
+ },
+
+ /**
+ * Called when the generation of a preview fails. Shows an error message.
+ * @private
+ */
+ onPreviewGenerationFail_: function() {
+ this.cancelTimeout();
this.showMessage_(PreviewArea.MessageId_.PREVIEW_FAILED);
cr.dispatchSimpleEvent(
this, PreviewArea.EventType.PREVIEW_GENERATION_FAIL);
@@ -622,11 +629,7 @@ cr.define('print_preview', function() {
* @private
*/
onPluginLoad_: function() {
- if (this.loadingTimeout_) {
- clearTimeout(this.loadingTimeout_);
- this.loadingTimeout_ = null;
- }
-
+ this.cancelTimeout();
this.setOverlayVisible_(false);
this.isPluginReloaded_ = true;
this.dispatchPreviewGenerationDoneIfReady_();
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.css b/chromium/chrome/browser/resources/print_preview/print_preview.css
index 982b9ff4bbb..fe76b9f991c 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.css
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.css
@@ -35,7 +35,7 @@ header {
#navbar-content-title {
color: black;
- font-size: 15px;
+ font-size: 1.25em;
font-weight: normal;
margin: 0;
padding-bottom: 6px;
@@ -73,9 +73,14 @@ header {
padding-top: 10px;
}
-.right-column .radio input[type='radio'] {
- height: 13px;
- width: 13px;
+.right-column .radio input[type='radio'],
+.right-column label input[type='checkbox'] {
+ --min-size: 13.19px;
+ --size: 1.1em;
+ height: var(--size);
+ min-height: var(--min-size);
+ min-width: var(--min-size);
+ width: var(--size);
}
.left-column {
@@ -88,7 +93,7 @@ header {
.left-column h1 {
color: #646464;
- font-size: 12px;
+ font-size: 1em;
margin-bottom: 0;
margin-top: 0;
}
@@ -152,7 +157,6 @@ span.hint {
font-size: 0.9em;
font-weight: bold;
height: 0;
- line-height: 10px;
margin: 0;
overflow: hidden;
transition: color 200ms;
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.html b/chromium/chrome/browser/resources/print_preview/print_preview.html
index e02f6b0012e..e32bbe93ab8 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.html
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.html
@@ -109,7 +109,6 @@
<include src="search/destination_list.html">
<include src="search/destination_list_item.html">
<include src="search/fedex_tos.html">
- <include src="search/cros_destination_resolver.html">
<include src="search/provisional_destination_resolver.html">
<script src="chrome://resources/js/i18n_template.js"></script>
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.js b/chromium/chrome/browser/resources/print_preview/print_preview.js
index 04fdd1dab9f..a4b96fcd52c 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.js
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.js
@@ -957,7 +957,10 @@ cr.define('print_preview', function() {
*/
onSettingsInvalid_: function() {
this.uiState_ = PrintPreview.UiState_.ERROR;
+ this.isPreviewGenerationInProgress_ = false;
+ this.printHeader_.isPrintButtonEnabled = false;
console.error('Invalid settings error reported from native layer');
+ this.previewArea_.cancelTimeout();
this.previewArea_.showCustomMessage(
loadTimeData.getString('invalidPrinterSettings'));
},
@@ -1362,7 +1365,6 @@ cr.define('print_preview', function() {
// <include src="search/destination_list_item.js">
// <include src="search/destination_search.js">
// <include src="search/fedex_tos.js">
-// <include src="search/cros_destination_resolver.js">
// <include src="search/provisional_destination_resolver.js">
window.addEventListener('DOMContentLoaded', function() {
diff --git a/chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.html b/chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.html
deleted file mode 100644
index 5d4fa3e5dc7..00000000000
--- a/chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<div id="cros-printer-resolver" class="overlay transparent" hidden>
- <div class="page">
- <div class="close-button"></div>
- <div class="action-area">
- <div class="resolving-message">
- $i18n{resolveCrosPrinterMessage}
- </div>
- </div>
- </div>
-</div>
diff --git a/chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.js b/chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.js
deleted file mode 100644
index a7f64d4a5b0..00000000000
--- a/chromium/chrome/browser/resources/print_preview/search/cros_destination_resolver.js
+++ /dev/null
@@ -1,142 +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.
-
-cr.define('print_preview', function() {
- 'use strict';
-
- /** @enum {string} */
- var ResolverState = {
- INITIAL: 'INITIAL',
- CONFIGURING_PRINTER: 'CONFIGURING_PRINTER',
- ERROR: 'ERROR',
- DONE: 'DONE'
- };
-
- /**
- * Overlay used to notify the user of printer setup steps for Chrome OS
- * printers. Printer installation can occur before any print job is executed.
- *
- * @param {!print_preview.DestinationStore} destinationStore The destination
- * store containing the destination. Used as a proxy to native layer for
- * resolving the destination.
- * @param {!print_preview.Destination} destination The destination that has
- * to be resolved.
- * @constructor
- * @extends {print_preview.Overlay}
- */
- function CrosDestinationResolver(destinationStore, destination) {
- print_preview.Overlay.call(this);
-
- /** @private {!print_preview.DestinationStore} */
- this.destinationStore_ = destinationStore;
- /** @private {!print_preview.Destination} */
- this.destination_ = destination;
-
- /** @private {!ResolverState} */
- this.state_ = ResolverState.INITIAL;
-
- /**
- * Promise resolver for promise returned by {@code this.run}.
- * @private {?PromiseResolver<!print_preview.Destination>}
- */
- this.promiseResolver_ = null;
- };
-
- CrosDestinationResolver.prototype = {
- __proto__: print_preview.Overlay.prototype,
-
- /** @override */
- enterDocument: function() {
- print_preview.Overlay.prototype.enterDocument.call(this);
-
- this.tracker.add(
- this.destinationStore_,
- print_preview.DestinationStore.EventType.PRINTER_CONFIGURED,
- this.onDestinationResolved_.bind(this));
- },
-
- /** @override */
- createDom: function() {
- this.setElementInternal(this.cloneTemplateInternal(
- 'cros-printer-resolver'));
- },
-
- /**
- * Dispatch the request to resolve the destination to the native layer.
- * @private
- */
- startResolveDestination_: function() {
- assert(this.state_ == ResolverState.INITIAL);
- assert(!this.promiseResolver_, 'Promise resolver already set');
- this.promiseResolver_ = new PromiseResolver();
- this.destinationStore_.resolveCrosDestination(this.destination_);
- this.setState_(ResolverState.CONFIGURING_PRINTER);
- },
-
- /**
- * Handler for PRINTER_SETUP event. It finalizes the
- * resolver state once the destination associated with the resolver gets
- * resolved.
- * @param {CustomEvent} event
- * @private
- */
- onDestinationResolved_: function(event) {
- assert(this.promiseResolver_, 'Promise resolver not found');
- var detail = event.detail;
- if (detail.success) {
- this.setState_(ResolverState.DONE);
- assert(detail.capabilities);
- // |detail| contains printerId and capabilities.
- this.promiseResolver_.resolve(detail);
- this.setIsVisible(false);
- } else {
- this.setState_(ResolverState.ERROR);
- this.promiseResolver_.reject();
- }
-
- this.promiseResolver_ = null;
- },
-
- /**
- * Sets new resolver state and updates the UI accordingly.
- * @param {!ResolverState} state
- * @private
- */
- setState_: function(state) {
- if (this.state_ == state)
- return;
-
- this.state_ = state;
- this.updateUI_();
- },
-
- /**
- * Updates the resolver overlay UI to match the resolver state.
- * @private
- */
- updateUI_: function() {
- // TODO(crbug.com/677567): Replace with meaningful UI.
- },
-
- /**
- * Initiates and shows the resolver overlay.
- * @param {!HTMLElement} parent The element that should parent the resolver
- * UI.
- * @return {!Promise<!print_preview.Destination>} Promise that will be
- * fulfilled when the destination resolving is finished.
- */
- run: function(parent) {
- this.render(parent);
- this.setIsVisible(true);
- this.startResolveDestination_();
-
- assert(this.promiseResolver_, 'Promise resolver not created.');
- return this.promiseResolver_.promise;
- }
- };
-
- return {
- CrosDestinationResolver: CrosDestinationResolver
- };
-});
diff --git a/chromium/chrome/browser/resources/print_preview/search/destination_list.js b/chromium/chrome/browser/resources/print_preview/search/destination_list.js
index 351d3118498..89b8163ea99 100644
--- a/chromium/chrome/browser/resources/print_preview/search/destination_list.js
+++ b/chromium/chrome/browser/resources/print_preview/search/destination_list.js
@@ -225,6 +225,17 @@ cr.define('print_preview', function() {
},
/**
+ * @param {string} destinationId The ID of the destination.
+ * @return {?print_preview.DestinationListItem} The found destination list
+ * item or null if not found.
+ */
+ getDestinationItem: function(destinationId) {
+ return this.listItems_.find(function(listItem) {
+ return listItem.destination.id == destinationId;
+ }) || null;
+ },
+
+ /**
* @param {string} text Text to set the action link to.
* @protected
*/
diff --git a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.css b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.css
index 8f358a55d9d..02f1cf4f778 100644
--- a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.css
+++ b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.css
@@ -98,3 +98,16 @@
margin: 0 3px;
width: 24px;
}
+
+.configuring-in-progress-text,
+.configuring-failed-text {
+ -webkit-margin-start: 1em;
+ flex: 0 1 auto;
+ line-height: 24px;
+ vertical-align: middle;
+}
+
+.configuring-failed-text {
+ color: red;
+ font-style: italic;
+}
diff --git a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.html b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.html
index a3678038492..f77a404f17f 100644
--- a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.html
+++ b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.html
@@ -13,5 +13,16 @@
<span class="extension-name"></span>
<span class="extension-icon" role="button" tabindex="0"></span>
</span>
+<if expr="chromeos">
+ <span class="configuring-in-progress-text" hidden>
+ $i18n{configuringInProgressText}
+ <span class="configuring-text-jumping-dots">
+ <span>.</span><span>.</span><span>.</span>
+ </span>
+ </span>
+ <span class="configuring-failed-text" hidden>
+ $i18n{configuringFailedText}
+ </span>
+</if>
</span>
</li>
diff --git a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js
index 8b529d45acc..b13dc5487fc 100644
--- a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js
+++ b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js
@@ -53,6 +53,8 @@ cr.define('print_preview', function() {
* @enum {string}
*/
DestinationListItem.EventType = {
+ // Dispatched to check the printer needs to be configured before activation.
+ CONFIGURE_REQUEST: 'print_preview.DestinationListItem.CONFIGURE_REQUEST',
// Dispatched when the list item is activated.
SELECT: 'print_preview.DestinationListItem.SELECT',
REGISTER_PROMO_CLICKED:
@@ -99,6 +101,49 @@ cr.define('print_preview', function() {
},
/**
+ * Called if the printer configuration request is accepted. Show the waiting
+ * message to the user as the configuration might take longer than expected.
+ */
+ onConfigureRequestAccepted: function() {
+ // It must be a Chrome OS CUPS printer which hasn't been set up before.
+ assert(
+ this.destination_.origin == print_preview.Destination.Origin.CROS &&
+ !this.destination_.capabilities);
+ this.updateConfiguringMessage_(true);
+ },
+
+ /**
+ * Called if the printer configuration request is rejected. The request is
+ * rejected if another printer is setting up in process or the current
+ * printer doesn't need to be setup.
+ * @param {boolean} otherPrinterSetupInProgress
+ */
+ onConfigureRequestRejected: function(otherPrinterSetupInProgress) {
+ // If another printer setup is in progress, the printer should not be
+ // activated.
+ if (!otherPrinterSetupInProgress)
+ this.onDestinationActivated_();
+ },
+
+ /**
+ * Called when the printer configuration request is resolved successful or
+ * failed.
+ * @param response {!print_preview.PrinterSetupResponse}
+ */
+ onConfigureResolved: function(response) {
+ assert(response.printerId == this.destination_.id);
+ if (response.success) {
+ this.updateConfiguringMessage_(false);
+ this.destination_.capabilities = response.capabilities;
+ this.onDestinationActivated_();
+ } else {
+ this.updateConfiguringMessage_(false);
+ setIsVisible(
+ this.getChildElement('.configuring-failed-text'), true);
+ }
+ },
+
+ /**
* Initializes the element with destination's info.
* @private
*/
@@ -171,6 +216,13 @@ cr.define('print_preview', function() {
this.getChildElement('.register-promo'),
this.destination_.connectionStatus ==
print_preview.Destination.ConnectionStatus.UNREGISTERED);
+
+ if (cr.isChromeOS) {
+ // Reset the configuring messages for CUPS printers.
+ this.updateConfiguringMessage_(false);
+ setIsVisible(
+ this.getChildElement('.configuring-failed-text'), false);
+ }
},
/**
@@ -195,11 +247,43 @@ cr.define('print_preview', function() {
},
/**
- * Called when the destination item is activated. Dispatches a SELECT event
- * on the given event target.
+ * Shows/Hides the configuring in progress message and starts/stops its
+ * animation accordingly.
+ * @param {bool} show If the message and animation should be shown.
+ * @private
+ */
+ updateConfiguringMessage_: function(show) {
+ setIsVisible(
+ this.getChildElement('.configuring-in-progress-text'), show);
+ this.getChildElement('.configuring-text-jumping-dots')
+ .classList.toggle('jumping-dots', show);
+ },
+
+ /**
+ * Called when the destination item is activated. Check if the printer needs
+ * to be set up first before activation.
* @private
*/
onActivate_: function() {
+ if (!cr.isChromeOS) {
+ this.onDestinationActivated_();
+ return;
+ }
+
+ // Check if the printer needs configuration before using. The user is only
+ // allowed to set up one printer at one time.
+ var configureEvent = new CustomEvent(
+ DestinationListItem.EventType.CONFIGURE_REQUEST,
+ {detail: {destination: this.destination_}});
+ this.eventTarget_.dispatchEvent(configureEvent);
+ },
+
+ /**
+ * Called when the destination has been resolved successfully and needs to
+ * be activated. Dispatches a SELECT event on the given event target.
+ * @private
+ */
+ onDestinationActivated_: function() {
if (this.destination_.id ==
print_preview.Destination.GooglePromotedId.FEDEX &&
!this.destination_.isTosAccepted) {
diff --git a/chromium/chrome/browser/resources/print_preview/search/destination_search.css b/chromium/chrome/browser/resources/print_preview/search/destination_search.css
index 903d86f4f30..2ff197aa7e4 100644
--- a/chromium/chrome/browser/resources/print_preview/search/destination_search.css
+++ b/chromium/chrome/browser/resources/print_preview/search/destination_search.css
@@ -17,22 +17,14 @@
}
#destination-search .user-info {
+ -webkit-padding-end: 18px;
+ -webkit-padding-start: 18px;
display: flex;
- position: absolute;
- right: 40px;
- text-align: right;
- top: 14px;
- width: 350px;
-}
-
-[dir='rtl'] #destination-search .user-info {
- left: 40px;
- right: auto;
+ padding-bottom: 14px;
}
#destination-search .account-select-label {
-webkit-user-select: none;
- flex: 1;
height: 2em;
line-height: 2em;
overflow: hidden;
@@ -41,8 +33,8 @@
}
#destination-search .account-select {
- flex: 1;
- margin-left: 8px;
+ -webkit-margin-start: 18px;
+ width: auto;
}
#destination-search > .page > .close-button {
diff --git a/chromium/chrome/browser/resources/print_preview/search/destination_search.js b/chromium/chrome/browser/resources/print_preview/search/destination_search.js
index cc59b37ebf0..33915459b15 100644
--- a/chromium/chrome/browser/resources/print_preview/search/destination_search.js
+++ b/chromium/chrome/browser/resources/print_preview/search/destination_search.js
@@ -74,6 +74,12 @@ cr.define('print_preview', function() {
this.provisionalDestinationResolver_ = null;
/**
+ * The destination that is currently in configuration.
+ * @private {?print_preview.Destination}
+ */
+ this.destinationInConfiguring_ = null;
+
+ /**
* Search box used to search through the destination lists.
* @type {!print_preview.SearchBox}
* @private
@@ -223,6 +229,10 @@ cr.define('print_preview', function() {
this.onSearch_.bind(this));
this.tracker.add(
this,
+ print_preview.DestinationListItem.EventType.CONFIGURE_REQUEST,
+ this.onDestinationConfigureRequest_.bind(this));
+ this.tracker.add(
+ this,
print_preview.DestinationListItem.EventType.SELECT,
this.onDestinationSelect_.bind(this));
this.tracker.add(
@@ -558,21 +568,82 @@ cr.define('print_preview', function() {
/**
* Called when a destination search should be executed. Filters the
* destination lists with the given query.
- * @param {Event} evt Contains the search query.
+ * @param {!Event} event Contains the search query.
* @private
*/
- onSearch_: function(evt) {
- this.filterLists_(evt.queryRegExp);
+ onSearch_: function(event) {
+ this.filterLists_(event.queryRegExp);
+ },
+
+ /**
+ * Handler for {@code print_preview.DestinationListItem.EventType.
+ * CONFIGURE_REQUEST} event, which is called to check a destination list
+ * item needs to be setup on Chrome OS before being selected. Note we do not
+ * allow configuring more than one destination at the same time.
+ * @param {!CustomEvent} event Contains the destination needs to be setup.
+ * @private
+ */
+ onDestinationConfigureRequest_: function(event) {
+ var destination = event.detail.destination;
+ // Cloud Print Device printers are stored in the local list
+ // crbug.com/713831.
+ // TODO(crbug.com/416701): Upon resolution, update this.
+ var destinationItem =
+ (destination.isLocal ||
+ destination.origin == print_preview.Destination.Origin.DEVICE) ?
+ this.localList_.getDestinationItem(destination.id) :
+ this.cloudList_.getDestinationItem(destination.id);
+ assert(destinationItem != null,
+ 'User does not select a valid destination item.');
+
+ // Another printer setup is in process or the printer doesn't need to be
+ // set up. Reject the setup request directly.
+ if (this.destinationInConfiguring_ != null ||
+ destination.origin != print_preview.Destination.Origin.CROS ||
+ destination.capabilities != null) {
+ destinationItem.onConfigureRequestRejected(
+ this.destinationInConfiguring_ != null);
+ } else {
+ destinationItem.onConfigureRequestAccepted();
+ this.handleConfigureDestination_(destination);
+ }
+ },
+
+ /**
+ * Called When a destination needs to be setup.
+ * @param {!print_preview.Destination} destination The destination needs to
+ * be setup.
+ * @private
+ */
+ handleConfigureDestination_: function(destination) {
+ assert(destination.origin == print_preview.Destination.Origin.CROS,
+ 'Only local printer on Chrome OS requires setup.');
+ this.destinationInConfiguring_ = destination;
+ this.destinationStore_.resolveCrosDestination(destination).then(
+ /**
+ * @param {!print_preview.PrinterSetupResponse} response.
+ */
+ function(response) {
+ this.destinationInConfiguring_ = null;
+ this.localList_.getDestinationItem(destination.id)
+ .onConfigureResolved(response);
+ }.bind(this),
+ function() {
+ this.destinationInConfiguring_ = null;
+ this.localList_.getDestinationItem(destination.id)
+ .onConfigureResolved({printerId: destination.id,
+ success: false});
+ }.bind(this));
},
/**
* Handler for {@code print_preview.DestinationListItem.EventType.SELECT}
- * event, which is called when a destinationi list item is selected.
- * @param {Event} evt Contains the selected destination.
+ * event, which is called when a destination list item is selected.
+ * @param {Event} event Contains the selected destination.
* @private
*/
- onDestinationSelect_: function(evt) {
- this.handleOnDestinationSelect_(evt.destination);
+ onDestinationSelect_: function(event) {
+ this.handleOnDestinationSelect_(event.destination);
},
/**
@@ -583,35 +654,6 @@ cr.define('print_preview', function() {
* @private
*/
handleOnDestinationSelect_: function(destination) {
- if (destination.origin == print_preview.Destination.Origin.CROS &&
- !destination.capabilities) {
- // local printers on CrOS require setup.
- assert(!this.printerConfigurer_);
- this.printerConfigurer_ = new print_preview.CrosDestinationResolver(
- this.destinationStore_, destination);
- this.addChild(this.printerConfigurer_);
- this.printerConfigurer_.run(this.getElement()).
- then(
- /**
- * @param {!print_preview.PrinterSetupResponse} result
- * An object containing the printerId and capabilities.
- */
- function(result) {
- assert(result.printerId == destination.id);
- destination.capabilities = result.capabilities;
- this.handleOnDestinationSelect_(destination);
- }.bind(this),
- function() {
- console.warn(
- 'Failed to setup destination: ' + destination.id);
- }).
- then(function() {
- this.removeChild(this.printerConfigurer_);
- this.printerConfigurer_ = null;
- }.bind(this));
- return;
- }
-
if (destination.isProvisional) {
assert(!this.provisionalDestinationResolver_,
'Provisional destination resolver already exists.');
diff --git a/chromium/chrome/browser/resources/print_preview/settings/page_settings.css b/chromium/chrome/browser/resources/print_preview/settings/page_settings.css
index 7e3defdae64..e239f939ae3 100644
--- a/chromium/chrome/browser/resources/print_preview/settings/page_settings.css
+++ b/chromium/chrome/browser/resources/print_preview/settings/page_settings.css
@@ -16,12 +16,12 @@
#page-settings .page-settings-custom-input-wrapper {
-webkit-box-flex: 1;
-webkit-margin-start: 0.6em;
- height: 28px;
+ min-height: 2em;
position: relative;
}
#page-settings .page-settings-custom-input {
- height: 28px;
+ min-height: 2em;
position: absolute;
width: 100%;
}
@@ -33,4 +33,4 @@
#page-settings .radio {
margin-bottom: 10px;
-} \ No newline at end of file
+}
diff --git a/chromium/chrome/browser/resources/quota_internals_resources.grd b/chromium/chrome/browser/resources/quota_internals_resources.grd
index d077fc8f514..f75b4f380de 100644
--- a/chromium/chrome/browser/resources/quota_internals_resources.grd
+++ b/chromium/chrome/browser/resources/quota_internals_resources.grd
@@ -8,9 +8,9 @@
</outputs>
<release seq="1">
<includes>
- <include name="IDR_QUOTA_INTERNALS_MAIN_HTML" file="quota_internals/main.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_QUOTA_INTERNALS_EVENT_HANDLER_JS" file="quota_internals/event_handler.js" type="BINDATA" />
- <include name="IDR_QUOTA_INTERNALS_MESSAGE_DISPATCHER_JS" file="quota_internals/message_dispatcher.js" type="BINDATA" />
+ <include name="IDR_QUOTA_INTERNALS_MAIN_HTML" file="quota_internals/main.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip"/>
+ <include name="IDR_QUOTA_INTERNALS_EVENT_HANDLER_JS" file="quota_internals/event_handler.js" type="BINDATA" compress="gzip"/>
+ <include name="IDR_QUOTA_INTERNALS_MESSAGE_DISPATCHER_JS" file="quota_internals/message_dispatcher.js" type="BINDATA" compress="gzip"/>
</includes>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
index 29790bdbd2e..6641e0deac9 100644
--- a/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
+++ b/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -8,7 +8,7 @@
##
## Top level settings
##
-version_id: 8
+version_id: 9
sampled_ping_probability: 0.01
default_file_type {
uma_value: 18
@@ -2649,6 +2649,11 @@ file_types {
danger_level: ALLOW_ON_USER_GESTURE
auto_open_hint: DISALLOW_AUTO_OPEN
}
+ platform_settings {
+ platform: PLATFORM_CHROME_OS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
}
file_types {
extension: "apk"
@@ -2660,6 +2665,11 @@ file_types {
auto_open_hint: DISALLOW_AUTO_OPEN
}
platform_settings {
+ platform: PLATFORM_CHROME_OS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
platform: PLATFORM_LINUX
danger_level: ALLOW_ON_USER_GESTURE
auto_open_hint: DISALLOW_AUTO_OPEN
diff --git a/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.html b/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.html
new file mode 100644
index 00000000000..308e08c75d7
--- /dev/null
+++ b/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Sandbox Status</title>
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+ <style type="text/css">
+ #sandbox-status {
+ border: 1px solid gray;
+ }
+ #sandbox-status td {
+ border: 1px solid gray;
+ padding: 3px;
+ }
+ #evaluation {
+ font-weight: bold;
+ }
+ .good {
+ background-color: rgb(143, 218, 146);
+ }
+ .bad {
+ background-color: rgb(249, 156, 149);
+ }
+ .info {
+ background-color: rgb(169, 217, 239);
+ }
+ </style>
+ <script src="chrome://resources/js/cr.js"></script>
+ <if expr="not is_android">
+ <script src="chrome://resources/js/load_time_data.js"></script>
+ <script src="chrome://sandbox/strings.js"></script>
+ </if>
+ <script src="chrome://resources/js/util.js"></script>
+ <script src="sandbox_internals.js"></script>
+ </head>
+ <body>
+ <h1>Sandbox Status</h1>
+
+ <table id="sandbox-status">
+ </table>
+
+ <p id="evaluation"></p>
+ </body>
+</html>
diff --git a/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.js b/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.js
new file mode 100644
index 00000000000..02479b54f3b
--- /dev/null
+++ b/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals.js
@@ -0,0 +1,139 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+ let GOOD = 'good';
+ let BAD = 'bad';
+ let INFO = 'info';
+
+ /**
+ * Adds a row to the sandbox status table.
+ * @param {string} name The name of the status item.
+ * @param {string} value The status of the item.
+ * @param {string?} cssClass A CSS class to apply to the row.
+ * @return {Element} The newly added TR.
+ */
+ function addStatusRow(name, value, cssClass) {
+ let row = cr.doc.createElement('tr');
+
+ let nameCol = row.appendChild(cr.doc.createElement('td'));
+ let valueCol = row.appendChild(cr.doc.createElement('td'));
+
+ nameCol.textContent = name;
+ valueCol.textContent = value;
+
+ if (cssClass != null) {
+ nameCol.classList.add(cssClass);
+ valueCol.classList.add(cssClass);
+ }
+
+ $('sandbox-status').appendChild(row);
+ return row;
+ }
+
+ /**
+ * Adds a status row that reports either Yes or No.
+ * @param {string} name The name of the status item.
+ * @param {boolean} result The status (good/bad) result.
+ * @return {Element} The newly added TR.
+ */
+ function addGoodBadRow(name, result) {
+ return addStatusRow(name, result ? 'Yes' : 'No', result ? GOOD : BAD);
+ }
+
+ /**
+ * Reports the overall sandbox status evaluation message.
+ * @param {boolean}
+ */
+ function setEvaluation(result) {
+ let message = result ? 'You are adequately sandboxed.'
+ : 'You are NOT adequately sandboxed.';
+ $('evaluation').innerText = message;
+ }
+
+ /**
+ * Main page handler for Android.
+ */
+ function androidHandler() {
+ chrome.getAndroidSandboxStatus((status) => {
+ var isIsolated = false;
+ var isTsync = false;
+ var isChromeSeccomp = false;
+
+ addStatusRow('PID', status.pid, INFO);
+ addStatusRow('UID', status.uid, INFO);
+ isIsolated = status.secontext.indexOf(':isolated_app:') != -1;
+ addStatusRow('SELinux Context', status.secontext,
+ isIsolated ? GOOD : BAD);
+
+ let procStatus = status.procStatus.split('\n');
+ for (let line of procStatus) {
+ if (line.startsWith('Seccomp')) {
+ var value = line.split(':')[1].trim();
+ var cssClass = BAD;
+ if (value == '2') {
+ value = 'Yes - TSYNC (' + line + ')';
+ cssClass = GOOD;
+ isTsync = true;
+ } else if (value == '1') {
+ value = 'Yes (' + line + ')';
+ } else {
+ value = line;
+ }
+ addStatusRow('Seccomp-BPF Enabled (Kernel)', value, cssClass);
+ break;
+ }
+ }
+
+ var seccompStatus = 'Unknown';
+ switch (status.seccompStatus) {
+ case 0:
+ seccompStatus = 'Not Supported';
+ break;
+ case 1:
+ seccompStatus = 'Run-time Detection Failed';
+ break;
+ case 2:
+ seccompStatus = 'Disabled by Field Trial';
+ break;
+ case 3:
+ seccompStatus = 'Enabled by Field Trial (not started)';
+ break;
+ case 4:
+ seccompStatus = 'Sandbox Started';
+ isChromeSeccomp = true;
+ break;
+ }
+ addStatusRow('Seccomp-BPF Enabled (Chrome)', seccompStatus,
+ status.seccompStatus == 4 ? GOOD : BAD);
+
+ addStatusRow('Android Build ID', status.androidBuildId, INFO);
+
+ setEvaluation(isIsolated && isTsync && isChromeSeccomp);
+ });
+ }
+
+ /**
+ * Main page handler for desktop Linux.
+ */
+ function linuxHandler() {
+ addGoodBadRow('SUID Sandbox', loadTimeData.getBoolean('suid'));
+ addGoodBadRow('Namespace Sandbox', loadTimeData.getBoolean('userNs'));
+ addGoodBadRow('PID namespaces', loadTimeData.getBoolean('pidNs'));
+ addGoodBadRow('Network namespaces', loadTimeData.getBoolean('netNs'));
+ addGoodBadRow('Seccomp-BPF sandbox', loadTimeData.getBoolean('seccompBpf'));
+ addGoodBadRow('Seccomp-BPF sandbox supports TSYNC',
+ loadTimeData.getBoolean('seccompTsync'));
+ addGoodBadRow('Yama LSM Enforcing', loadTimeData.getBoolean('yama'));
+ setEvaluation(loadTimeData.getBoolean('sandboxGood'));
+ }
+
+ document.addEventListener('DOMContentLoaded', () => {
+ if (cr.isAndroid) {
+ androidHandler();
+ } else {
+ linuxHandler();
+ }
+ });
+})();
diff --git a/chromium/chrome/browser/resources/settings/BUILD.gn b/chromium/chrome/browser/resources/settings/BUILD.gn
index 8a905acd624..30c997005ad 100644
--- a/chromium/chrome/browser/resources/settings/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/BUILD.gn
@@ -2,40 +2,71 @@ import("../vulcanize.gni")
import("//tools/grit/grit_rule.gni")
import("//chrome/common/features.gni")
-vulcanized_unbuilt = "vulcanized.unbuilt.html"
+app_unbuilt = "vulcanized.unbuilt.html"
+lazy_load_unbuilt = "lazy_load.vulcanized.unbuilt.html"
+settings_pak_file = "settings_resources.pak"
+unpak_folder = "settings_resources.unpak"
-vulcanize("vulcanize") {
+vulcanize("vulcanize_app") {
host = "md-settings"
html_in_file = "settings.html"
- html_out_file = vulcanized_unbuilt
+ html_out_file = app_unbuilt
insert_in_head = "<base href=\"chrome://\$i18n{hostname}\">"
- input = rebase_path(root_gen_dir, root_build_dir) +
- "/chrome/browser/resources/settings/settings_resources.pak"
+ input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
js_out_file = "crisper.js"
deps = [
+ ":unpak",
+ ]
+}
+
+vulcanize("vulcanize_lazy_load") {
+ host = "md-settings"
+ html_in_file = "lazy_load.html"
+ html_out_file = lazy_load_unbuilt
+ insert_in_head = "<base href=\"chrome://\$i18n{hostname}\">"
+ input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
+ js_out_file = "lazy_load.crisper.js"
+
+ excludes = [ "/settings.html" ]
+
+ deps = [
+ ":unpak",
+ ]
+}
+
+unpak("unpak") {
+ pak_file = settings_pak_file
+ out_folder = unpak_folder
+
+ deps = [
":flattened_resources",
]
}
polymer_css_build("build") {
- input_files = [ vulcanized_unbuilt ]
- output_files = [ "vulcanized.html" ]
+ input_files = [
+ app_unbuilt,
+ lazy_load_unbuilt,
+ ]
+ output_files = [
+ "vulcanized.html",
+ "lazy_load.vulcanized.html",
+ ]
deps = [
- ":vulcanize",
+ ":vulcanize_app",
+ ":vulcanize_lazy_load",
]
}
grit("flattened_resources") {
source = "settings_resources.grd"
-
- # TODO(thestig): use_qualified_include = true
defines = chrome_grit_defines
outputs = [
"grit/settings_resources.h",
"grit/settings_resources_map.cc",
"grit/settings_resources_map.h",
- "settings_resources.pak",
+ settings_pak_file,
]
output_dir = "$root_gen_dir/chrome/browser/resources/settings"
}
diff --git a/chromium/chrome/browser/resources/settings/OWNERS b/chromium/chrome/browser/resources/settings/OWNERS
index 7786353858f..a34bf8b5f11 100644
--- a/chromium/chrome/browser/resources/settings/OWNERS
+++ b/chromium/chrome/browser/resources/settings/OWNERS
@@ -5,3 +5,5 @@ hcarmona@chromium.org
michaelpg@chromium.org
stevenjb@chromium.org
tommycli@chromium.org
+
+# COMPONENT: UI>Settings
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html
index f83afb0c5ba..9a26583b53a 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html
+++ b/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -5,8 +5,8 @@
<if expr="chromeos">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="manage_a11y_page.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../settings_page/settings_animated_pages.html">
<link rel="import" href="../settings_page/settings_subpage.html">
</if>
@@ -16,31 +16,26 @@
<style include="settings-shared"></style>
<if expr="chromeos">
<settings-animated-pages id="pages" current-route="{{currentRoute}}"
- section="a11y">
+ section="a11y" focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
- <div class="settings-box first">
- <div id="optionsInMenuLabel" class="start">
- $i18n{optionsInMenuLabel}
- </div>
- <paper-toggle-button id="optionsInMenuToggle"
- checked="{{prefs.settings.a11y.enable_menu.value}}"
- aria-labelledby="optionsInMenuLabel">
- </paper-toggle-button>
+ <div class="settings-box">
+ <settings-toggle-button id="optionsInMenuToggle" class="start"
+ label="$i18n{optionsInMenuLabel}"
+ pref="{{prefs.settings.a11y.enable_menu}}">
+ </settings-toggle-button>
</div>
- <template is="dom-if" if="[[!isGuest_]]">
- <div id="subpage-trigger" class="settings-box two-line"
- on-tap="onManageAccessibilityFeaturesTap_" actionable>
- <div class="start">
- $i18n{manageAccessibilityFeatures}
- <div class="secondary" id="themesSecondary">
- $i18n{moreFeaturesLinkDescription}
- </div>
+ <div id="subpage-trigger" class="settings-box two-line"
+ on-tap="onManageAccessibilityFeaturesTap_" actionable>
+ <div class="start">
+ $i18n{manageAccessibilityFeatures}
+ <div class="secondary" id="themesSecondary">
+ $i18n{moreFeaturesLinkDescription}
</div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{manageAccessibilityFeatures}"
- aria-describedby="themesSecondary"></button>
</div>
- </template>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{manageAccessibilityFeatures}"
+ aria-describedby="themesSecondary"></button>
+ </div>
</neon-animatable>
<template is="dom-if" route-path="/manageAccessibility">
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.js b/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.js
index 29c0b6c226f..0bcbcbcfb31 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.js
+++ b/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.js
@@ -28,10 +28,18 @@ Polymer({
notify: true,
},
- /** @private */
- isGuest_: {
- type: Boolean,
- value: function() { return loadTimeData.getBoolean('isGuest'); }
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+// <if expr="chromeos">
+ map.set(
+ settings.Route.MANAGE_ACCESSIBILITY.path,
+ '#subpage-trigger .subpage-arrow');
+// </if>
+ return map;
+ },
},
},
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
index d2fef1036ac..bcb42c73623 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
+++ b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -1,5 +1,8 @@
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="../controls/settings_slider.html">
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../route.html">
@@ -17,6 +20,10 @@
-webkit-margin-start: 16px;
}
+ .sub-item > .start {
+ -webkit-margin-start: var(--settings-indent-width);
+ }
+
h2 ~ .settings-box {
-webkit-margin-end: var(--settings-box-row-padding);
-webkit-margin-start: var(--settings-box-row-indent);
@@ -38,18 +45,25 @@
<settings-toggle-button class="start"
pref="{{prefs.settings.accessibility}}"
label="$i18n{chromeVoxLabel}">
- <button class="more-actions icon-external" is="paper-icon-button-light"
+ <paper-icon-button icon="cr:settings_icon"
+ class="more-actions"
on-tap="onChromeVoxSettingsTap_"
hidden="[[!prefs.settings.accessibility.value]]"
- aria-label="$i18n{chromeVoxLabel}"></button>
+ aria-label="$i18n{chromeVoxOptionsLabel}"></paper-icon-button>
</settings-toggle-button>
</div>
<template is="dom-if" if="[[showExperimentalFeatures_]]">
- <div class="settings-box block">
+ <div class="settings-box block" actionable>
<settings-toggle-button
pref="{{prefs.settings.a11y.select_to_speak}}"
label="$i18n{selectToSpeakTitle}"
sub-label="$i18n{selectToSpeakDescription}">
+ <paper-icon-button icon="cr:settings_icon"
+ class="more-actions"
+ on-tap="onSelectToSpeakSettingsTap_"
+ hidden="[[!prefs.settings.a11y.select_to_speak.value]]"
+ aria-label="$i18n{selectToSpeakOptionsLabel}">
+ </paper-icon-button>
</settings-toggle-button>
</div>
</template>
@@ -106,13 +120,21 @@
pref="{{prefs.settings.a11y.caret_highlight}}"
label="$i18n{caretHighlightLabel}">
</settings-toggle-button>
- <template is="dom-if" if="[[showExperimentalFeatures_]]">
+ </div>
+ <template is="dom-if" if="[[showExperimentalFeatures_]]">
+ <div class="settings-box block" actionable>
<settings-toggle-button
pref="{{prefs.settings.a11y.switch_access}}"
label="$i18n{switchAccessLabel}">
+ <paper-icon-button icon="cr:settings_icon"
+ class="more-actions"
+ on-tap="onSwitchAccessSettingsTap_"
+ hidden="[[!prefs.settings.a11y.switch_access.value]]"
+ aria-label="$i18n{selectToSpeakOptionsLabel}">
+ </paper-icon-button>
</settings-toggle-button>
- </template>
- </div>
+ </div>
+ </template>
<div class="settings-box two-line" on-tap="onKeyboardTap_" actionable>
<div class="start">
$i18n{keyboardSettingsTitle}
@@ -133,7 +155,7 @@
</settings-toggle-button>
<div class="list-item settings-toggle-button-spacer">
<div>$i18n{delayBeforeClickLabel}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{delayBeforeClickLabel}"
pref="{{prefs.settings.a11y.autoclick_delay_ms}}"
menu-options="[[autoClickDelayOptions_]]"
disabled="[[!prefs.settings.a11y.autoclick.value]]">
@@ -148,12 +170,14 @@
label="$i18n{largeMouseCursorLabel}">
</settings-toggle-button>
<template is="dom-if" if="[[enableAdjustableLargeCursor_]]">
- <div class="list-item">
- <div>$i18n{largeMouseCursorSizeLabel}</div>
- <cr-slider
- disabled="[[!prefs.settings.a11y.large_cursor_enabled.value]]"
- value="{{prefs.settings.a11y.large_cursor_dip_size.value}}"
- min="25" max="64"></cr-slider>
+ <div class="list-item sub-item"
+ hidden$="[[!prefs.settings.a11y.large_cursor_enabled.value]]">
+ <div class="start">$i18n{largeMouseCursorSizeLabel}</div>
+ <settings-slider
+ pref="{{prefs.settings.a11y.large_cursor_dip_size}}"
+ min="25" max="64" label-min="$i18n{largeMouseCursorSizeSmallLabel}"
+ label-max="$i18n{largeMouseCursorSizeLargeLabel}">
+ </settings-slider>
</div>
</template>
<settings-toggle-button
@@ -181,17 +205,19 @@
</settings-toggle-button>
</div>
- <div class="settings-box two-line" on-tap="onMoreFeaturesTap_" actionable>
- <div class="start">
- $i18n{additionalFeaturesTitle}
- <div class="secondary" id="moreFeaturesSecondary">
- $i18n{a11yWebStore}
+ <template is="dom-if" if="[[!isGuest_]]">
+ <div class="settings-box two-line" on-tap="onMoreFeaturesTap_" actionable>
+ <div class="start">
+ $i18n{additionalFeaturesTitle}
+ <div class="secondary" id="moreFeaturesSecondary">
+ $i18n{a11yWebStore}
+ </div>
</div>
+ <button class="icon-external" is="paper-icon-button-light"
+ aria-label="$i18n{additionalFeaturesTitle}"
+ aria-describedby="moreFeaturesSecondary"></button>
</div>
- <button class="icon-external" is="paper-icon-button-light"
- aria-label="$i18n{additionalFeaturesTitle}"
- aria-describedby="moreFeaturesSecondary"></button>
- </div>
+ </template>
</template>
<script src="manage_a11y_page.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js
index 354082bad3f..eac4841b8b6 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js
+++ b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js
@@ -62,6 +62,12 @@ Polymer({
return loadTimeData.getBoolean('enableAdjustableLargeCursor');
},
},
+
+ /** @private */
+ isGuest_: {
+ type: Boolean,
+ value: function() { return loadTimeData.getBoolean('isGuest'); }
+ },
},
/** @private */
@@ -70,6 +76,16 @@ Polymer({
},
/** @private */
+ onSelectToSpeakSettingsTap_: function() {
+ chrome.send('showSelectToSpeakSettings');
+ },
+
+ /** @private */
+ onSwitchAccessSettingsTap_: function() {
+ chrome.send('showSwitchAccessSettings');
+ },
+
+ /** @private */
onDisplayTap_: function() {
settings.navigateTo(
settings.Route.DISPLAY,
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.html b/chromium/chrome/browser/resources/settings/about_page/about_page.html
index 7eda97ec7ab..d24e89c279b 100644
--- a/chromium/chrome/browser/resources/settings/about_page/about_page.html
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.html
@@ -85,7 +85,8 @@
</style>
<div>
<settings-section page-title="$i18n{aboutPageTitle}" section="about">
- <settings-animated-pages id="pages" section="about">
+ <settings-animated-pages id="pages" section="about"
+ focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<div class="settings-box two-line">
<img id="product-logo" on-tap="onProductLogoTap_"
@@ -182,7 +183,8 @@
<div class="settings-box" on-tap="onDetailedBuildInfoTap_"
actionable>
<div class="start">$i18n{aboutDetailedBuildInfo}</div>
- <button class="subpage-arrow" is="paper-icon-button-light"
+ <button id="detailed-build-info-trigger" class="subpage-arrow"
+ is="paper-icon-button-light"
aria-label="$i18n{aboutDetailedBuildInfo}">
</button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.js b/chromium/chrome/browser/resources/settings/about_page/about_page.js
index cb26f366b61..36f8b61d208 100644
--- a/chromium/chrome/browser/resources/settings/about_page/about_page.js
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.js
@@ -73,6 +73,18 @@ Polymer({
type: Boolean,
computed: 'computeShowCheckUpdates_(currentUpdateStatusEvent_)',
},
+
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+ map.set(
+ settings.Route.DETAILED_BUILD_INFO.path,
+ '#detailed-build-info-trigger');
+ return map;
+ },
+ }
// </if>
},
diff --git a/chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp
index b477f45a24d..c7824f0ea8c 100644
--- a/chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp
@@ -31,6 +31,7 @@
'target_name': 'detailed_build_info',
'dependencies': [
'about_page_browser_proxy',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html
index 135f81371db..d9ee2a067eb 100644
--- a/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html
+++ b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html
@@ -3,9 +3,8 @@
<link rel="import" href="channel_switcher_dialog.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../settings_shared_css.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<dom-module id="settings-detailed-build-info">
@@ -15,8 +14,8 @@
-webkit-user-select: text;
}
- iron-icon {
- padding: 8px;
+ cr-policy-indicator {
+ -webkit-margin-start: 8px;
}
/* The command line string can contain very long substrings that
@@ -45,10 +44,19 @@
disabled="[[!canChangeChannel_]]">
$i18n{aboutChangeChannel}
</paper-button>
- <iron-icon icon="cr20:domain" hidden="[[canChangeChannel_]]"</iron-icon>
+ <template is="dom-if" if="[[!canChangeChannel_]]">
+ <cr-policy-indicator
+ indicator-source-name="[[getChangeChannelIndicatorSourceName_(
+ canChangeChannel_)]]"
+ indicator-type="[[getChangeChannelIndicatorType_(
+ canChangeChannel_)]]">
+ </cr-policy-indicator>
+ </template>
</div>
<template is="dom-if" if="[[showChannelSwitcherDialog_]]" restamp>
- <settings-channel-switcher-dialog></settings-channel-switcher-dialog>
+ <settings-channel-switcher-dialog
+ on-close="onChannelSwitcherDialogClosed_">
+ </settings-channel-switcher-dialog>
</template>
</div>
<div class="settings-box two-line single-column"
diff --git a/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.js b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.js
index dfd68b2c07d..33a90b780c4 100644
--- a/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.js
+++ b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.js
@@ -60,22 +60,41 @@ Polymer({
},
/**
+ * @param {boolean} canChangeChannel
+ * @return {string}
+ * @private
+ */
+ getChangeChannelIndicatorSourceName_: function(canChangeChannel) {
+ return loadTimeData.getBoolean('aboutEnterpriseManaged') ? '' :
+ loadTimeData.getString('ownerEmail');
+ },
+
+ /**
+ * @param {boolean} canChangeChannel
+ * @return {CrPolicyIndicatorType}
+ * @private
+ */
+ getChangeChannelIndicatorType_: function(canChangeChannel) {
+ if (canChangeChannel)
+ return CrPolicyIndicatorType.NONE;
+ return loadTimeData.getBoolean('aboutEnterpriseManaged') ?
+ CrPolicyIndicatorType.DEVICE_POLICY :
+ CrPolicyIndicatorType.OWNER;
+ },
+
+ /**
* @param {!Event} e
* @private
*/
onChangeChannelTap_: function(e) {
e.preventDefault();
this.showChannelSwitcherDialog_ = true;
- // Async to wait for dialog to appear in the DOM.
- this.async(function() {
- var dialog = this.$$('settings-channel-switcher-dialog');
- // Register listener to detect when the dialog is closed. Flip the boolean
- // once closed to force a restamp next time it is shown such that the
- // previous dialog's contents are cleared.
- dialog.addEventListener('close', function() {
- this.showChannelSwitcherDialog_ = false;
- this.updateChannelInfo_();
- }.bind(this));
- }.bind(this));
+ },
+
+ /** @private */
+ onChannelSwitcherDialogClosed_: function() {
+ this.showChannelSwitcherDialog_ = false;
+ this.$$('paper-button').focus();
+ this.updateChannelInfo_();
},
});
diff --git a/chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.html b/chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.html
new file mode 100644
index 00000000000..38026cce414
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.html
@@ -0,0 +1,27 @@
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="about_page_browser_proxy.html">
+<link rel="import" href="../settings_shared_css.html">
+
+<dom-module id="settings-update-warning-dialog">
+ <template>
+ <style include="settings-shared"></style>
+ <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
+ <div class="title">$i18n{aboutUpdateWarningTitle}</div>
+ <div class="body">
+ <div id="update-warning-message"></div>
+ </div>
+ <div class="button-container">
+ <paper-button id="cancel" class="cancel-button"
+ on-tap="onCancelTap_">$i18n{cancel}</paper-button>
+ <paper-button id="continue" class="action-button"
+ on-tap="onContinueTap_">
+ $i18n{aboutUpdateWarningContinue}
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="update_warning_dialog.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.js b/chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.js
new file mode 100644
index 00000000000..1060fa4f02b
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/update_warning_dialog.js
@@ -0,0 +1,45 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview 'settings-update-warning-dialog' is a component warning the
+ * user about update over mobile data. By clicking 'Continue', the user
+ * agrees to download update using mobile data.
+ */
+Polymer({
+ is: 'settings-update-warning-dialog',
+
+ behaviors: [I18nBehavior],
+
+ /** @override */
+ ready: function() {
+ this.browserProxy_ = settings.AboutPageBrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ this.$.dialog.showModal();
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ // TODO(weidongg): implement the real behaviors here.
+ this.$.dialog.close();
+ },
+
+ /** @private */
+ onContinueTap_: function() {
+ // TODO(weidongg): implement the real behaviors here.
+ this.$.dialog.close();
+ },
+
+ /**
+ * @param {string} updateSizeMb Size of the update in megabytes.
+ * @private
+ */
+ setUpdateWarningMessage: function(updateSizeMb) {
+ this.$$("#update-warning-message").innerHTML =
+ this.i18n("aboutUpdateWarningMessage", updateSizeMb);
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_browser_proxy.js b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_browser_proxy.js
index 1a2e0be7b98..0c5c3d56a44 100644
--- a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_browser_proxy.js
@@ -8,7 +8,13 @@
*/
/**
- * @typedef {{appReady: boolean}}
+ * Type definition of AndroidAppsInfo entry. |playStoreEnabled| indicates that
+ * Play Store is enabled. |settingsAppAvailable| indicates that Android settings
+ * app is registered in the system.
+ * @typedef {{
+ * playStoreEnabled: boolean,
+ * settingsAppAvailable: boolean,
+ * }}
* @see chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
*/
var AndroidAppsInfo;
diff --git a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.html b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
index be48d94033d..a655bba6f38 100644
--- a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
+++ b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
@@ -1,65 +1,64 @@
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="android_apps_browser_proxy.html">
-<link rel="import" href="../controls/settings_toggle_button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../prefs/prefs_behavior.html">
+<link rel="import" href="../settings_page/settings_animated_pages.html">
+<link rel="import" href="../settings_page/settings_subpage.html">
<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="android_apps_browser_proxy.html">
+<link rel="import" href="android_apps_subpage.html">
<dom-module id="settings-android-apps-page">
<template>
- <style include="settings-shared">
- a {
- -webkit-margin-start: 4px;
- height: var(--checkbox-size);
- }
-
- .indented {
- -webkit-margin-start: var(--settings-indent-width);
- }
- </style>
+ <style include="settings-shared"></style>
- <div class="settings-box first">
- <settings-toggle-button id="enabled" class="start"
- pref="{{prefs.arc.enabled}}"
- label="$i18n{androidAppsEnabled}"
- on-change="onArcEnabledChange_"
- no-set-pref>
- <a href="$i18nRaw{androidAppsLearnMoreUrl}" target="_blank"
- class="more-actions" on-tap="stopPropagation_">
- $i18n{androidAppsLearnMore}
- </a>
- </settings-toggle-button>
- </div>
+ <settings-animated-pages id="pages" section="androidApps"
+ focus-config="[[focusConfig_]]">
+ <neon-animatable route-path="default">
+ <div id="android-apps" class="settings-box two-line first" actionable
+ on-tap="onSubpageTap_">
+ <div class="start">
+ $i18n{androidAppsPageLabel}
+ <div class="secondary" id="secondaryText"
+ inner-h-t-m-l="[[i18n('androidAppsSubtext')]]">
+ </div>
+ </div>
+ <cr-policy-pref-indicator pref="[[prefs.arc.enabled]]"
+ icon-aria-label="$i18n{androidAppsPageTitle}">
+ </cr-policy-pref-indicator>
+ <template is="dom-if" if="[[androidAppsInfo_.playStoreEnabled]]">
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{androidAppsPageTitle}"
+ aria-describedby="secondaryText">
+ </button>
+ </template>
+ <template is="dom-if" if="[[!androidAppsInfo_.playStoreEnabled]]">
+ <div class="separator"></div>
+ <paper-button id="enable" class="secondary-button"
+ on-tap="onEnableTap_"
+ aria-label="$i18n{androidAppsPageTitle}"
+ aria-describedby="secondaryText">
+ $i18n{androidAppsEnable}
+ </paper-button>
+ </template>
+ </div>
+ </neon-animatable>
- <div id="manageApps" class="settings-box continuation indented"
- on-keydown="onManageAndroidAppsKeydown_"
- on-tap="onManageAndroidAppsTap_" actionable
- hidden="[[!androidAppsInfo_.appReady]]">
- <div class="start">
- <div>$i18n{androidAppsManageApps}</div>
- </div>
- <button class="icon-external" is="paper-icon-button-light">
- </button>
- </div>
+ <template is="dom-if" route-path="/androidApps/details">
+ <settings-subpage
+ associated-control="[[$$('#android-apps')]]"
+ page-title="$i18n{androidAppsPageLabel}">
+ <settings-android-apps-subpage
+ android-apps-info="[[androidAppsInfo_]]" prefs="{{prefs}}">
+ </settings-android-apps-subpage>
+ </settings-subpage>
+ </template>
+ </settings-animated-pages>
- <!-- Confirm disable android apps dialog -->
- <dialog is="cr-dialog" id="confirmDisableDialog" close-text="$i18n{close}"
- on-cancel="onConfirmDisableDialogCancel_">
- <div class="title">$i18n{androidAppsDisableDialogTitle}</div>
- <div class="body" inner-h-t-m-l="[[getDialogBody_()]]"></div>
- <div class="button-container">
- <paper-button class="cancel-button"
- on-tap="onConfirmDisableDialogCancel_">
- $i18n{cancel}
- </paper-button>
- <paper-button class="action-button"
- on-tap="onConfirmDisableDialogConfirm_">
- $i18n{confirm}
- </paper-button>
- </div>
- </dialog>
</template>
<script src="android_apps_page.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.js b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.js
index 53128b7f70f..e5f9cba60d5 100644
--- a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.js
+++ b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_page.js
@@ -14,27 +14,50 @@ Polymer({
properties: {
/** Preferences state. */
- prefs: Object,
+ prefs: {
+ type: Object,
+ notify: true,
+ },
/** @private {!AndroidAppsInfo|undefined} */
androidAppsInfo_: Object,
+
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+ map.set(
+ settings.Route.ANDROID_APPS_DETAILS.path,
+ '#android-apps .subpage-arrow');
+ return map;
+ },
+ },
},
/** @private {?settings.AndroidAppsBrowserProxy} */
browserProxy_: null,
+ /** @private {?WebUIListener} */
+ listener_: null,
+
/** @override */
created: function() {
this.browserProxy_ = settings.AndroidAppsBrowserProxyImpl.getInstance();
},
/** @override */
- ready: function() {
- cr.addWebUIListener(
+ attached: function() {
+ this.listener_ = cr.addWebUIListener(
'android-apps-info-update', this.androidAppsInfoUpdate_.bind(this));
this.browserProxy_.requestAndroidAppsInfo();
},
+ /** @override */
+ detached: function() {
+ cr.removeWebUIListener(this.listener_);
+ },
+
/**
* @param {AndroidAppsInfo} info
* @private
@@ -47,65 +70,14 @@ Polymer({
* @param {Event} event
* @private
*/
- onManageAndroidAppsKeydown_: function(event) {
- if (event.key != 'Enter' && event.key != ' ')
- return;
- this.browserProxy_.showAndroidAppsSettings(true /** keyboardAction */);
+ onEnableTap_: function(event) {
+ this.setPrefValue('arc.enabled', true);
event.stopPropagation();
},
/** @private */
- onManageAndroidAppsTap_: function(event) {
- this.browserProxy_.showAndroidAppsSettings(false /** keyboardAction */);
- },
-
- /**
- * @return {string}
- * @private
- */
- getDialogBody_: function() {
- return this.i18nAdvanced(
- 'androidAppsDisableDialogMessage', {substitutions: [], tags: ['br']});
- },
-
- /**
- * Handles the change event for the arc.enabled checkbox. Shows a
- * confirmation dialog when disabling the preference.
- * @param {Event} event
- * @private
- */
- onArcEnabledChange_: function(event) {
- if (event.target.checked) {
- /** @type {!SettingsCheckboxElement} */ (event.target).sendPrefChange();
- return;
- }
- this.$.confirmDisableDialog.showModal();
- },
-
- /**
- * Handles the shared proxy confirmation dialog 'Confirm' button.
- * @private
- */
- onConfirmDisableDialogConfirm_: function() {
- /** @type {!SettingsCheckboxElement} */ (this.$.enabled).sendPrefChange();
- this.$.confirmDisableDialog.close();
- },
-
- /**
- * Handles the shared proxy confirmation dialog 'Cancel' button or a cancel
- * event.
- * @private
- */
- onConfirmDisableDialogCancel_: function() {
- /** @type {!SettingsCheckboxElement} */ (this.$.enabled).resetToPrefValue();
- this.$.confirmDisableDialog.close();
- },
-
- /**
- * @param {!Event} e
- * @private
- */
- stopPropagation_: function(e) {
- e.stopPropagation();
+ onSubpageTap_: function() {
+ if (this.androidAppsInfo_.playStoreEnabled)
+ settings.navigateTo(settings.Route.ANDROID_APPS_DETAILS);
},
});
diff --git a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html
new file mode 100644
index 00000000000..f6c23bc191c
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html
@@ -0,0 +1,53 @@
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="android_apps_browser_proxy.html">
+<link rel="import" href="../i18n_setup.html">
+<link rel="import" href="../prefs/prefs_behavior.html">
+<link rel="import" href="../settings_shared_css.html">
+
+<dom-module id="settings-android-apps-subpage">
+ <template>
+ <style include="settings-shared"></style>
+
+ <div id="manageApps" class="settings-box first"
+ on-keydown="onManageAndroidAppsKeydown_"
+ on-tap="onManageAndroidAppsTap_" actionable
+ hidden="[[!androidAppsInfo.settingsAppAvailable]]">
+ <div class="start">
+ <div>$i18n{androidAppsManageApps}</div>
+ </div>
+ <button class="icon-external" is="paper-icon-button-light">
+ </button>
+ </div>
+
+ <template is="dom-if" if="[[allowRemove_(prefs.arc.enabled.*)]]">
+ <div id="remove" class="settings-box" actionable on-tap="onRemoveTap_">
+ <div class="start">$i18n{androidAppsRemove}</div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{androidAppsRemove}">
+ </button>
+ </div>
+ </template>
+
+ <!-- Confirm disable android apps dialog -->
+ <dialog is="cr-dialog" id="confirmDisableDialog" close-text="$i18n{close}"
+ on-cancel="onConfirmDisableDialogCancel_"
+ on-close="onConfirmDisableDialogClose_">
+ <div class="title">$i18n{androidAppsDisableDialogTitle}</div>
+ <div class="body" inner-h-t-m-l="[[dialogBody_]]"></div>
+ <div class="button-container">
+ <paper-button class="cancel-button"
+ on-tap="onConfirmDisableDialogCancel_">
+ $i18n{cancel}
+ </paper-button>
+ <paper-button class="action-button"
+ on-tap="onConfirmDisableDialogConfirm_">
+ $i18n{androidAppsDisableDialogRemove}
+ </paper-button>
+ </div>
+ </dialog>
+
+ </template>
+ <script src="android_apps_subpage.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.js b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.js
new file mode 100644
index 00000000000..f6972396811
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.js
@@ -0,0 +1,109 @@
+// 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.
+
+/**
+ * @fileoverview
+ * 'android-apps-subpage' is the settings subpage for managing android apps.
+ */
+
+Polymer({
+ is: 'settings-android-apps-subpage',
+
+ behaviors: [I18nBehavior, PrefsBehavior],
+
+ properties: {
+ /** Preferences state. */
+ prefs: Object,
+
+ /** @private {!AndroidAppsInfo|undefined} */
+ androidAppsInfo: {
+ type: Object,
+ observer: 'onAndroidAppsInfoUpdate_',
+ },
+
+ /** @private */
+ dialogBody_: {
+ type: String,
+ value: function() {
+ return this.i18nAdvanced(
+ 'androidAppsDisableDialogMessage',
+ {substitutions: [], tags: ['br']});
+ }
+ }
+ },
+
+ /** @private {?settings.AndroidAppsBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = settings.AndroidAppsBrowserProxyImpl.getInstance();
+ },
+
+ /**
+ * @private
+ */
+ onAndroidAppsInfoUpdate_: function() {
+ if (!this.androidAppsInfo.playStoreEnabled)
+ settings.navigateToPreviousRoute();
+ },
+
+ /**
+ * @param {Event} event
+ * @private
+ */
+ onManageAndroidAppsKeydown_: function(event) {
+ if (event.key != 'Enter' && event.key != ' ')
+ return;
+ this.browserProxy_.showAndroidAppsSettings(true /** keyboardAction */);
+ event.stopPropagation();
+ },
+
+ /** @private */
+ onManageAndroidAppsTap_: function(event) {
+ this.browserProxy_.showAndroidAppsSettings(false /** keyboardAction */);
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ allowRemove_: function() {
+ return this.prefs.arc.enabled.enforcement !=
+ chrome.settingsPrivate.Enforcement.ENFORCED;
+ },
+
+ /**
+ * Shows a confirmation dialog when disabling android apps.
+ * @param {Event} event
+ * @private
+ */
+ onRemoveTap_: function(event) {
+ this.$.confirmDisableDialog.showModal();
+ },
+
+ /**
+ * Handles the shared proxy confirmation dialog 'Confirm' button.
+ * @private
+ */
+ onConfirmDisableDialogConfirm_: function() {
+ this.setPrefValue('arc.enabled', false);
+ this.$.confirmDisableDialog.close();
+ settings.navigateToPreviousRoute();
+ },
+
+ /**
+ * Handles the shared proxy confirmation dialog 'Cancel' button or a cancel
+ * event.
+ * @private
+ */
+ onConfirmDisableDialogCancel_: function() {
+ this.$.confirmDisableDialog.close();
+ },
+
+ /** @private */
+ onConfirmDisableDialogClose_: function() {
+ this.$$('#remove button').focus();
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/android_apps_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/android_apps_page/compiled_resources2.gyp
index 655b3eb0668..68c188bb7d3 100644
--- a/chromium/chrome/browser/resources/settings/android_apps_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/android_apps_page/compiled_resources2.gyp
@@ -14,9 +14,19 @@
{
'target_name': 'android_apps_page',
'dependencies': [
- '../controls/compiled_resources2.gyp:settings_checkbox',
+ '../compiled_resources2.gyp:route',
+ '../prefs/compiled_resources2.gyp:prefs_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(EXTERNS_GYP):settings_private',
+ 'android_apps_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'android_apps_subpage',
+ 'dependencies': [
+ '../compiled_resources2.gyp:route',
'../prefs/compiled_resources2.gyp:prefs_behavior',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'android_apps_browser_proxy',
],
diff --git a/chromium/chrome/browser/resources/settings/animation/animation_group.js b/chromium/chrome/browser/resources/settings/animation/animation_group.js
deleted file mode 100644
index 7e731efa736..00000000000
--- a/chromium/chrome/browser/resources/settings/animation/animation_group.js
+++ /dev/null
@@ -1,49 +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.
-
-cr.define('settings.animation', function() {
- 'use strict';
-
- /**
- * An AnimationGroup manages a set of animations, handles any styling setup or
- * cleanup, and provides a Promise for chaining actions on finish or cancel.
- * This abstracts out all these details so UI elements can simply create an
- * object rather than individually track the state of every element, style and
- * web animation. AnimationGroups may compose web animations and other
- * AnimationGroups.
- * @interface
- */
- function AnimationGroup() {}
-
- AnimationGroup.prototype = {
- /**
- * Sets up and plays the animation(s).
- * @return {!Promise} Convenient reference to |finished| for chaining.
- */
- play: assertNotReached,
-
- /**
- * If animations are still playing, immediately finishes them and resolves
- * |finished| with the |true| value.
- */
- finish: assertNotReached,
-
- /**
- * If animations are still playing, immediately cancels them and resolves
- * |finished| with the |false| value.
- */
- cancel: assertNotReached,
-
- /**
- * Resolved with a success value once the AnimationGroup finishes (true) or
- * is canceled (false).
- * @type {?Promise<boolean>}
- */
- finished: null,
- };
-
- return {
- AnimationGroup: AnimationGroup,
- };
-});
diff --git a/chromium/chrome/browser/resources/settings/animation/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/animation/compiled_resources2.gyp
index 45a628db233..be9c892fc4c 100644
--- a/chromium/chrome/browser/resources/settings/animation/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/animation/compiled_resources2.gyp
@@ -13,9 +13,11 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'animation_group',
+ 'target_name': 'fade_animations',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ 'animation',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp:neon-animation-behavior-extracted',
+ '<(EXTERNS_GYP):web_animations',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/settings/animation/fade_animations.html b/chromium/chrome/browser/resources/settings/animation/fade_animations.html
new file mode 100644
index 00000000000..b42fef50d99
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/animation/fade_animations.html
@@ -0,0 +1,3 @@
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-behavior.html">
+<link rel="import" href="animation.html">
+<script src="fade_animations.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/animation/fade_animations.js b/chromium/chrome/browser/resources/settings/animation/fade_animations.js
new file mode 100644
index 00000000000..1fbd3bcd6bb
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/animation/fade_animations.js
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Defines fade animations similar to Polymer's fade-in-animation
+ * and fade-out-animation, but with Settings-specific timings.
+ */
+Polymer({
+ is: 'settings-fade-in-animation',
+
+ behaviors: [Polymer.NeonAnimationBehavior],
+
+ configure: function(config) {
+ var node = config.node;
+ this._effect = new KeyframeEffect(
+ node,
+ [
+ {'opacity': '0'},
+ {'opacity': '1'},
+ ],
+ /** @type {!KeyframeEffectOptions} */ ({
+ duration: settings.animation.Timing.DURATION,
+ easing: settings.animation.Timing.EASING,
+ fill: 'both',
+ }));
+ return this._effect;
+ }
+});
+
+Polymer({
+ is: 'settings-fade-out-animation',
+
+ behaviors: [Polymer.NeonAnimationBehavior],
+
+ configure: function(config) {
+ var node = config.node;
+ this._effect = new KeyframeEffect(
+ node,
+ [
+ {'opacity': '1'},
+ {'opacity': '0'},
+ ],
+ /** @type {!KeyframeEffectOptions} */ ({
+ duration: settings.animation.Timing.DURATION,
+ easing: settings.animation.Timing.EASING,
+ fill: 'both',
+ }));
+ return this._effect;
+ }
+});
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js b/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js
index b139a7f1494..65b7698028c 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js
@@ -28,6 +28,12 @@ cr.define('settings', function() {
// <if expr="is_linux and not chromeos">
useSystemTheme: assertNotReached,
// </if>
+
+ /**
+ * @param {string} url The url of which to check validity.
+ * @return {!Promise<boolean>}
+ */
+ validateStartupPage: assertNotReached,
};
/**
@@ -76,6 +82,11 @@ cr.define('settings', function() {
chrome.send('useSystemTheme');
},
// </if>
+
+ /** @override */
+ validateStartupPage: function(url) {
+ return cr.sendWithPromise('validateStartupPage', url);
+ },
};
return {
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html b/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html
index 782feff8345..72fac987255 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html
@@ -1,9 +1,9 @@
-<link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="fonts_browser_proxy.html">
+<link rel="import" href="../controls/settings_slider.html">
<link rel="import" href="../controls/settings_dropdown_menu.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../settings_shared_css.html">
@@ -13,101 +13,109 @@
<style include="settings-shared"></style>
<div class="settings-box first">
<div class="start">$i18n{fontSize}</div>
- <cr-slider id="sizeSlider"
- value="{{prefs.webkit.webprefs.default_font_size.value}}"
+ <settings-slider id="sizeSlider"
+ pref="{{prefs.webkit.webprefs.default_font_size}}"
tick-values="[[fontSizeRange_]]"
label-min="$i18n{tiny}" label-max="$i18n{huge}">
- </cr-slider>
+ </settings-slider>
</div>
<div class="settings-box">
<div class="start">$i18n{minimumFont}</div>
- <div class="list-item"
- style$="[[computeStyle_(
- prefs.webkit.webprefs.minimum_font_size.value,
- prefs.webkit.webprefs.fonts.standard.Zyyy.value)]]">
- <span>[[prefs.webkit.webprefs.minimum_font_size.value]]</span>
- : $i18n{quickBrownFox}
+ <div style="
+ font-size:[[computeMinimumFontSize_(
+ prefs.webkit.webprefs.minimum_font_size.value)]]px;
+ font-family:
+ '[[prefs.webkit.webprefs.fonts.standard.Zyyy.value]]';">
+ [[computeMinimumFontSize_(
+ prefs.webkit.webprefs.minimum_font_size.value)]]:
+ $i18n{quickBrownFox}
</div>
- <cr-slider id="minimumSizeSlider"
- value="{{prefs.webkit.webprefs.minimum_font_size.value}}"
+ <settings-slider id="minimumSizeSlider"
+ pref="{{prefs.webkit.webprefs.minimum_font_size}}"
tick-values="[[minimumFontSizeRange_]]"
label-min="$i18n{tiny}" label-max="$i18n{huge}">
- </cr-slider>
+ </settings-slider>
</div>
<div class="settings-box">
- <div class="start">
- <h2>$i18n{standardFont}</h2>
- <div class="list-frame">
- <div class="list-item">
- <settings-dropdown-menu class="start"
- pref="{{prefs.webkit.webprefs.fonts.standard.Zyyy}}"
- menu-options="[[fontOptions_]]">
- </settings-dropdown-menu>
- </div>
- <div class="list-item underbar"
- style$="[[computeStyle_(
- prefs.webkit.webprefs.default_font_size.value,
- prefs.webkit.webprefs.fonts.standard.Zyyy.value)]]">
- <span>
- [[prefs.webkit.webprefs.default_font_size.value]]:
- $i18n{quickBrownFox}
- </span>
- </div>
- </div>
- <h2>$i18n{serifFont}</h2>
- <div class="list-frame">
- <div class="list-item">
- <settings-dropdown-menu class="start"
- pref="{{prefs.webkit.webprefs.fonts.serif.Zyyy}}"
- menu-options="[[fontOptions_]]">
- </settings-dropdown-menu>
- </div>
- <div class="list-item underbar"
- style$="[[computeStyle_(
- prefs.webkit.webprefs.default_font_size.value,
- prefs.webkit.webprefs.fonts.serif.Zyyy.value)]]">
- <span>
- [[prefs.webkit.webprefs.default_font_size.value]]:
- $i18n{quickBrownFox}
- </span>
- </div>
- </div>
- <h2>$i18n{sansSerifFont}</h2>
- <div class="list-frame">
- <div class="list-item">
- <settings-dropdown-menu class="start"
- pref="{{prefs.webkit.webprefs.fonts.sansserif.Zyyy}}"
- menu-options="[[fontOptions_]]">
- </settings-dropdown-menu>
- </div>
- <div class="list-item underbar"
- style$="{{computeStyle_(
- prefs.webkit.webprefs.default_font_size.value,
- prefs.webkit.webprefs.fonts.sansserif.Zyyy.value)}}">
- <span>
- [[prefs.webkit.webprefs.default_font_size.value]]:
- $i18n{quickBrownFox}
- </span>
- </div>
- </div>
- <h2>$i18n{fixedWidthFont}</h2>
- <div class="list-frame">
- <div class="list-item">
- <settings-dropdown-menu class="start"
- pref="{{prefs.webkit.webprefs.fonts.fixed.Zyyy}}"
- menu-options="[[fontOptions_]]">
- </settings-dropdown-menu>
- </div>
- <div class="list-item"
- style$="[[computeStyle_(
- prefs.webkit.webprefs.default_fixed_font_size.value,
- prefs.webkit.webprefs.fonts.fixed.Zyyy.value)]]">
- <span>
- [[prefs.webkit.webprefs.default_font_size.value]]:
- $i18n{quickBrownFox}
- </span>
- </div>
- </div>
+ <h2>$i18n{standardFont}</h2>
+ </div>
+ <div class="list-frame">
+ <div class="list-item">
+ <settings-dropdown-menu class="start" label="$i18n{standardFont}"
+ pref="{{prefs.webkit.webprefs.fonts.standard.Zyyy}}"
+ menu-options="[[fontOptions_]]">
+ </settings-dropdown-menu>
+ </div>
+ <div class="list-item underbar"
+ style="
+ font-size:[[prefs.webkit.webprefs.default_font_size.value]]px;
+ font-family:
+ '[[prefs.webkit.webprefs.fonts.standard.Zyyy.value]]';">
+ <span>
+ [[prefs.webkit.webprefs.default_font_size.value]]:
+ $i18n{quickBrownFox}
+ </span>
+ </div>
+ </div>
+ <div class="settings-box">
+ <h2>$i18n{serifFont}</h2>
+ </div>
+ <div class="list-frame">
+ <div class="list-item">
+ <settings-dropdown-menu class="start" label="$i18n{serifFont}"
+ pref="{{prefs.webkit.webprefs.fonts.serif.Zyyy}}"
+ menu-options="[[fontOptions_]]">
+ </settings-dropdown-menu>
+ </div>
+ <div class="list-item underbar"
+ style="
+ font-size:[[prefs.webkit.webprefs.default_font_size.value]]px;
+ font-family:
+ '[[prefs.webkit.webprefs.fonts.serif.Zyyy.value]]';">
+ <span>
+ [[prefs.webkit.webprefs.default_font_size.value]]:
+ $i18n{quickBrownFox}
+ </span>
+ </div>
+ </div>
+ <div class="settings-box">
+ <h2>$i18n{sansSerifFont}</h2>
+ </div>
+ <div class="list-frame">
+ <div class="list-item">
+ <settings-dropdown-menu class="start" label="$i18n{sansSerifFont}"
+ pref="{{prefs.webkit.webprefs.fonts.sansserif.Zyyy}}"
+ menu-options="[[fontOptions_]]">
+ </settings-dropdown-menu>
+ </div>
+ <div class="list-item underbar"
+ style="
+ font-size:[[prefs.webkit.webprefs.default_font_size.value]]px;
+ font-family:
+ '[[prefs.webkit.webprefs.fonts.sansserif.Zyyy.value]]';">
+ <span>
+ [[prefs.webkit.webprefs.default_font_size.value]]:
+ $i18n{quickBrownFox}
+ </span>
+ </div>
+ </div>
+ <div class="settings-box">
+ <h2>$i18n{fixedWidthFont}</h2>
+ </div>
+ <div class="list-frame">
+ <div class="list-item">
+ <settings-dropdown-menu class="start" label="$i18n{fixedWidthFont}"
+ pref="{{prefs.webkit.webprefs.fonts.fixed.Zyyy}}"
+ menu-options="[[fontOptions_]]">
+ </settings-dropdown-menu>
+ </div>
+ <div class="list-item"
+ style="
+ font-size:
+ [[prefs.webkit.webprefs.default_fixed_font_size.value]]px;
+ font-family:
+ '[[prefs.webkit.webprefs.fonts.fixed.Zyyy.value]]';">
+ $i18n{quickBrownFox}
</div>
</div>
<template is="dom-if" if="[[!isGuest_]]">
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js b/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js
index 17d826a81fe..0f5e31a134a 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js
@@ -5,13 +5,6 @@
(function() {
'use strict';
- /**
- * This is the absolute difference maintained between standard and
- * fixed-width font sizes. http://crbug.com/91922.
- * @const @private {number}
- */
- var SIZE_DIFFERENCE_FIXED_STANDARD_ = 3;
-
/** @const @private {!Array<number>} */
var FONT_SIZE_RANGE_ = [
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36,
@@ -26,11 +19,6 @@
/**
* 'settings-appearance-fonts-page' is the settings page containing appearance
* settings.
- *
- * Example:
- *
- * <settings-appearance-fonts-page prefs="{{prefs}}">
- * </settings-appearance-fonts-page>
*/
Polymer({
is: 'settings-appearance-fonts-page',
@@ -47,9 +35,6 @@
/** @private */
advancedExtensionUrl_: String,
- /** @private {!settings.FontsBrowserProxy} */
- browserProxy_: Object,
-
/** @private {!DropdownMenuOptionList} */
fontOptions_: Object,
@@ -88,9 +73,8 @@
},
},
- observers: [
- 'fontSizeChanged_(prefs.webkit.webprefs.default_font_size.value)',
- ],
+ /** @private {?settings.FontsBrowserProxy} */
+ browserProxy_: null,
/** @override */
created: function() {
@@ -144,27 +128,13 @@
},
/**
- * @param {number} value The changed font size slider value.
- * @private
- */
- fontSizeChanged_: function(value) {
- // TODO(michaelpg): Whitelist this pref in prefs_utils.cc so it is
- // included in the <settings-prefs> getAllPrefs call, otherwise this path
- // is invalid and nothing happens. See crbug.com/612535.
- this.set('prefs.webkit.webprefs.default_fixed_font_size.value',
- value - SIZE_DIFFERENCE_FIXED_STANDARD_);
- },
-
- /**
- * Creates an html style value.
- * @param {number} fontSize The font size to use.
- * @param {string} fontFamily The name of the font family use.
- * @return {string}
+ * Get the minimum font size, accounting for unset prefs.
+ * @return {?}
* @private
*/
- computeStyle_: function(fontSize, fontFamily) {
- return 'font-size: ' + fontSize + "px; font-family: '" + fontFamily +
- "';";
+ computeMinimumFontSize_: function() {
+ return this.get('prefs.webkit.webprefs.minimum_font_size.value') ||
+ MINIMUM_FONT_SIZE_RANGE_[0];
},
});
})();
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
index de371637cdd..712bce03b97 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -9,7 +9,6 @@
<link rel="import" href="../controls/controlled_radio_button.html">
<link rel="import" href="../controls/extension_controlled_indicator.html">
<link rel="import" href="../controls/settings_dropdown_menu.html">
-<link rel="import" href="../controls/settings_input.html">
<link rel="import" href="../controls/settings_radio_group.html">
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../route.html">
@@ -18,22 +17,28 @@
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="../settings_vars_css.html">
<link rel="import" href="appearance_fonts_page.html">
+<link rel="import" href="home_url_input.html">
<dom-module id="settings-appearance-page">
<template>
<style include="settings-shared md-select">
- :host {
- --paper-input-container-label: {
- font-size: inherit;
- font-weight: inherit;
- };
- }
-
.secondary-button ~ .secondary-button {
-webkit-margin-start: 12px;
}
+
+ #custom-input {
+ margin-bottom: 1rem;
+ }
+
+ #customHomePage {
+ --paper-input-container: {
+ width: 200px;
+ };
+ width: 100%; /* Pushes policy indicators to end. */
+ }
</style>
- <settings-animated-pages id="pages" section="appearance">
+ <settings-animated-pages id="pages" section="appearance"
+ focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<if expr="chromeos">
<div class="settings-box first two-line" id="wallpaperButton"
@@ -103,28 +108,27 @@
pref="{{prefs.browser.show_home_button}}"
label="$i18n{showHomeButton}"
sub-label="[[getShowHomeSubLabel_(
- prefs.homepage_is_newtabpage.value, prefs.homepage.value)]]">
+ prefs.browser.show_home_button.value,
+ prefs.homepage_is_newtabpage.value,
+ prefs.homepage.value)]]">
</settings-toggle-button>
</div>
<template is="dom-if" if="[[prefs.browser.show_home_button.value]]">
- <div class="list-frame"
- hidden="[[!pageVisibility.homeButton]]">
+ <div class="list-frame" hidden="[[!pageVisibility.homeButton]]">
<settings-radio-group pref="{{prefs.homepage_is_newtabpage}}">
<controlled-radio-button class="list-item" name="true"
- pref="[[prefs.homepage_is_newtabpage]]">
- $i18n{homePageNtp}
+ pref="[[prefs.homepage_is_newtabpage]]"
+ label="$i18n{homePageNtp}" no-extension-indicator>
</controlled-radio-button>
- <controlled-radio-button class="list-item" name="false"
- pref="[[prefs.homepage_is_newtabpage]]">
- $i18n{other}
+ <controlled-radio-button id="custom-input" class="list-item"
+ name="false" pref="[[prefs.homepage_is_newtabpage]]"
+ no-extension-indicator>
<!-- TODO(dbeam): this can show double indicators when both
homepage and whether to use the NTP as the homepage are
managed. -->
- <settings-input no-label-float pref="{{prefs.homepage}}"
- label="$i18n{exampleDotCom}"
- can-tab="[[!prefs.homepage_is_newtabpage.value]]"
- stop-keyboard-event-propagation>
- </settings-input>
+ <home-url-input id="customHomePage" pref="{{prefs.homepage}}"
+ can-tab="[[!prefs.homepage_is_newtabpage.value]]">
+ </home-url-input>
</controlled-radio-button>
<template is="dom-if" if="[[prefs.homepage.extensionId]]">
<extension-controlled-indicator
@@ -156,30 +160,27 @@
<div class="settings-box">
</if>
<div class="start">$i18n{fontSize}</div>
- <settings-dropdown-menu id="defaultFontSize"
+ <settings-dropdown-menu id="defaultFontSize" label="$i18n{fontSize}"
pref="{{prefs.webkit.webprefs.default_font_size}}"
menu-options="[[fontSizeOptions_]]">
</settings-dropdown-menu>
</div>
- <div id="customize-fonts-subpage-trigger" class="settings-box two-line"
+ <div id="customize-fonts-subpage-trigger" class="settings-box"
on-tap="onCustomizeFontsTap_" actionable>
<div class="start">
$i18n{customizeFonts}
- <div class="secondary" id="fontsSecondary">$i18n{chooseFonts}</div>
</div>
<button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{customizeFonts}"
- aria-describedby="fontsSecondary"></button>
+ aria-label="$i18n{customizeFonts}"></button>
</div>
- <div class="settings-box"
- hidden="[[!pageVisibility.pageZoom]]">
- <div class="start">$i18n{pageZoom}</div>
+ <div class="settings-box" hidden="[[!pageVisibility.pageZoom]]">
+ <div id="pageZoom" class="start">$i18n{pageZoom}</div>
<div class="md-select-wrapper">
- <select id="zoomLevel" class="md-select"
+ <select id="zoomLevel" class="md-select" aria-labelledy="pageZoom"
on-change="onZoomLevelChange_">
<template is="dom-repeat" items="[[pageZoomLevels_]]">
<option value="[[item]]"
- selected$="[[zoomValuesEqual_(item, defaultZoom_)]]">
+ selected="[[zoomValuesEqual_(item, defaultZoom_)]]">
[[formatZoom_(item)]]%
</option>
</template>
@@ -187,6 +188,14 @@
<span class="md-select-underline"></span>
</div>
</div>
+<if expr="is_macosx">
+ <div class="settings-box">
+ <settings-toggle-button class="start"
+ pref="{{prefs.webkit.webprefs.tabs_to_links}}"
+ label="$i18n{tabsToLinks}">
+ </settings-toggle-button>
+ </div>
+</if>
</neon-animatable>
<template is="dom-if" route-path="/fonts">
<settings-subpage
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js
index a258d4687d6..5571b2d2499 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -2,6 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
+/**
+ * This is the absolute difference maintained between standard and
+ * fixed-width font sizes. http://crbug.com/91922.
+ * @const @private {number}
+ */
+var SIZE_DIFFERENCE_FIXED_STANDARD_ = 3;
+
+
/**
* 'settings-appearance-page' is the settings page containing appearance
* settings.
@@ -89,6 +98,18 @@ Polymer({
type: Boolean,
value: false, // Can only be true on Linux, but value exists everywhere.
},
+
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+ map.set(
+ settings.Route.FONTS.path,
+ '#customize-fonts-subpage-trigger .subpage-arrow');
+ return map;
+ },
+ },
},
/** @private {?settings.AppearanceBrowserProxy} */
@@ -98,12 +119,13 @@ Polymer({
themeUrl_: '',
observers: [
+ 'defaultFontSizeChanged_(prefs.webkit.webprefs.default_font_size.value)',
'themeChanged_(prefs.extensions.theme.id.value, useSystemTheme_)',
-// <if expr="is_linux and not chromeos">
+ // <if expr="is_linux and not chromeos">
// NOTE: this pref only exists on Linux.
'useSystemThemePrefChanged_(prefs.extensions.theme.use_system.value)',
-// </if>
+ // </if>
],
created: function() {
@@ -129,15 +151,18 @@ Polymer({
},
/**
+ * @param {boolean} showHomepage Whether to show home page.
* @param {boolean} isNtp Whether to use the NTP as the home page.
- * @param {string} homepage If not using NTP, use this URL.
+ * @param {string} homepageValue If not using NTP, use this URL.
* @return {string} The sub-label.
* @private
*/
- getShowHomeSubLabel_: function(isNtp, homepage) {
+ getShowHomeSubLabel_: function(showHomepage, isNtp, homepageValue) {
+ if (!showHomepage)
+ return this.i18n('homeButtonDisabled');
if (isNtp)
return this.i18n('homePageNtp');
- return homepage || this.i18n('exampleDotCom');
+ return homepageValue || this.i18n('customWebAddress');
},
/** @private */
@@ -150,12 +175,24 @@ Polymer({
this.fire('refresh-pref', 'homepage');
},
+ /**
+ * @param {number} value The changed font size slider value.
+ * @private
+ */
+ defaultFontSizeChanged_: function(value) {
+ // This pref is handled separately in some extensions, but here it is tied
+ // to default_font_size (to simplify the UI).
+ this.set(
+ 'prefs.webkit.webprefs.default_fixed_font_size.value',
+ value - SIZE_DIFFERENCE_FIXED_STANDARD_);
+ },
+
/** @private */
onThemesTap_: function() {
window.open(this.themeUrl_ || loadTimeData.getString('themesGalleryUrl'));
},
-// <if expr="chromeos">
+ // <if expr="chromeos">
/**
* ChromeOS only.
* @private
@@ -163,14 +200,14 @@ Polymer({
openWallpaperManager_: function() {
this.browserProxy_.openWallpaperManager();
},
-// </if>
+ // </if>
/** @private */
onUseDefaultTap_: function() {
this.browserProxy_.useDefaultTheme();
},
-// <if expr="is_linux and not chromeos">
+ // <if expr="is_linux and not chromeos">
/**
* @param {boolean} useSystemTheme
* @private
@@ -215,7 +252,7 @@ Polymer({
onUseSystemTap_: function() {
this.browserProxy_.useSystemTheme();
},
-// </if>
+ // </if>
/**
* @param {string} themeId
@@ -235,12 +272,12 @@ Polymer({
}
var i18nId;
-// <if expr="is_linux and not chromeos">
+ // <if expr="is_linux and not chromeos">
i18nId = useSystemTheme ? 'systemTheme' : 'classicTheme';
-// </if>
-// <if expr="not is_linux or chromeos">
+ // </if>
+ // <if expr="not is_linux or chromeos">
i18nId = 'chooseFromWebStore';
-// </if>
+ // </if>
this.themeSublabel_ = this.i18n(i18nId);
this.themeUrl_ = '';
},
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp
index 50b44592390..67937b8e249 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp
@@ -52,5 +52,18 @@
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'home_url_input',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_pref_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(EXTERNS_GYP):settings_private',
+ '../controls/compiled_resources2.gyp:pref_control_behavior',
+ 'appearance_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
],
}
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.html b/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.html
new file mode 100644
index 00000000000..0e9dc1036d4
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.html
@@ -0,0 +1,36 @@
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
+<link rel="import" href="../controls/pref_control_behavior.html">
+<link rel="import" href="appearance_browser_proxy.html">
+
+<dom-module id="home-url-input">
+ <template>
+ <style>
+ :host {
+ cursor: auto;
+ display: inline-block;
+ }
+
+ #outerDiv {
+ justify-content: space-between;
+ }
+ </style>
+ <div id="outerDiv" class="layout horizontal center">
+ <paper-input id="input" value="{{value}}" no-label-float
+ label="$i18n{enterCustomWebAddress}" error-message="$i18n{notValid}"
+ on-change="onChange_" on-keydown="onKeydown_" on-input="validate_"
+ invalid="{{invalid}}" tabindex$="[[getTabindex_(canTab)]]"
+ disabled="[[isDisabled_(disabled, pref.*)]]"
+ stop-keyboard-event-propagation>
+ </paper-input>
+ <template is="dom-if" if="[[hasPrefPolicyIndicator(pref.*)]]">
+ <cr-policy-pref-indicator pref="[[pref]]" icon-aria-label="[[label]]">
+ </cr-policy-pref-indicator>
+ </template>
+ </div>
+ </template>
+ <script src="home_url_input.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js b/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js
new file mode 100644
index 00000000000..95faaa58fdf
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js
@@ -0,0 +1,141 @@
+// 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.
+
+/**
+ * @fileoverview
+ * `home-url-input` is a single-line text field intending to be used with
+ * prefs.homepage
+ */
+Polymer({
+ is: 'home-url-input',
+
+ behaviors: [CrPolicyPrefBehavior, PrefControlBehavior],
+
+ properties: {
+ /**
+ * The preference object to control.
+ * @type {!chrome.settingsPrivate.PrefObject|undefined}
+ * @override
+ */
+ pref: {observer: 'prefChanged_'},
+
+ /* Set to true to disable editing the input. */
+ disabled: {type: Boolean, value: false, reflectToAttribute: true},
+
+ canTab: Boolean,
+
+ invalid: {type: Boolean, value: false},
+
+ /* The current value of the input, reflected to/from |pref|. */
+ value: {
+ type: String,
+ value: '',
+ notify: true,
+ },
+ },
+
+ /** @private {?settings.AppearanceBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = settings.AppearanceBrowserProxyImpl.getInstance();
+ this.noExtensionIndicator = true; // Prevent double indicator.
+ },
+
+ /**
+ * Focuses the 'input' element.
+ */
+ focus: function() {
+ this.$.input.focus();
+ },
+
+ /**
+ * Polymer changed observer for |pref|.
+ * @private
+ */
+ prefChanged_: function() {
+ if (!this.pref)
+ return;
+
+ // Ignore updates while the input is focused so that user input is not
+ // overwritten.
+ if (this.$.input.focused)
+ return;
+
+ this.setInputValueFromPref_();
+ },
+
+ /** @private */
+ setInputValueFromPref_: function() {
+ assert(this.pref.type == chrome.settingsPrivate.PrefType.URL);
+ this.value = /** @type {string} */ (this.pref.value);
+ },
+
+ /**
+ * Gets a tab index for this control if it can be tabbed to.
+ * @param {boolean} canTab
+ * @return {number}
+ * @private
+ */
+ getTabindex_: function(canTab) {
+ return canTab ? 0 : -1;
+ },
+
+ /**
+ * Change event handler for paper-input. Updates the pref value.
+ * settings-input uses the change event because it is fired by the Enter key.
+ * @private
+ */
+ onChange_: function() {
+ if (this.invalid) {
+ this.resetValue_();
+ return;
+ }
+
+ assert(this.pref.type == chrome.settingsPrivate.PrefType.URL);
+ this.set('pref.value', this.value);
+ },
+
+ /** @private */
+ resetValue_: function() {
+ this.invalid = false;
+ this.setInputValueFromPref_();
+ this.$.input.blur();
+ },
+
+ /**
+ * Keydown handler to specify enter-key and escape-key interactions.
+ * @param {!Event} event
+ * @private
+ */
+ onKeydown_: function(event) {
+ // If pressed enter when input is invalid, do not trigger on-change.
+ if (event.key == 'Enter' && this.invalid)
+ event.preventDefault();
+ else if (event.key == 'Escape')
+ this.resetValue_();
+ },
+
+ /**
+ * @param {boolean} disabled
+ * @return {boolean} Whether the element should be disabled.
+ * @private
+ */
+ isDisabled_: function(disabled) {
+ return disabled || this.isPrefEnforced();
+ },
+
+ /** @private */
+ validate_: function() {
+ if (this.value == '') {
+ this.invalid = false;
+ return;
+ }
+
+ this.browserProxy_.validateStartupPage(this.value).then(function(isValid) {
+ this.invalid = !isValid;
+ }.bind(this));
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/basic_page/basic_page.html b/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
index 47041e172e7..206c4b053f0 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -1,15 +1,8 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="../a11y_page/a11y_page.html">
<link rel="import" href="../appearance_page/appearance_page.html">
-<link rel="import" href="../controls/settings_idle_render.html">
-<link rel="import" href="../downloads_page/downloads_page.html">
-<link rel="import" href="../languages_page/languages_page.html">
+<link rel="import" href="../controls/settings_idle_load.html">
<link rel="import" href="../on_startup_page/on_startup_page.html">
-<link rel="import" href="../passwords_and_forms_page/passwords_and_forms_page.html">
<link rel="import" href="../people_page/people_page.html">
-<link rel="import" href="../printing_page/printing_page.html">
-<link rel="import" href="../privacy_page/privacy_page.html">
-<link rel="import" href="../reset_page/reset_page.html">
<link rel="import" href="../reset_page/reset_profile_banner.html">
<link rel="import" href="../search_page/search_page.html">
<link rel="import" href="../settings_page/main_page_behavior.html">
@@ -21,14 +14,12 @@
<if expr="chromeos">
<link rel="import" href="../android_apps_page/android_apps_page.html">
<link rel="import" href="../bluetooth_page/bluetooth_page.html">
-<link rel="import" href="../date_time_page/date_time_page.html">
<link rel="import" href="../device_page/device_page.html">
<link rel="import" href="../internet_page/internet_page.html">
</if>
<if expr="not chromeos">
<link rel="import" href="../default_browser_page/default_browser_page.html">
-<link rel="import" href="../system_page/system_page.html">
</if>
<!-- TODO(michaelpg): Rename to something better than "basic" now that this page
@@ -36,6 +27,12 @@
<dom-module id="settings-basic-page">
<template>
<style include="settings-page-styles">
+ :host([is-subpage-animating]) {
+ /* Prevent an unwanted horizontal scrollbar when transitioning back from
+ * a sub-page. */
+ overflow: hidden;
+ }
+
#advancedToggle {
--paper-button: {
text-transform: none;
@@ -190,7 +187,8 @@
</h2>
</template>
- <template is="settings-idle-render" id="advancedPageTemplate">
+ <template is="settings-idle-load" id="advancedPageTemplate"
+ url="/lazy_load.html">
<div id="advancedPage" hidden$="[[!showAdvancedPage_(
currentRoute_, inSearchMode, hasExpandedSection_,
advancedToggleExpanded)]]">
diff --git a/chromium/chrome/browser/resources/settings/basic_page/basic_page.js b/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
index 395996069a8..d360e891f42 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -105,19 +105,33 @@ Polymer({
* Queues a task to search the basic sections, then another for the advanced
* sections.
* @param {string} query The text to search for.
- * @return {!Promise<!settings.SearchRequest>} A signal indicating that
+ * @return {!Promise<!settings.SearchResult>} A signal indicating that
* searching finished.
*/
searchContents: function(query) {
- var whenSearchDone = settings.getSearchManager().search(
- query, assert(this.$$('#basicPage')));
+ var whenSearchDone = [
+ settings.getSearchManager().search(query, assert(this.$$('#basicPage'))),
+ ];
if (this.pageVisibility.advancedSettings !== false) {
- assert(whenSearchDone === settings.getSearchManager().search(
- query, assert(this.$$('#advancedPageTemplate').get())));
+ whenSearchDone.push(this.$$('#advancedPageTemplate').get().then(
+ function(advancedPage) {
+ return settings.getSearchManager().search(query, advancedPage);
+ }));
}
- return whenSearchDone;
+ return Promise.all(whenSearchDone).then(function(requests) {
+ // Combine the SearchRequests results to a single SearchResult object.
+ return {
+ canceled: requests.some(function(r) { return r.canceled; }),
+ didFindMatches: requests.every(function(r) {
+ return !r.didFindMatches();
+ }),
+ // All requests correspond to the same user query, so only need to check
+ // one of them.
+ wasClearSearch: requests[0].isSame(''),
+ };
+ });
},
// <if expr="chromeos">
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.js b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.js
index 898e479e4ac..5f0dee2bdde 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.js
@@ -57,7 +57,7 @@ Polymer({
* @private
*/
getConnectActionText_: function(connected) {
- return this.i18n(connected ? 'bluetoothDisconnect' : 'bluetoothPair');
+ return this.i18n(connected ? 'bluetoothDisconnect' : 'bluetoothConnect');
},
/**
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
index 035e18e114c..8f3623559cc 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
@@ -20,26 +20,29 @@
<neon-animatable route-path="default">
<div id="bluetoothDevices"
class="settings-box two-line" actionable on-tap="onTap_">
- <iron-icon icon="[[getIcon_(bluetoothEnabled_)]]"></iron-icon>
+ <iron-icon icon="[[getIcon_(bluetoothToggleState_)]]"></iron-icon>
<div class="middle">
$i18n{bluetoothPageTitle}
<div class="secondary" id="bluetoothSecondary">
- [[getOnOffString_(bluetoothEnabled_,
+ [[getOnOffString_(bluetoothToggleState_,
'$i18nPolymer{deviceOn}', '$i18nPolymer{deviceOff}')]]
</div>
</div>
- <cr-policy-pref-indicator
+ <cr-policy-pref-indicator icon-aria-label="$i18n{bluetoothPageTitle}"
pref="[[prefs.cros.device.allow_bluetooth]]"
hidden="[[prefs.cros.device.allow_bluetooth.value]]">
</cr-policy-pref-indicator>
- <button class="subpage-arrow" is="paper-icon-button-light"
- on-tap="onSubpageArrowTap_" aria-label="$i18n{bluetoothPageTitle}"
- aria-describedby="bluetoothSecondary">
- </button>
+ <template is="dom-if" if="[[bluetoothEnabled_]]">
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ on-tap="onSubpageArrowTap_"
+ aria-label="$i18n{bluetoothPageTitle}"
+ aria-describedby="bluetoothSecondary">
+ </button>
+ </template>
<div class="secondary-action">
<paper-toggle-button id="enableBluetooth"
- checked="{{bluetoothEnabled_}}"
- disabled="[[!adapterState_.available]]" on-tap="stopTap_"
+ checked="{{bluetoothToggleState_}}"
+ disabled$="[[bluetoothToggleDisabled_]]" on-tap="stopTap_"
aria-label="$i18n{bluetoothToggleA11yLabel}">
</paper-toggle-button>
</div>
@@ -51,7 +54,8 @@
page-title="$i18n{bluetoothPageTitle}">
<settings-bluetooth-subpage
adapter-state="[[adapterState_]]"
- bluetooth-enabled="{{bluetoothEnabled_}}"
+ bluetooth-toggle-state="{{bluetoothToggleState_}}"
+ bluetooth-toggle-disabled="[[bluetoothToggleDisabled_]]"
bluetooth="[[bluetooth]]"
bluetooth-private="[[bluetoothPrivate]]">
</settings-bluetooth-subpage>
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
index e23ed90c9e1..6510e5472d5 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -32,11 +32,27 @@ Polymer({
notify: true,
},
- /** @private */
- bluetoothEnabled_: {
+ /**
+ * Reflects the current state of the toggle buttons (in this page and the
+ * subpage). This will be set when the adapter state change or when the user
+ * changes the toggle.
+ * @private
+ */
+ bluetoothToggleState_: {
type: Boolean,
- observer: 'bluetoothEnabledChanged_',
- notify: true,
+ observer: 'bluetoothToggleStateChanged_',
+ },
+
+ /**
+ * Set to true before the adapter state is received, when the adapter is
+ * unavailable, and while an adapter state change is requested. This
+ * prevents user changes while a change is in progress or when the adapter
+ * is not available.
+ * @private
+ */
+ bluetoothToggleDisabled_: {
+ type: Boolean,
+ value: true,
},
/**
@@ -111,7 +127,7 @@ Polymer({
* @private
*/
getIcon_: function() {
- if (!this.bluetoothEnabled_)
+ if (!this.bluetoothToggleState_)
return 'settings:bluetooth-disabled';
return 'settings:bluetooth';
},
@@ -134,15 +150,16 @@ Polymer({
*/
onBluetoothAdapterStateChanged_: function(state) {
this.adapterState_ = state;
- this.bluetoothEnabled_ = state.powered;
+ this.bluetoothToggleState_ = state.powered;
+ this.bluetoothToggleDisabled_ = !state.available;
},
/** @private */
onTap_: function() {
if (this.adapterState_.available === false)
return;
- if (!this.bluetoothEnabled_)
- this.bluetoothEnabled_ = true;
+ if (!this.bluetoothToggleState_)
+ this.bluetoothToggleState_ = true;
else
this.openSubpage_();
},
@@ -165,9 +182,14 @@ Polymer({
},
/** @private */
- bluetoothEnabledChanged_: function() {
+ bluetoothToggleStateChanged_: function() {
+ if (!this.adapterState_ || this.bluetoothToggleDisabled_ ||
+ this.bluetoothToggleState_ == this.adapterState_.powered) {
+ return;
+ }
+ this.bluetoothToggleDisabled_ = true;
this.bluetoothPrivate.setAdapterState(
- {powered: this.bluetoothEnabled_}, function() {
+ {powered: this.bluetoothToggleState_}, function() {
if (chrome.runtime.lastError) {
console.error(
'Error enabling bluetooth: ' +
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
index b3c703c233d..aa473836c54 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.html
@@ -34,26 +34,28 @@
</style>
<div class="settings-box first">
- <div id="onoff" class="start" on$="[[bluetoothEnabled]]">
- [[getOnOffString_(bluetoothEnabled,
+ <div id="onoff" class="start" on$="[[bluetoothToggleState]]">
+ [[getOnOffString_(bluetoothToggleState,
'$i18nPolymer{deviceOn}', '$i18nPolymer{deviceOff}')]]
</div>
- <paper-toggle-button id="enableBluetooth" checked="{{bluetoothEnabled}}"
+ <paper-toggle-button id="enableBluetooth"
+ checked="{{bluetoothToggleState}}"
+ disabled$="[[bluetoothToggleDisabled]]"
aria-label="$i18n{bluetoothToggleA11yLabel}">
</paper-toggle-button>
</div>
<!-- Paired device list -->
- <div class="settings-box first header" hidden$="[[!bluetoothEnabled]]">
+ <div class="settings-box first header" hidden="[[!bluetoothToggleState]]">
<div class="start">$i18n{bluetoothDeviceListPaired}</div>
</div>
<div id="noPairedDevices" class="list-frame"
- hidden$="[[!showNoDevices_(bluetoothEnabled, pairedDeviceList_)]]">
+ hidden="[[!showNoDevices_(bluetoothToggleState, pairedDeviceList_)]]">
$i18n{bluetoothNoDevices}
</div>
<div id="pairedContainer" class="container layout vertical"
scrollable on-device-event="onDeviceEvent_"
- hidden="[[!showDevices_(bluetoothEnabled, pairedDeviceList_)]]">
+ hidden="[[!showDevices_(bluetoothToggleState, pairedDeviceList_)]]">
<iron-list id="pairedDevices" class="vertical-list"
items="[[pairedDeviceList_]]"
selection-enabled selected-item="{{selectedPairedItem_}}"
@@ -67,18 +69,18 @@
</div>
<!-- Unpaired device list -->
- <div class="settings-box first header" hidden$="[[!bluetoothEnabled]]">
+ <div class="settings-box first header" hidden="[[!bluetoothToggleState]]">
<div class="start">$i18n{bluetoothDeviceListUnpaired}</div>
<paper-spinner active="[[showSpinner_]]">
</paper-spinner>
</div>
<div id="noUnpairedDevices" class="list-frame"
- hidden$="[[!showNoDevices_(bluetoothEnabled, unpairedDeviceList_)]]">
+ hidden="[[!showNoDevices_(bluetoothToggleState, unpairedDeviceList_)]]">
$i18n{bluetoothNoDevicesFound}
</div>
<div id="unpairedContainer" class="container layout vertical"
scrollable on-device-event="onDeviceEvent_"
- hidden="[[!showDevices_(bluetoothEnabled, unpairedDeviceList_)]]">
+ hidden="[[!showDevices_(bluetoothToggleState, unpairedDeviceList_)]]">
<iron-list id="unpairedDevices" class="vertical-list"
items="[[unpairedDeviceList_]]"
selection-enabled selected-item="{{selectedUnpairedItem_}}"
@@ -95,7 +97,7 @@
bluetooth-private="[[bluetoothPrivate]]"
dialog-id="[[dialogId_]]"
error-message="[[errorMessage_]]"
- on-close="onDialogClosed_"
+ on-close="onDialogClose_"
on-device-event="onDeviceEvent_"
pairing-device="[[pairingDevice_]]">
</bluetooth-device-dialog>
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
index bbff7a44432..1a11a1bc816 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
@@ -22,11 +22,14 @@ Polymer({
properties: {
/** Reflects the bluetooth-page property. */
- bluetoothEnabled: {
+ bluetoothToggleState: {
type: Boolean,
notify: true,
},
+ /** Reflects the bluetooth-page property. */
+ bluetoothToggleDisabled: Boolean,
+
/**
* The bluetooth adapter state, cached by bluetooth-page.
* @type {!chrome.bluetooth.AdapterState|undefined}
@@ -249,7 +252,7 @@ Polymer({
* @private
*/
updateDeviceList_: function() {
- if (!this.bluetoothEnabled) {
+ if (!this.bluetoothToggleState) {
this.deviceList_ = [];
return;
}
@@ -352,23 +355,23 @@ Polymer({
},
/**
- * @param {boolean} bluetoothEnabled
+ * @param {boolean} bluetoothToggleState
* @param {!Array<!chrome.bluetooth.Device>} deviceList
* @return {boolean}
* @private
*/
- showDevices_: function(bluetoothEnabled, deviceList) {
- return bluetoothEnabled && deviceList.length > 0;
+ showDevices_: function(bluetoothToggleState, deviceList) {
+ return bluetoothToggleState && deviceList.length > 0;
},
/**
- * @param {boolean} bluetoothEnabled
+ * @param {boolean} bluetoothToggleState
* @param {!Array<!chrome.bluetooth.Device>} deviceList
* @return {boolean}
* @private
*/
- showNoDevices_: function(bluetoothEnabled, deviceList) {
- return bluetoothEnabled && deviceList.length == 0;
+ showNoDevices_: function(bluetoothToggleState, deviceList) {
+ return bluetoothToggleState && deviceList.length == 0;
},
/**
@@ -462,8 +465,12 @@ Polymer({
},
/** @private */
- onDialogClosed_: function() {
+ onDialogClose_: function() {
this.dialogId_ = '';
this.pairingDevice_ = undefined;
+ // The list is dynamic so focus the first item.
+ var device = this.$$('#unpairedContainer bluetooth-device-list-item');
+ if (device)
+ device.focus();
},
});
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.html b/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.html
index e801dcb2386..d7a51a8a69d 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.html
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.html
@@ -12,6 +12,10 @@
<style include="settings-shared">
paper-checkbox {
display: block;
+ }
+
+ paper-checkbox,
+ #description {
margin: 15px 0;
}
</style>
@@ -20,7 +24,9 @@
<div class="title">$i18n{certificateManagerCaTrustEditDialogTitle}</div>
<div class="body">
<div>[[explanationText_]]</div>
- <div>$i18n{certificateManagerCaTrustEditDialogDescription}</div>
+ <div id="description">
+ $i18n{certificateManagerCaTrustEditDialogDescription}
+ </div>
<paper-checkbox id="ssl" checked="[[trustInfo_.ssl]]">
$i18n{certificateManagerCaTrustEditDialogSsl}
</paper-checkbox>
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.js
index 3045cc6f3cb..3139be38f91 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/ca_trust_edit_dialog.js
@@ -12,9 +12,6 @@ Polymer({
is: 'settings-ca-trust-edit-dialog',
properties: {
- /** @private {!settings.CertificatesBrowserProxy} */
- browserProxy_: Object,
-
/** @type {!CertificateSubnode|!NewCertificateSubNode} */
model: Object,
@@ -25,6 +22,9 @@ Polymer({
explanationText_: String,
},
+ /** @private {?settings.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
/** @override */
ready: function() {
this.browserProxy_ = settings.CertificatesBrowserProxyImpl.getInstance();
@@ -73,7 +73,7 @@ Polymer({
/** @param {!CertificatesError} error */
function(error) {
/** @type {!CrDialogElement} */ (this.$.dialog).close();
- this.fire('certificates-error', error);
+ this.fire('certificates-error', {error: error, anchor: null});
}.bind(this));
},
});
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_delete_confirmation_dialog.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_delete_confirmation_dialog.js
index b2e267c1fdd..0ed718010ad 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_delete_confirmation_dialog.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_delete_confirmation_dialog.js
@@ -10,9 +10,6 @@ Polymer({
is: 'settings-certificate-delete-confirmation-dialog',
properties: {
- /** @private {!settings.CertificatesBrowserProxy} */
- browserProxy_: Object,
-
/** @type {!CertificateSubnode} */
model: Object,
@@ -20,6 +17,9 @@ Polymer({
certificateType: String,
},
+ /** @private {?settings.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
/** @override */
ready: function() {
this.browserProxy_ = settings.CertificatesBrowserProxyImpl.getInstance();
@@ -89,7 +89,7 @@ Polymer({
/** @param {!CertificatesError} error */
function(error) {
/** @type {!CrDialogElement} */ (this.$.dialog).close();
- this.fire('certificates-error', error);
+ this.fire('certificates-error', {error: error, anchor: null});
}.bind(this));
},
});
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_entry.html b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_entry.html
index ee0f93a79cb..31cb15c857e 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_entry.html
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_entry.html
@@ -14,8 +14,8 @@
alt="$i18n{certificateManagerExpandA11yLabel}">
</cr-expand-button>
</div>
- <iron-collapse opened="[[expanded_]]" no-animation>
- <template is="dom-if" if="[[expanded_]]">
+ <template is="dom-if" if="[[expanded_]]">
+ <iron-collapse opened="[[expanded_]]" no-animation>
<div class="list-frame">
<template is="dom-repeat" items="[[model.subnodes]]">
<settings-certificate-subentry model="[[item]]"
@@ -24,8 +24,8 @@
</settings-certificate-subentry>
</template>
</div>
- </template>
- <iron-collapse>
+ <iron-collapse>
+ </template>
</template>
<script src="certificate_entry.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_list.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_list.js
index 82b261fd8cd..f13138a08f5 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_list.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_list.js
@@ -64,10 +64,11 @@ Polymer({
/**
* Handles a rejected Promise returned from |browserProxy_|.
+ * @param {!HTMLElement} anchor
* @param {*} error Expects {!CertificatesError|!CertificatesImportError}.
* @private
*/
- onRejected_: function(error) {
+ onRejected_: function(anchor, error) {
if (error === null) {
// Nothing to do here. Null indicates that the user clicked "cancel" on
// a native file chooser dialog.
@@ -76,58 +77,69 @@ Polymer({
// Otherwise propagate the error to the parents, such that a dialog
// displaying the error will be shown.
- this.fire('certificates-error', error);
+ this.fire('certificates-error', {error: error, anchor: anchor});
},
/**
* @param {?NewCertificateSubNode} subnode
+ * @param {!HTMLElement} anchor
* @private
*/
- dispatchImportActionEvent_: function(subnode) {
+ dispatchImportActionEvent_: function(subnode, anchor) {
this.fire(
settings.CertificateActionEvent,
/** @type {!CertificateActionEventDetail} */ ({
action: CertificateAction.IMPORT,
subnode: subnode,
certificateType: this.certificateType,
+ anchor: anchor,
}));
},
- /** @private */
- onImportTap_: function() {
- this.handleImport_(false);
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onImportTap_: function(e) {
+ this.handleImport_(false, /** @type {!HTMLElement} */ (
+ Polymer.dom(e).localTarget));
},
// <if expr="chromeos">
- /** @private */
- onImportAndBindTap_: function() {
- this.handleImport_(true);
+ /**
+ * @private
+ * @param {!Event} e
+ */
+ onImportAndBindTap_: function(e) {
+ this.handleImport_(true, /** @type {!HTMLElement} */ (
+ Polymer.dom(e).localTarget));
},
// </if>
/**
* @param {boolean} useHardwareBacked
+ * @param {!HTMLElement} anchor
* @private
*/
- handleImport_: function(useHardwareBacked) {
+ handleImport_: function(useHardwareBacked, anchor) {
var browserProxy = settings.CertificatesBrowserProxyImpl.getInstance();
if (this.certificateType == CertificateType.PERSONAL) {
browserProxy.importPersonalCertificate(useHardwareBacked).then(
function(showPasswordPrompt) {
if (showPasswordPrompt)
- this.dispatchImportActionEvent_(null);
+ this.dispatchImportActionEvent_(null, anchor);
}.bind(this),
- this.onRejected_.bind(this));
+ this.onRejected_.bind(this, anchor));
} else if (this.certificateType == CertificateType.CA) {
browserProxy.importCaCertificate().then(
function(certificateName) {
- this.dispatchImportActionEvent_({name: certificateName});
+ this.dispatchImportActionEvent_({name: certificateName}, anchor);
}.bind(this),
- this.onRejected_.bind(this));
+ this.onRejected_.bind(this, anchor));
} else if (this.certificateType == CertificateType.SERVER) {
browserProxy.importServerCertificate().catch(
- this.onRejected_.bind(this));
+ this.onRejected_.bind(this, anchor));
} else {
assertNotReached();
}
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_page.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_page.js
index afa70a9b5d8..d48ce13c304 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_page.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_page.js
@@ -82,6 +82,13 @@ Polymer({
* @private {null|!CertificatesError|!CertificatesImportError}
*/
errorDialogModel_: Object,
+
+ /**
+ * The element to return focus to, when the currently shown dialog is
+ * closed.
+ * @private {?HTMLElement}
+ */
+ activeDialogAnchor_: Object,
},
/** @override */
@@ -110,25 +117,28 @@ Polymer({
if (event.detail.certificateType == CertificateType.PERSONAL) {
this.openDialog_(
'settings-certificate-password-decryption-dialog',
- 'showPasswordDecryptionDialog_');
+ 'showPasswordDecryptionDialog_',
+ event.detail.anchor);
} else if (event.detail.certificateType ==
CertificateType.CA) {
this.openDialog_(
- 'settings-ca-trust-edit-dialog', 'showCaTrustEditDialog_');
+ 'settings-ca-trust-edit-dialog', 'showCaTrustEditDialog_',
+ event.detail.anchor);
}
} else {
if (event.detail.action == CertificateAction.EDIT) {
this.openDialog_(
- 'settings-ca-trust-edit-dialog', 'showCaTrustEditDialog_');
+ 'settings-ca-trust-edit-dialog', 'showCaTrustEditDialog_',
+ event.detail.anchor);
} else if (event.detail.action == CertificateAction.DELETE) {
this.openDialog_(
'settings-certificate-delete-confirmation-dialog',
- 'showDeleteConfirmationDialog_');
+ 'showDeleteConfirmationDialog_', event.detail.anchor);
} else if (event.detail.action ==
CertificateAction.EXPORT_PERSONAL) {
this.openDialog_(
'settings-certificate-password-encryption-dialog',
- 'showPasswordEncryptionDialog_');
+ 'showPasswordEncryptionDialog_', event.detail.anchor);
}
}
@@ -136,10 +146,12 @@ Polymer({
}.bind(this));
this.addEventListener('certificates-error', function(event) {
- this.errorDialogModel_ = event.detail;
+ var detail = /** @type {!CertificatesErrorEventDetail} */ (event.detail);
+ this.errorDialogModel_ = detail.error;
this.openDialog_(
'settings-certificates-error-dialog',
- 'showErrorDialog_');
+ 'showErrorDialog_',
+ detail.anchor);
event.stopPropagation();
}.bind(this));
},
@@ -152,14 +164,22 @@ Polymer({
* @param {string} dialogTagName The tag name of the dialog to be shown.
* @param {string} domIfBooleanName The name of the boolean variable
* corresponding to the dialog.
+ * @param {?HTMLElement} anchor The element to focus when the dialog is
+ * closed. If null, the previous anchor element should be reused. This
+ * happens when a 'settings-certificates-error-dialog' is opened,
+ * which when closed should focus the anchor of the previous dialog (the
+ * one that generated the error).
* @private
*/
- openDialog_: function(dialogTagName, domIfBooleanName) {
+ openDialog_: function(dialogTagName, domIfBooleanName, anchor) {
+ if (anchor)
+ this.activeDialogAnchor_ = anchor;
this.set(domIfBooleanName, true);
this.async(function() {
var dialog = this.$$(dialogTagName);
dialog.addEventListener('close', function() {
this.set(domIfBooleanName, false);
+ this.activeDialogAnchor_.focus();
}.bind(this));
}.bind(this));
},
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_types.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_types.js
index 44c397c5a18..6063848b6a0 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_types.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_types.js
@@ -7,17 +7,26 @@
*/
/**
- * The payload of the certificate-action event that is emitted from this
- * component.
+ * The payload of the 'certificate-action' event.
* @typedef {{
* action: !CertificateAction,
* subnode: (null|CertificateSubnode|NewCertificateSubNode),
- * certificateType: !CertificateType
+ * certificateType: !CertificateType,
+ * anchor: !HTMLElement
* }}
*/
var CertificateActionEventDetail;
/**
+ * The payload of the 'certificates-error' event.
+ * @typedef {{
+ * error: (null|CertificatesError|CertificatesImportError),
+ * anchor: ?HTMLElement
+ * }}
+ */
+var CertificatesErrorEventDetail;
+
+/**
* Enumeration of actions that require a popup menu to be shown to the user.
* @enum {number}
*/
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.html b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.html
index cc87a2ebb17..0dc89c87137 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.html
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.html
@@ -13,16 +13,14 @@
<div class="title">$i18n{certificateManagerDecryptPasswordTitle}</div>
<div class="body">
<paper-input type="password" id="password"
- label="$i18n{certificateManagerPassword}"
- value="{{password_}}" on-keypress="onKeypress_">
+ label="$i18n{certificateManagerPassword}" value="{{password_}}">
</paper-input>
</div>
<div class="button-container">
<paper-button class="cancel-button" on-tap="onCancelTap_">
$i18n{cancel}
</paper-button>
- <paper-button id="ok" class="action-button" on-tap="onOkTap_"
- disabled="[[!password_.length]]">
+ <paper-button id="ok" class="action-button" on-tap="onOkTap_">
$i18n{ok}
</paper-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.js
index 6232fc2d1ea..3ecc2f0aa11 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_decryption_dialog.js
@@ -10,9 +10,6 @@ Polymer({
is: 'settings-certificate-password-decryption-dialog',
properties: {
- /** @private {!settings.CertificatesBrowserProxy} */
- browserProxy_: Object,
-
/** @private */
password_: {
type: String,
@@ -20,6 +17,9 @@ Polymer({
},
},
+ /** @private {?settings.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
/** @override */
ready: function() {
this.browserProxy_ = settings.CertificatesBrowserProxyImpl.getInstance();
@@ -45,16 +45,7 @@ Polymer({
/** @param {!CertificatesError} error */
function(error) {
/** @type {!CrDialogElement} */ (this.$.dialog).close();
- this.fire('certificates-error', error);
+ this.fire('certificates-error', {error: error, anchor: null});
}.bind(this));
},
-
- /**
- * @param {!KeyboardEvent} e
- * @private
- */
- onKeypress_: function(e) {
- if (e.key == 'Enter' && !this.$.ok.disabled)
- this.onOkTap_();
- },
});
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.html b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.html
index 95da2bf58b6..a1b6c26b677 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.html
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.html
@@ -17,7 +17,7 @@
<div class="title">$i18n{certificateManagerEncryptPasswordTitle}</div>
<div class="body">
<div>$i18n{certificateManagerEncryptPasswordDescription}</div>
- <div class="password-buttons" on-keypress="onKeypress_">
+ <div class="password-buttons">
<paper-input type="password" value="{{password_}}" id="password"
label="$i18n{certificateManagerPassword}"
on-input="validate_"></paper-input>
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.js
index dc64b96bfe2..a768879d0df 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_password_encryption_dialog.js
@@ -10,9 +10,6 @@ Polymer({
is: 'settings-certificate-password-encryption-dialog',
properties: {
- /** @private {!settings.CertificatesBrowserProxy} */
- browserProxy_: Object,
-
/** @type {!CertificateSubnode} */
model: Object,
@@ -29,6 +26,9 @@ Polymer({
},
},
+ /** @private {?settings.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
/** @override */
ready: function() {
this.browserProxy_ = settings.CertificatesBrowserProxyImpl.getInstance();
@@ -54,19 +54,10 @@ Polymer({
/** @param {!CertificatesError} error */
function(error) {
this.$.dialog.close();
- this.fire('certificates-error', error);
+ this.fire('certificates-error', {error: error, anchor: null});
}.bind(this));
},
- /**
- * @param {!KeyboardEvent} e
- * @private
- */
- onKeypress_: function(e) {
- if (e.key == 'Enter' && !this.$.ok.disabled)
- this.onOkTap_();
- },
-
/** @private */
validate_: function() {
var isValid = this.password_ != '' &&
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.js b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.js
index 715320dd05a..cd76f4b9d55 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.js
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.js
@@ -51,6 +51,7 @@ Polymer({
action: action,
subnode: this.model,
certificateType: this.certificateType,
+ anchor: this.$.dots,
}));
},
@@ -69,7 +70,7 @@ Polymer({
// Otherwise propagate the error to the parents, such that a dialog
// displaying the error will be shown.
- this.fire('certificates-error', error);
+ this.fire('certificates-error', {error: error, anchor: this.$.dots});
},
/**
@@ -158,6 +159,6 @@ Polymer({
onDotsTap_: function() {
var actionMenu = /** @type {!CrActionMenuElement} */(
this.$.menu.get());
- actionMenu.showAt(assert(this.$$('paper-icon-button')));
+ actionMenu.showAt(this.$.dots);
},
});
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
index 93472c082c9..057a6ff63fa 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -18,12 +18,6 @@
visibility: hidden;
}
- #dialog .button-container {
- border-top: 1px solid rgba(0, 0, 0, 0.14);
- margin-top: 0;
- padding-top: 10px;
- }
-
#dialog .footer {
color: var(--paper-grey-600);
}
@@ -40,6 +34,13 @@
margin-top: auto;
}
+ settings-checkbox {
+ --settings-row-two-line-min-height: 48px;
+ --settings-checkbox-label: {
+ line-height: 1.25rem;
+ };
+ }
+
#generalFooter {
margin: 0;
min-height: 18px;
@@ -89,22 +90,23 @@
* Replace the bottom margin with padding to avoid the gap between
* the scrollbar and the bottom separator. */
@media all and (max-height: 724px) {
- #dialog .body {
- margin-bottom: 0;
+ #dialog {
/* crbug.com/652027: Show four and a *half* items in the list. */
- max-height: 280px;
- overflow-y: scroll;
- padding-bottom: 12px;
+ --cr-dialog-body-container: {
+ max-height: 280px;
+ };
}
}
</style>
- <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}" ignore-popstate>
+ <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"
+ show-scroll-borders ignore-popstate>
<div class="title">$i18n{clearBrowsingData}</div>
<div class="body">
<div class="row">
$i18n{clearFollowingItemsFrom}
<settings-dropdown-menu id="clearFrom"
+ label="$i18n{clearFollowingItemsFrom}"
pref="{{prefs.browser.clear_data.time_period}}"
menu-options="[[clearFromOptions_]]">
</settings-dropdown-menu>
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html
index 43b2a944b1f..2fec2c47f6e 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.html
@@ -4,11 +4,7 @@
<dom-module id="settings-history-deletion-dialog">
<template>
- <style include="settings-shared">
- #dialog .body {
- margin-bottom: 50px;
- }
- </style>
+ <style include="settings-shared"></style>
<dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
<div class="title">$i18n{historyDeletionDialogTitle}</div>
diff --git a/chromium/chrome/browser/resources/settings/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
index b8b4242c72a..ed5c8767ee8 100644
--- a/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
@@ -22,9 +22,9 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'focusable_iron_list_item_behavior',
+ 'target_name': 'focus_row_behavior',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr'
+ '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_row',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -48,6 +48,7 @@
'target_name': 'route',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp
index 66451b29fc8..59d1cac43a6 100644
--- a/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp
@@ -15,6 +15,7 @@
{
'target_name': 'controlled_radio_button',
'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(EXTERNS_GYP):settings_private',
'../prefs/compiled_resources2.gyp:pref_util',
@@ -58,6 +59,8 @@
{
'target_name': 'settings_dropdown_menu',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_pref_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
@@ -68,25 +71,22 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'settings_input',
+ 'target_name': 'settings_radio_group',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior',
- '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_pref_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(EXTERNS_GYP):settings_private',
+ '../prefs/compiled_resources2.gyp:pref_util',
'pref_control_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'settings_radio_group',
+ 'target_name': 'settings_slider',
'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-slider/compiled_resources2.gyp:paper-slider-extracted',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_pref_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- '<(EXTERNS_GYP):settings_private',
- '../prefs/compiled_resources2.gyp:pref_util',
- 'pref_control_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/settings/controls/controlled_button.html b/chromium/chrome/browser/resources/settings/controls/controlled_button.html
index b053b266077..ddad0bd7895 100644
--- a/chromium/chrome/browser/resources/settings/controls/controlled_button.html
+++ b/chromium/chrome/browser/resources/settings/controls/controlled_button.html
@@ -16,7 +16,7 @@
--justify-margin: 18px;
}
- :host([controlled_]) {
+ :host([enforced_]) {
/* Disable pointer events for this whole element, as outer on-tap gets
* triggered when clicking/tapping anywhere in :host. */
pointer-events: none;
@@ -38,12 +38,11 @@
}
</style>
- <paper-button disabled="[[controlled_]]">
- <content></content>
- </paper-button>
+ <paper-button disabled="[[enforced_]]">[[label]]</paper-button>
<template is="dom-if" if="[[hasPrefPolicyIndicator(pref.*)]]" restamp>
- <cr-policy-pref-indicator pref="[[pref]]" on-tap="onIndicatorTap_">
+ <cr-policy-pref-indicator pref="[[pref]]" on-tap="onIndicatorTap_"
+ icon-aria-label="[[label]]">
</cr-policy-pref-indicator>
</template>
diff --git a/chromium/chrome/browser/resources/settings/controls/controlled_button.js b/chromium/chrome/browser/resources/settings/controls/controlled_button.js
index a1188763ef8..307475678a9 100644
--- a/chromium/chrome/browser/resources/settings/controls/controlled_button.js
+++ b/chromium/chrome/browser/resources/settings/controls/controlled_button.js
@@ -17,23 +17,17 @@ Polymer({
reflectToAttribute: true,
},
+ label: String,
+
/** @private */
- controlled_: {
+ enforced_: {
type: Boolean,
- computed: 'computeControlled_(pref.*)',
+ computed: 'isPrefEnforced(pref.*)',
reflectToAttribute: true,
},
},
/**
- * @return {boolean} Whether the button is disabled.
- * @private
- */
- computeControlled_: function() {
- return this.pref.enforcement == chrome.settingsPrivate.Enforcement.ENFORCED;
- },
-
- /**
* @param {!Event} e
* @private
*/
diff --git a/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html b/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html
index 90c000b300d..c19f779f335 100644
--- a/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html
+++ b/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html
@@ -1,6 +1,6 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="pref_control_behavior.html">
<link rel="import" href="../prefs/pref_util.html">
<link rel="import" href="../settings_shared_css.html">
@@ -9,36 +9,126 @@
<template>
<style include="settings-shared">
:host {
+ --ink-to-circle: calc((var(--paper-radio-button-ink-size) -
+ var(--paper-radio-button-size)) / 2);
+ @apply(--settings-actionable);
align-items: center;
display: flex;
outline: none;
}
- #radioButton {
+ #labelWrapper {
+ -webkit-margin-start: var(--paper-radio-button-label-spacing, 10px);
flex: 1;
}
+ #label {
+ color: var(--paper-radio-button-label-color, --primary-text-color);
+ }
+
+ .circle,
+ .disc,
+ .disc-wrapper,
+ paper-ripple {
+ border-radius: 50%;
+ }
+
+ .disc-wrapper {
+ height: var(--paper-radio-button-ink-size);
+ margin: 0 calc(-1 * var(--ink-to-circle));
+ position: relative;
+ width: var(--paper-radio-button-ink-size);
+ }
+
+ .circle,
+ .disc {
+ box-sizing: border-box;
+ height: var(--paper-radio-button-size);
+ left: var(--ink-to-circle);
+ position: absolute;
+ top: var(--ink-to-circle);
+ width: var(--paper-radio-button-size);
+ }
+
+ .circle {
+ border: 2px solid var(--paper-radio-button-unchecked-color,
+ --primary-text-color);
+ }
+
+ :host([checked]) .circle {
+ border-color: var(--paper-radio-button-checked-color, --primary-color);
+ }
+
+ .disc {
+ background-color: var(--paper-radio-button-unchecked-background-color,
+ transparent);
+ transform: scale(0);
+ transition: border-color 200ms, transform 200ms;
+ }
+
+ :host([checked]) .disc {
+ background-color: var(--paper-radio-button-checked-color,
+ --primary-color);
+ transform: scale(0.5);
+ }
+
+ paper-ripple {
+ color: var(--paper-radio-button-unchecked-ink-color,
+ --primary-text-color);
+ opacity: .6;
+ }
+
+ :host([checked]) paper-ripple {
+ color: var(--paper-radio-button-checked-ink-color,
+ --primary-text-color);
+ }
+
:host([controlled_]) {
/* Disable pointer events for this whole element, as outer on-tap gets
* triggered when clicking/tapping anywhere in :host. */
pointer-events: none;
}
+ :host([controlled_]) :-webkit-any(.circle, .disc) {
+ opacity: .5;
+ }
+
+ :host([controlled_]) .circle {
+ border-color: var(--paper-radio-button-unchecked-color,
+ --primary-text-color);
+ }
+
+ :host([controlled_][checked]) .disc {
+ background-color: var(--paper-radio-button-unchecked-color,
+ --primary-text-color);
+ }
+
+ :host([controlled_]) #labelWrapper {
+ opacity: .65;
+ }
+
cr-policy-pref-indicator {
- -webkit-margin-start: var(--checkbox-spacing);
+ -webkit-margin-start: var(--settings-control-spacing);
/* Enable pointer events for the indicator so :hover works. Disable
* clicks/taps via onIndicatorTap_ so outer on-tap doesn't trigger. */
pointer-events: all;
}
</style>
- <paper-radio-button id="radioButton" name="{{name}}" checked="{{checked}}"
- disabled="[[controlled_]]" tabindex$="[[tabindex]]">
+ <div class="disc-wrapper">
+ <div class="circle"></div>
+ <div class="disc"></div>
+ <paper-ripple center hold-down="[[pressed_]]"></paper-ripple>
+ </div>
+
+ <div id="labelWrapper">
+ <span id="label" hidden$="[[!label]]">[[label]]</span>
<content></content>
- </paper-radio-button>
+ </div>
<template is="dom-if" if="[[showIndicator_(controlled_, name, pref.*)]]">
- <cr-policy-pref-indicator pref="[[pref]]" on-tap="onIndicatorTap_">
+ <cr-policy-pref-indicator pref="[[pref]]" on-tap="onIndicatorTap_"
+ icon-aria-label="[[label]]">
</cr-policy-pref-indicator>
</template>
diff --git a/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.js b/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.js
index 39e5fbf1fbc..15e60dda7e8 100644
--- a/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.js
+++ b/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.js
@@ -5,9 +5,23 @@
Polymer({
is: 'controlled-radio-button',
- behaviors: [PrefControlBehavior],
+ behaviors: [
+ PrefControlBehavior,
+ Polymer.IronA11yKeysBehavior,
+ ],
properties: {
+ checked: {
+ type: Boolean,
+ reflectToAttribute: true,
+ observer: 'checkedChanged_',
+ },
+
+ label: {
+ type: String,
+ value: '', // Allows the hidden$= binding to run without being set.
+ },
+
name: {
type: String,
notify: true,
@@ -19,10 +33,34 @@ Polymer({
computed: 'computeControlled_(pref.*)',
reflectToAttribute: true,
},
+
+ /** @private */
+ pressed_: Boolean,
+ },
+
+ hostAttributes: {
+ role: 'radio',
+ tabindex: 0,
},
listeners: {
- 'focus': 'onFocus_',
+ 'blur': 'updatePressed_',
+ 'down': 'updatePressed_',
+ 'focus': 'updatePressed_',
+ 'tap': 'onTap_',
+ 'up': 'updatePressed_',
+ },
+
+ keyBindings: {
+ // This is mainly for screenreaders, which can perform actions on things
+ // that aren't focused (only focused things get synthetic click/tap events).
+ 'enter:keyup': 'click',
+ 'space:keyup': 'click',
+ },
+
+ /** @private */
+ checkedChanged_: function() {
+ this.setAttribute('aria-checked', this.checked ? 'true' : 'false');
},
/**
@@ -54,8 +92,17 @@ Polymer({
e.stopPropagation();
},
- /** Focuses the internal radio button when the row is selected. */
- onFocus_: function() {
- this.$.radioButton.focus();
+ /** @private */
+ onTap_: function() {
+ if (!this.controlled_)
+ this.checked = true;
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ updatePressed_: function(e) {
+ this.pressed_ = ['down', 'focus'].includes(e.type);
},
});
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.js b/chromium/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.js
index bae9955e8c3..0b45e03db70 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.js
+++ b/chromium/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.js
@@ -63,7 +63,6 @@ var SettingsBooleanControlBehaviorImpl = {
*/
numericUncheckedValue: {
type: Number,
- readOnly: true,
value: 0,
}
},
@@ -126,7 +125,7 @@ var SettingsBooleanControlBehaviorImpl = {
* @private
*/
controlDisabled_: function() {
- return this.disabled || this.isPrefPolicyControlled();
+ return this.disabled || this.isPrefEnforced();
},
};
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
index 4b31374fbf5..187a4030a97 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -27,18 +27,23 @@
}
cr-policy-pref-indicator {
- -webkit-margin-start: var(--checkbox-spacing);
+ -webkit-margin-start: var(--settings-control-spacing);
+ }
+
+ .label {
+ @apply(--settings-checkbox-label);
}
</style>
<div id="outerRow" noSubLabel$="[[!subLabel]]">
<paper-checkbox id="checkbox" checked="{{checked}}"
on-change="notifyChangedByUserInteraction"
disabled="[[controlDisabled_(disabled, pref.*)]]">
- <div>[[label]] <content></content></div>
- <div class="secondary">[[subLabel]]</div>
+ <div class="label">[[label]] <content></content></div>
+ <div class="secondary label">[[subLabel]]</div>
</paper-checkbox>
<template is="dom-if" if="[[pref.controlledBy]]">
- <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator>
+ <cr-policy-pref-indicator pref="[[pref]]" icon-aria-label="[[label]]">
+ </cr-policy-pref-indicator>
</template>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html b/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
index 6659294fdfd..c3fca94ba81 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
@@ -1,5 +1,7 @@
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
<link rel="import" href="pref_control_behavior.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../prefs/pref_util.html">
@@ -9,14 +11,26 @@
<dom-module id="settings-dropdown-menu">
<template>
<style include="settings-shared md-select">
+ :host {
+ display: inline-flex;
+ }
+
+ cr-policy-pref-indicator {
+ margin: 0 var(--settings-control-spacing);
+ }
+
/* Hide "Custom" value when unselectable. */
option:disabled {
display: none;
}
</style>
+ <template is="dom-if" if="[[pref.controlledBy]]" restamp>
+ <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator>
+ </template>
<div class="md-select-wrapper">
<select class="md-select" id="dropdownMenu" on-change="onChange_"
- disabled="[[shouldDisableMenu_(disabled, menuOptions)]]">
+ aria-label$="[[label]]"
+ disabled="[[shouldDisableMenu_(disabled, menuOptions, pref.*)]]">
<template is="dom-repeat" items="[[menuOptions]]">
<option value="[[item.value]]">[[item.name]]</option>
</template>
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js b/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
index aaf0834b585..4bc6c65582e 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
+++ b/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
@@ -29,6 +29,8 @@ var DropdownMenuOptionList;
Polymer({
is: 'settings-dropdown-menu',
+ behaviors: [CrPolicyPrefBehavior, PrefControlBehavior],
+
properties: {
/**
* List of options for the drop-down menu.
@@ -55,11 +57,10 @@ Polymer({
value: 'SETTINGS_DROPDOWN_NOT_FOUND_ITEM',
readOnly: true,
},
- },
- behaviors: [
- PrefControlBehavior,
- ],
+ /** Label for a11y purposes */
+ label: String,
+ },
observers: [
'updateSelected_(menuOptions, pref.value)',
@@ -125,7 +126,7 @@ Polymer({
* @private
*/
shouldDisableMenu_: function() {
- return this.disabled || this.menuOptions === null ||
- this.menuOptions.length == 0;
+ return this.disabled || this.isPrefEnforced() ||
+ this.menuOptions === null || this.menuOptions.length == 0;
},
});
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_idle_render.html b/chromium/chrome/browser/resources/settings/controls/settings_idle_load.html
index dda6b0a3455..c8a6b6a6713 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_idle_render.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_idle_load.html
@@ -1,3 +1,3 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<script src="settings_idle_render.js"></script>
+<script src="settings_idle_load.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_idle_load.js b/chromium/chrome/browser/resources/settings/controls/settings_idle_load.js
new file mode 100644
index 00000000000..3d741adb2cd
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/controls/settings_idle_load.js
@@ -0,0 +1,88 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * settings-idle-load is a simple variant of dom-if designed for lazy
+ * loading and rendering of elements that are accessed imperatively. A URL is
+ * given that holds the elements to be loaded lazily.
+ */
+Polymer({
+ is: 'settings-idle-load',
+ extends: 'template',
+
+ behaviors: [Polymer.Templatizer],
+
+ properties: {
+ /**
+ * If specified, it will be loaded via an HTML import before stamping the
+ * template.
+ */
+ url: String,
+ },
+
+ /** @private {TemplatizerNode} */
+ child_: null,
+
+ /** @private {number} */
+ idleCallback_: 0,
+
+ /** @override */
+ attached: function() {
+ this.idleCallback_ = requestIdleCallback(this.get.bind(this));
+ },
+
+ /** @override */
+ detached: function() {
+ // No-op if callback already fired.
+ cancelIdleCallback(this.idleCallback_);
+ },
+
+ /**
+ * @return {!Promise<Element>} Child element which has been stamped into the
+ * DOM tree.
+ */
+ get: function() {
+ if (this.loading_)
+ return this.loading_;
+
+ this.loading_ = new Promise(function(resolve, reject) {
+ this.importHref(this.url, function() {
+ assert(!this.ctor);
+ this.templatize(this);
+ assert(this.ctor);
+
+ var instance = this.stamp({});
+
+ assert(!this.child_);
+ this.child_ = instance.root.firstElementChild;
+
+ this.parentNode.insertBefore(instance.root, this);
+ resolve(this.child_);
+
+ this.fire('lazy-loaded');
+ }.bind(this), reject, true);
+ }.bind(this));
+
+ return this.loading_;
+ },
+
+ /**
+ * @param {string} prop
+ * @param {Object} value
+ */
+ _forwardParentProp: function(prop, value) {
+ if (this.child_)
+ this.child_._templateInstance[prop] = value;
+ },
+
+ /**
+ * @param {string} path
+ * @param {Object} value
+ */
+ _forwardParentPath: function(path, value) {
+ if (this.child_)
+ this.child_._templateInstance.notifyPath(path, value, true);
+ }
+});
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_idle_render.js b/chromium/chrome/browser/resources/settings/controls/settings_idle_render.js
deleted file mode 100644
index 8e224c9e541..00000000000
--- a/chromium/chrome/browser/resources/settings/controls/settings_idle_render.js
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview
- * settings-idle-render is a simple variant of dom-if designed for lazy
- * rendering of elements that are accessed imperatively.
- * If a use for idle time expansion is found outside of settings, this code
- * should be replaced by cr-lazy-render after that feature is merged into
- * ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.js
- */
-
-Polymer({
- is: 'settings-idle-render',
- extends: 'template',
-
- behaviors: [Polymer.Templatizer],
-
- /** @private {TemplatizerNode} */
- child_: null,
-
- /** @private {number} */
- idleCallback_: 0,
-
- /** @override */
- attached: function() {
- this.idleCallback_ = requestIdleCallback(this.render_.bind(this));
- },
-
- /** @override */
- detached: function() {
- // No-op if callback already fired.
- cancelIdleCallback(this.idleCallback_);
- },
-
- /**
- * Stamp the template into the DOM tree synchronously
- * @return {Element} Child element which has been stamped into the DOM tree.
- */
- get: function() {
- if (!this.child_)
- this.render_();
- return this.child_;
- },
-
- /** @private */
- render_: function() {
- if (!this.ctor)
- this.templatize(this);
- var parentNode = this.parentNode;
- if (parentNode && !this.child_) {
- var instance = this.stamp({});
- this.child_ = instance.root.firstElementChild;
- parentNode.insertBefore(instance.root, this);
- }
- },
-
- /**
- * @param {string} prop
- * @param {Object} value
- */
- _forwardParentProp: function(prop, value) {
- if (this.child_)
- this.child_._templateInstance[prop] = value;
- },
-
- /**
- * @param {string} path
- * @param {Object} value
- */
- _forwardParentPath: function(path, value) {
- if (this.child_)
- this.child_._templateInstance.notifyPath(path, value, true);
- }
-});
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_input.html b/chromium/chrome/browser/resources/settings/controls/settings_input.html
deleted file mode 100644
index 51bf0ee6759..00000000000
--- a/chromium/chrome/browser/resources/settings/controls/settings_input.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_behavior.html">
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
-<link rel="import" href="pref_control_behavior.html">
-
-<dom-module id="settings-input">
- <template>
- <style>
- :host {
- -webkit-margin-start: 4px;
- cursor: auto;
- display: inline-block;
- }
- </style>
- <div id="outerDiv" class="layout horizontal center">
- <paper-input id="input" auto-validate value="{{value}}"
- error-message="[[errorMessage]]" label="[[label]]"
- no-label-float="[[noLabelFloat]]" pattern="[[pattern]]"
- readonly$="[[readonly]]" required="[[required]]" type="[[type]]"
- on-change="onChange_" disabled="[[isDisabled_(disabled, pref.*)]]"
- stop-keyboard-event-propagation$="[[stopKeyboardEventPropagation]]"
- tabindex$="[[getTabindex_(canTab)]]">
- </paper-input>
- <template is="dom-if" if="[[pref.contolledBy]]">
- <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator>
- </template>
- </div>
- </template>
- <script src="settings_input.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_input.js b/chromium/chrome/browser/resources/settings/controls/settings_input.js
deleted file mode 100644
index 0bee8236aab..00000000000
--- a/chromium/chrome/browser/resources/settings/controls/settings_input.js
+++ /dev/null
@@ -1,128 +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.
-
-/**
- * @fileoverview
- * `settings-input` is a single-line text field for user input associated
- * with a pref value.
- */
-Polymer({
- is: 'settings-input',
-
- behaviors: [CrPolicyPrefBehavior, PrefControlBehavior],
-
- properties: {
- /**
- * The preference object to control.
- * @type {!chrome.settingsPrivate.PrefObject|undefined}
- * @override
- */
- pref: {
- observer: 'prefChanged_'
- },
-
- /* The current value of the input, reflected to/from |pref|. */
- value: {
- type: String,
- value: '',
- notify: true,
- },
-
- /* Set to true to disable editing the input. */
- disabled: {
- type: Boolean,
- value: false,
- reflectToAttribute: true
- },
-
- canTab: Boolean,
-
- /* Properties for paper-input. This is not strictly necessary.
- * Though it does define the types for the closure compiler. */
- errorMessage: { type: String },
- label: { type: String },
- noLabelFloat: { type: Boolean, value: false },
- pattern: { type: String },
- readonly: { type: Boolean, value: false },
- required: { type: Boolean, value: false },
- stopKeyboardEventPropagation: { type: Boolean, value: false },
- type: { type: String },
- },
-
- /**
- * Focuses the 'input' element.
- */
- focus: function() {
- this.$.input.focus();
- },
-
- /**
- * Polymer changed observer for |pref|.
- * @private
- */
- prefChanged_: function() {
- if (!this.pref)
- return;
-
- // Ignore updates while the input is focused so that user input is not
- // overwritten.
- if (this.$.input.focused)
- return;
-
- if (this.pref.type == chrome.settingsPrivate.PrefType.NUMBER) {
- this.value = this.pref.value.toString();
- } else {
- assert(this.pref.type == chrome.settingsPrivate.PrefType.STRING ||
- this.pref.type == chrome.settingsPrivate.PrefType.URL);
- this.value = /** @type {string} */(this.pref.value);
- }
- },
-
- /**
- * Gets a tab index for this control if it can be tabbed to.
- * @param {boolean} canTab
- * @return {number}
- * @private
- */
- getTabindex_: function(canTab) {
- return canTab ? 0 : -1;
- },
-
- /**
- * Change event handler for paper-input. Updates the pref value.
- * settings-input uses the change event because it is fired by the Enter key.
- * @private
- */
- onChange_: function() {
- if (!this.pref)
- return;
-
- if (this.pref.type == chrome.settingsPrivate.PrefType.NUMBER) {
- if (!this.value) {
- // Ignore empty input field and restore value.
- this.value = this.pref.value.toString();
- return;
- }
- var n = parseInt(this.value, 10);
- if (isNaN(n)) {
- console.error('Bad value for numerical pref: ' + this.value);
- return;
- }
- this.set('pref.value', n);
- } else {
- assert(this.pref.type == chrome.settingsPrivate.PrefType.STRING ||
- this.pref.type == chrome.settingsPrivate.PrefType.URL);
- this.set('pref.value', this.value);
- }
- },
-
- /**
- * @param {boolean} disabled
- * @return {boolean} Whether the element should be disabled.
- * @private
- */
- isDisabled_: function(disabled) {
- return disabled || this.isPrefPolicyControlled();
- },
-});
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_radio_group.js b/chromium/chrome/browser/resources/settings/controls/settings_radio_group.js
index f0bedec092b..c56d803f686 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_radio_group.js
+++ b/chromium/chrome/browser/resources/settings/controls/settings_radio_group.js
@@ -28,6 +28,10 @@ Polymer({
},
},
+ hostAttributes: {
+ role: 'none',
+ },
+
observers: [
'prefChanged_(pref.*)',
],
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_slider.html b/chromium/chrome/browser/resources/settings/controls/settings_slider.html
new file mode 100644
index 00000000000..e80d1caea85
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/controls/settings_slider.html
@@ -0,0 +1,74 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_behavior.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-slider/paper-slider.html">
+
+<dom-module id="settings-slider">
+ <template>
+ <style>
+ :host {
+ display: inline-flex;
+ }
+
+ cr-policy-pref-indicator {
+ -webkit-margin-start: var(--settings-control-spacing);
+ align-self: center;
+ }
+
+ #labels[disabled] {
+ color: var(--paper-grey-400);
+ }
+
+ div.outer {
+ align-items: stretch;
+ display: flex;
+ flex-direction: column;
+ margin: 8px 0;
+ min-width: 200px;
+ }
+
+ #labels {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ margin: -4px 16px 0 16px;
+ }
+
+ #labels > div {
+ font-size: 12px;
+ }
+
+ #label-begin {
+ -webkit-margin-end: 4px;
+ }
+
+ #label-end {
+ -webkit-margin-begin: 4px;
+ }
+
+ paper-slider {
+ /* Make the slider bar always grey. */
+ --paper-slider-active-color: var(--paper-grey-400);
+ /* Make the knob always blue. */
+ --paper-slider-knob-start-color: var(--google-blue-700);
+ --paper-slider-knob-start-border-color: var(--google-blue-700);
+ width: 100%;
+ }
+ </style>
+ <template is="dom-if" if="[[pref.controlledBy]]" restamp>
+ <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator>
+ </template>
+ <div class="outer">
+ <paper-slider id="slider"
+ disabled$="[[disableSlider_]]" snaps
+ on-immediate-value-changed="onSliderChanged_" max="[[max]]"
+ min="[[min]]">
+ </paper-slider>
+ <div id="labels" disabled$="[[disableSlider_]]">
+ <div id="label-begin">[[labelMin]]</div>
+ <div id="label-end">[[labelMax]]</div>
+ </div>
+ </div>
+ </template>
+ <script src="settings_slider.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_slider.js b/chromium/chrome/browser/resources/settings/controls/settings_slider.js
new file mode 100644
index 00000000000..1d7e2a94372
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/controls/settings_slider.js
@@ -0,0 +1,139 @@
+// 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.
+
+/**
+ * @fileoverview
+ * settings-slider wraps a paper-slider. It maps the slider's values from a
+ * linear UI range to a range of real values. When |value| does not map exactly
+ * to a tick mark, it interpolates to the nearest tick.
+ *
+ * Unlike paper-slider, there is no distinction between value and
+ * immediateValue; when either changes, the |value| property is updated.
+ */
+Polymer({
+ is: 'settings-slider',
+
+ behaviors: [CrPolicyPrefBehavior],
+
+ properties: {
+ /** @type {!chrome.settingsPrivate.PrefObject} */
+ pref: Object,
+
+ /** @type {!Array<number>} Values corresponding to each tick. */
+ tickValues: {type: Array, value: []},
+
+ min: Number,
+
+ max: Number,
+
+ labelMin: String,
+
+ labelMax: String,
+
+ disabled: Boolean,
+
+ /** @private */
+ disableSlider_: {
+ computed: 'computeDisableSlider_(pref.*, disabled)',
+ type: Boolean,
+ },
+ },
+
+ observers: [
+ 'valueChanged_(pref.*, tickValues.*)',
+ ],
+
+ /**
+ * Sets the |pref.value| property to the value corresponding to the knob
+ * position after a user action.
+ * @private
+ */
+ onSliderChanged_: function() {
+ var sliderValue = isNaN(this.$.slider.immediateValue)
+ ? this.$.slider.value
+ : this.$.slider.immediateValue;
+
+ var newValue;
+ if (this.tickValues && this.tickValues.length > 0)
+ newValue = this.tickValues[sliderValue];
+ else
+ newValue = sliderValue;
+
+ this.set('pref.value', newValue);
+ },
+
+ /** @private */
+ computeDisableSlider_: function() {
+ return this.disabled || this.isPrefEnforced();
+ },
+
+ /**
+ * Updates the knob position when |pref.value| changes. If the knob is still
+ * being dragged, this instead forces |pref.value| back to the current
+ * position.
+ * @private
+ */
+ valueChanged_: function() {
+ // If |tickValues| is empty, simply set current value to the slider.
+ if (this.tickValues.length == 0) {
+ this.$.slider.value = this.pref.value;
+ return;
+ }
+
+ // First update the slider settings if |tickValues| was set.
+ var numTicks = Math.max(1, this.tickValues.length);
+ this.$.slider.max = numTicks - 1;
+ // Limit the number of ticks to 10 to keep the slider from looking too busy.
+ /** @const */ var MAX_TICKS = 10;
+ this.$.slider.snaps = numTicks < MAX_TICKS;
+ this.$.slider.maxMarkers = numTicks < MAX_TICKS ? numTicks : 0;
+
+ if (this.$.slider.dragging && this.tickValues.length > 0 &&
+ this.pref.value != this.tickValues[this.$.slider.immediateValue]) {
+ // The value changed outside settings-slider but we're still holding the
+ // knob, so set the value back to where the knob was.
+ // Async so we don't confuse Polymer's data binding.
+ this.async(function() {
+ var newValue = this.tickValues[this.$.slider.immediateValue];
+ this.set('pref.value', newValue);
+ });
+ return;
+ }
+
+ // Convert from the public |value| to the slider index (where the knob
+ // should be positioned on the slider).
+ var sliderIndex = this.tickValues.length > 0 ?
+ this.tickValues.indexOf(/** @type {number} */ (this.pref.value)) :
+ 0;
+ if (sliderIndex == -1) {
+ // No exact match.
+ sliderIndex = this.findNearestIndex_(
+ this.tickValues,
+ /** @type {number} */ (this.pref.value));
+ }
+ this.$.slider.value = sliderIndex;
+ },
+
+ /**
+ * Returns the index of the item in |arr| closest to |value|.
+ * @param {!Array<number>} arr
+ * @param {number} value
+ * @return {number}
+ * @private
+ */
+ findNearestIndex_: function(arr, value) {
+ var closestIndex;
+ var minDifference = Number.MAX_VALUE;
+ for (var i = 0; i < arr.length; i++) {
+ var difference = Math.abs(arr[i] - value);
+ if (difference < minDifference) {
+ closestIndex = i;
+ minDifference = difference;
+ }
+ }
+
+ assert(typeof closestIndex != 'undefined');
+ return closestIndex;
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
index 22e2bb5e9b0..554613fe015 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
@@ -28,29 +28,27 @@
min-height: var(--settings-row-min-height);
}
- paper-toggle-button,
+ #labelWrapper,
+ ::content .more-actions,
cr-policy-pref-indicator {
- -webkit-margin-start: var(--checkbox-spacing);
- }
-
- ::content .more-actions {
- -webkit-margin-end: 10px;
+ -webkit-margin-end: var(--settings-control-spacing);
}
</style>
<div id="outerRow" noSubLabel$="[[!subLabel]]">
- <div class="flex" on-tap="onLabelWrapperTap_"
- actionable$="[[!controlDisabled_(disabled, pref.*)]]">
- <div id="label" class="label">
- [[label]]
- </div>
- <div class="secondary label">[[subLabel]]</div>
+ <div class="flex" id="labelWrapper" on-tap="onLabelWrapperTap_"
+ actionable$="[[!controlDisabled_(disabled, pref.*)]]"
+ hidden="[[!label]]">
+ <div id="label" class="label">[[label]]</div>
+ <div id="subLabel" class="secondary label">[[subLabel]]</div>
</div>
<content select=".more-actions"></content>
- <template is="dom-if" if="[[pref.controlledBy]]" restamp>
- <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator>
+ <template is="dom-if" if="[[hasPrefPolicyIndicator(pref.*)]]">
+ <cr-policy-pref-indicator pref="[[pref]]" icon-aria-label="[[label]]">
+ </cr-policy-pref-indicator>
</template>
<paper-toggle-button id="control" checked="{{checked}}"
on-change="notifyChangedByUserInteraction" aria-labelledby="label"
+ aria-describedby="subLabel"
disabled="[[controlDisabled_(disabled, pref)]]">
</paper-toggle-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp
index 04756b71421..0da9b331bfe 100644
--- a/chromium/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/date_time_page/compiled_resources2.gyp
@@ -9,6 +9,7 @@
'../controls/compiled_resources2.gyp:settings_dropdown_menu',
'../prefs/compiled_resources2.gyp:prefs_behavior',
'../prefs/compiled_resources2.gyp:prefs_types',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
diff --git a/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.html
index 922cf022fa2..b221d10842f 100644
--- a/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.html
+++ b/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -1,7 +1,7 @@
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="../controls/settings_dropdown_menu.html">
@@ -23,8 +23,8 @@
}
paper-toggle-button,
- cr-policy-pref-indicator {
- -webkit-margin-start: var(--checkbox-spacing);
+ cr-policy-indicator {
+ -webkit-margin-start: var(--settings-control-spacing);
}
</style>
<div class="settings-box first">
@@ -32,8 +32,9 @@
$i18n{timeZoneGeolocation}
</div>
<template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]" restamp>
- <cr-policy-pref-indicator pref="[[fakeTimeZonePolicyPref_]]">
- </cr-policy-pref-indicator>
+ <cr-policy-indicator indicator-type="devicePolicy"
+ icon-aria-label="$i18n{timeZoneGeolocation}">
+ </cr-policy-indicator>
</template>
<paper-toggle-button
id="timeZoneAutoDetect"
@@ -45,6 +46,7 @@
</div>
<div class="settings-box continuation embedded">
<settings-dropdown-menu pref="{{prefs.cros.system.timezone}}"
+ label="$i18n{timeZone}"
menu-options="[[timeZoneList_]]"
disabled="[[timeZoneAutoDetect_]]">
</settings-dropdown-menu>
diff --git a/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.js b/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.js
index 6e28f44220f..b2349200702 100644
--- a/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.js
+++ b/chromium/chrome/browser/resources/settings/date_time_page/date_time_page.js
@@ -63,12 +63,6 @@ Polymer({
},
/**
- * A fake preference to provide cr-policy-pref-indicator with policy info.
- * @private {!chrome.settingsPrivate.PrefObject|undefined}
- */
- fakeTimeZonePolicyPref_: Object,
-
- /**
* Initialized with the current time zone so the menu displays the
* correct value. The full option list is fetched lazily if necessary by
* maybeGetTimeZoneList_.
@@ -118,24 +112,12 @@ Polymer({
* @private
*/
onTimeZoneAutoDetectPolicyChanged_: function(managed, valueFromPolicy) {
- if (!managed) {
+ if (managed) {
+ this.timeZoneAutoDetectPolicy_ = valueFromPolicy ?
+ settings.TimeZoneAutoDetectPolicy.FORCED_ON :
+ settings.TimeZoneAutoDetectPolicy.FORCED_OFF;
+ } else {
this.timeZoneAutoDetectPolicy_ = settings.TimeZoneAutoDetectPolicy.NONE;
- this.fakeTimeZonePolicyPref_ = undefined;
- return;
- }
-
- this.timeZoneAutoDetectPolicy_ = valueFromPolicy ?
- settings.TimeZoneAutoDetectPolicy.FORCED_ON :
- settings.TimeZoneAutoDetectPolicy.FORCED_OFF;
-
- if (!this.fakeTimeZonePolicyPref_) {
- this.fakeTimeZonePolicyPref_ = {
- key: 'fakeTimeZonePref',
- type: chrome.settingsPrivate.PrefType.NUMBER,
- value: 0,
- controlledBy: chrome.settingsPrivate.ControlledBy.DEVICE_POLICY,
- enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
- };
}
},
diff --git a/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.html b/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.html
index 2e133156dc6..e72f7615370 100644
--- a/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.html
+++ b/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.html
@@ -7,10 +7,6 @@
<dom-module id="settings-default-browser-page">
<template>
<style include="settings-shared">
- .solo-secondary {
- @apply(--settings-secondary);
- margin: 0;
- }
</style>
<template is="dom-if" if="[[maySetDefaultBrowser_]]">
<div class="settings-box first two-line">
@@ -28,16 +24,14 @@
</template>
<template is="dom-if" if="[[!maySetDefaultBrowser_]]">
<div class="settings-box first">
- <div class="solo-secondary start" hidden$="[[!isDefault_]]"
- id="isDefault">
+ <div class="start" hidden$="[[!isDefault_]]" id="isDefault">
$i18n{defaultBrowserDefault}
</div>
- <div class="solo-secondary start" hidden$="[[!isSecondaryInstall_]]"
- id="isSecondaryInstall">
+ <div class="start" hidden$="[[!isSecondaryInstall_]]"
+ id="isSecondaryInstall">
$i18n{defaultBrowserSecondary}
</div>
- <div class="solo-secondary start" hidden$="[[!isUnknownError_]]"
- id="isUnknownError">
+ <div class="start" hidden$="[[!isUnknownError_]]" id="isUnknownError">
$i18n{defaultBrowserError}
</div>
</div>
diff --git a/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
index d7fb5f2cbbd..09496723e22 100644
--- a/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
@@ -23,6 +23,7 @@
{
'target_name': 'pointers',
'dependencies': [
+ '../controls/compiled_resources2.gyp:settings_toggle_button',
'device_page_browser_proxy'
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
@@ -55,6 +56,7 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(EXTERNS_GYP):settings_private',
'<(EXTERNS_GYP):system_display',
'<(INTERFACES_GYP):system_display_interface',
'display_layout'
diff --git a/chromium/chrome/browser/resources/settings/device_page/device_page.html b/chromium/chrome/browser/resources/settings/device_page/device_page.html
index da02e5f7945..8a1f5b552a9 100644
--- a/chromium/chrome/browser/resources/settings/device_page/device_page.html
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page.html
@@ -19,7 +19,8 @@
<dom-module id="settings-device-page">
<template>
<style include="settings-shared"></style>
- <settings-animated-pages id="pages" section="device">
+ <settings-animated-pages id="pages" section="device"
+ focus-config="[[focusConfig_]]">
<neon-animatable id="main" route-path="default">
<div id="pointersRow" class="settings-box first"
on-tap="onPointersTap_" actionable>
@@ -61,7 +62,7 @@
actionable>
<div class="start">$i18n{powerTitle}</div>
<button class="subpage-arrow" is="paper-icon-button-light"
- arial-label="$i18n{powerTitle}"></button>
+ aria-label="$i18n{powerTitle}"></button>
</div>
</template>
</neon-animatable>
@@ -102,10 +103,10 @@
<settings-storage></settings-storage>
</settings-subpage>
</template>
- <template is="dom-if" route-path="/power">
+ <template is="dom-if" route-path="/power"
+ no-search$="[[!enablePowerSettings_]]">
<settings-subpage
associated-control="[[$$('#powerRow')]]"
- no-search$="[[!enablePowerSettings_]]"
page-title="$i18n{powerTitle}">
<settings-power enable-power-settings="[[enablePowerSettings_]]">
</settings-power>
diff --git a/chromium/chrome/browser/resources/settings/device_page/device_page.js b/chromium/chrome/browser/resources/settings/device_page/device_page.js
index 9d4521589c4..dc714a08bbf 100644
--- a/chromium/chrome/browser/resources/settings/device_page/device_page.js
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page.js
@@ -51,6 +51,27 @@ Polymer({
},
readOnly: true,
},
+
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+ map.set(
+ settings.Route.POINTERS.path, '#pointersRow .subpage-arrow');
+ map.set(
+ settings.Route.KEYBOARD.path, '#keyboardRow .subpage-arrow');
+ map.set(
+ settings.Route.STYLUS.path, '#stylusRow .subpage-arrow');
+ map.set(
+ settings.Route.DISPLAY.path, '#displayRow .subpage-arrow');
+ map.set(
+ settings.Route.STORAGE.path, '#storageRow .subpage-arrow');
+ map.set(
+ settings.Route.POWER.path, '#powerRow .subpage-arrow');
+ return map;
+ },
+ },
},
observers: [
diff --git a/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js b/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
index e9a0c391da6..34d616d4b6c 100644
--- a/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
@@ -6,7 +6,7 @@
cr.exportPath('settings');
/**
- * Mirrors DeviceType from ash/common/system/chromeos/power/power_status.h.
+ * Mirrors DeviceType from ash/system/power/power_status.h.
* @enum {number}
*/
settings.PowerDeviceType = {
diff --git a/chromium/chrome/browser/resources/settings/device_page/display.html b/chromium/chrome/browser/resources/settings/device_page/display.html
index d51a777fa4e..a3d49285682 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display.html
+++ b/chromium/chrome/browser/resources/settings/device_page/display.html
@@ -1,7 +1,6 @@
-<link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
@@ -9,6 +8,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="display_layout.html">
<link rel="import" href="display_overscan_dialog.html">
+<link rel="import" href="../controls/settings_slider.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="../settings_vars_css.html">
@@ -44,11 +44,6 @@
margin-top: 10px;
}
- .info-text {
- color: var(--paper-grey-500);
- margin-top: 5px;
- }
-
.settings-box > paper-button:first-child {
-webkit-padding-start: 0
}
@@ -57,6 +52,9 @@
text-transform: uppercase;
}
+ #controlsDiv > .settings-box:first-of-type {
+ border-top: none;
+ }
</style>
<div class="settings-box first layout vertical self-stretch">
<div class="title-text layout self-start">
@@ -81,57 +79,94 @@
</div>
<div hidden="[[hasMultipleDisplays_(displays)]]"
class="settings-box line-only"></div>
- <div class="settings-box layout vertical first">
+
+ <div id="controlsDiv" class="settings-box layout vertical first">
<h2>[[selectedDisplay.name]]</h2>
- <div class="settings-box embedded first two-line"
- hidden$="[[!showMirror_(displays)]]">
- <div class="start">
- <div id="displayMirrorCheckboxLabel">$i18n{displayMirror}</div>
- <div class="secondary">[[getDisplayMirrorText_(displays)]]</div>
+
+ <template is="dom-if" if="[[showMirror_(unifiedDesktopMode_, displays)]]"
+ restamp>
+ <div class="settings-box embedded two-line">
+ <div class="start">
+ <div id="displayMirrorCheckboxLabel">$i18n{displayMirror}</div>
+ <div class="secondary">[[getDisplayMirrorText_(displays)]]</div>
+ </div>
+ <paper-toggle-button checked="[[isMirrored_(displays)]]"
+ on-tap="onMirroredTap_"
+ aria-labelledby="displayMirrorCheckboxLabel">
+ </paper-toggle-button>
</div>
- <paper-toggle-button checked="[[isMirrored_(displays)]]"
- on-tap="onMirroredTap_"
- aria-labelledby="displayMirrorCheckboxLabel">
- </div>
- <div class="settings-box embedded"
- hidden$="[[!showDisplaySelectMenu_(displays, selectedDisplay)]]">
- <div class="start">$i18n{displayScreenTitle}</div>
- <div class="md-select-wrapper">
- <select class="md-select" on-change="updatePrimaryDisplay_"
- value="[[getDisplaySelectMenuIndex_(
- selectedDisplay, primaryDisplayId)]]">
- <option value="0">$i18n{displayScreenPrimary}</option>
- <option value="1">$i18n{displayScreenExtended}</option>
- </select>
- <span class="md-select-underline"></span>
+ </template>
+
+ <template is="dom-if" if="[[showUnifiedDesktop_(unifiedDesktopAvailable_,
+ unifiedDesktopMode_, displays)]]" restamp>
+ <div class="settings-box embedded two-line">
+ <div class="start">
+ <div id="displayUnifiedDesktopCheckboxLabel">
+ $i18n{displayUnfiedDesktop}
+ </div>
+ <div class="secondary">
+ [[getUnifiedDesktopText_(unifiedDesktopMode_)]]
+ </div>
+ </div>
+ <paper-toggle-button checked="[[unifiedDesktopMode_]]"
+ on-tap="onUnifiedDesktopTap_"
+ aria-labelledby="displayUnifiedDesktopCheckboxLabel">
+ </paper-toggle-button>
</div>
- </div>
+ </template>
+
+ <template is="dom-if" restamp
+ if="[[showDisplaySelectMenu_(displays, selectedDisplay)]]">
+ <div class="settings-box embedded">
+ <div id="displayScreenTitle" class="start">
+ $i18n{displayScreenTitle}
+ </div>
+ <div class="md-select-wrapper">
+ <select class="md-select" on-change="updatePrimaryDisplay_"
+ aria-labelledby="displayScreenTitle"
+ value="[[getDisplaySelectMenuIndex_(
+ selectedDisplay, primaryDisplayId)]]">
+ <option value="0">$i18n{displayScreenPrimary}</option>
+ <option value="1">$i18n{displayScreenExtended}</option>
+ </select>
+ <span class="md-select-underline"></span>
+ </div>
+ </div>
+ </template>
+
<div class="settings-box embedded two-line">
<div class="start textarea layout vertical">
<div>$i18n{displayResolutionTitle}</div>
<div class="secondary layout self-start">
- [[getResolutionText_(selectedDisplay, selectedModeIndex_)]]
+ [[getResolutionText_(selectedDisplay, selectedModePref_.value)]]
</div>
</div>
- <cr-slider disabled="[[!enableSetResolution_(selectedDisplay)]]"
- tick-values="[[modeValues_]]" value="{{selectedModeIndex_}}"
+ <settings-slider disabled="[[!enableSetResolution_(selectedDisplay)]]"
+ tick-values="[[modeValues_]]" pref="{{selectedModePref_}}"
on-change="onSelectedModeChange_">
- </cr-slider>
+ </settings-slider>
</div>
- <div class="settings-box embedded">
- <div class="start textarea">$i18n{displayOrientation}</div>
- <div class="md-select-wrapper">
- <select class="md-select" value="[[selectedDisplay.rotation]]"
- on-change="onOrientationChange_">
- <option value="0">$i18n{displayOrientationStandard}</option>
- <option value="90">90</option>
- <option value="180">180</option>
- <option value="270">270</option>
- </select>
- <span class="md-select-underline"></span>
+
+ <template is="dom-if" if="[[!unifiedDesktopMode_]]" restamp>
+ <div class="settings-box embedded">
+ <div id="displayOrientation" class="start textarea">
+ $i18n{displayOrientation}
+ </div>
+ <div class="md-select-wrapper">
+ <select class="md-select" value="[[selectedDisplay.rotation]]"
+ aria-labelledby="displayOrientation"
+ on-change="onOrientationChange_">
+ <option value="0">$i18n{displayOrientationStandard}</option>
+ <option value="90">90</option>
+ <option value="180">180</option>
+ <option value="270">270</option>
+ </select>
+ <span class="md-select-underline"></span>
+ </div>
</div>
- </div>
- <div class="settings-box embedded two-line"
+ </template>
+
+ <div id="overscan" class="settings-box embedded two-line"
on-tap="onOverscanTap_" hidden$="[[selectedDisplay.isInternal]]"
actionable>
<div class="start">
@@ -146,7 +181,8 @@
</div>
<settings-display-overscan-dialog id="displayOverscan"
- display-id="{{overscanDisplayId}}">
+ display-id="{{overscanDisplayId}}"
+ on-close="onCloseOverscanDialog_">
</settings-display-overscan-dialog>
<div class="settings-box embedded two-line"
diff --git a/chromium/chrome/browser/resources/settings/device_page/display.js b/chromium/chrome/browser/resources/settings/device_page/display.js
index dfea430d003..70102f17e75 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display.js
+++ b/chromium/chrome/browser/resources/settings/device_page/display.js
@@ -24,6 +24,21 @@ Polymer({
properties: {
/**
+ * @type {!chrome.settingsPrivate.PrefObject}
+ * @private
+ */
+ selectedModePref_: {
+ type: Object,
+ value: function() {
+ return {
+ key: 'fakeDisplaySliderPref',
+ type: chrome.settingsPrivate.PrefType.NUMBER,
+ value: 0,
+ };
+ },
+ },
+
+ /**
* Array of displays.
* @type {!Array<!chrome.system.display.DisplayUnitInfo>}
*/
@@ -45,7 +60,7 @@ Polymer({
primaryDisplayId: String,
/** @type {!chrome.system.display.DisplayUnitInfo|undefined} */
- selectedDisplay: {type: Object, observer: 'selectedDisplayChanged_'},
+ selectedDisplay: Object,
/** Id passed to the overscan dialog. */
overscanDisplayId: {
@@ -56,8 +71,19 @@ Polymer({
/** @private {!Array<number>} Mode index values for slider. */
modeValues_: Array,
- /** @private Selected mode index value for slider. */
- selectedModeIndex_: Number,
+ /** @private */
+ unifiedDesktopAvailable_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('unifiedDesktopAvailable');
+ }
+ },
+
+ /** @private */
+ unifiedDesktopMode_: {
+ type: Boolean,
+ value: false,
+ },
},
/** @private {number} Selected mode index received from chrome. */
@@ -110,8 +136,11 @@ Polymer({
/** @private */
getDisplayInfo_: function() {
+ /** @type {chrome.system.display.GetInfoFlags} */ var flags = {
+ singleUnified: true
+ };
settings.display.systemDisplayApi.getInfo(
- this.displayInfoFetched_.bind(this));
+ flags, this.displayInfoFetched_.bind(this));
},
/**
@@ -149,20 +178,28 @@ Polymer({
return 0;
},
- /** @private */
- selectedDisplayChanged_: function() {
- // Set |modeValues_| before |selectedModeIndex_| so that the slider updates
- // correctly.
- var numModes = this.selectedDisplay.modes.length;
+ /**
+ * We need to call this explicitly rather than relying on change events
+ * so that we can control the update order.
+ * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
+ * @private
+ */
+ setSelectedDisplay_: function(selectedDisplay) {
+ // Set |currentSelectedModeIndex_| and |modeValues_| first since these
+ // are not used directly in data binding.
+ var numModes = selectedDisplay.modes.length;
if (numModes == 0) {
this.modeValues_ = [];
- this.selectedModeIndex_ = 0;
this.currentSelectedModeIndex_ = 0;
- return;
+ } else {
+ this.modeValues_ = Array.from(Array(numModes).keys());
+ this.currentSelectedModeIndex_ = this.getSelectedModeIndex_(
+ selectedDisplay);
}
- this.modeValues_ = Array.from(Array(numModes).keys());
- this.selectedModeIndex_ = this.getSelectedModeIndex_(this.selectedDisplay);
- this.currentSelectedModeIndex_ = this.selectedModeIndex_;
+ // Set |selectedDisplay| first since only the resolution slider depends
+ // on |selectedModePref_|.
+ this.selectedDisplay = selectedDisplay;
+ this.set('selectedModePref_.value', this.currentSelectedModeIndex_);
},
/**
@@ -204,7 +241,7 @@ Polymer({
* primary or extended.
* @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
* @param {string} primaryDisplayId
- * @return {number} Retruns 0 if the display is primary else returns 1.
+ * @return {number} Returns 0 if the display is primary else returns 1.
* @private
*/
getDisplaySelectMenuIndex_: function(selectedDisplay, primaryDisplayId) {
@@ -220,17 +257,41 @@ Polymer({
* @private
*/
getDisplayMirrorText_: function(displays) {
- return this.i18n(
- this.isMirrored_(displays) ? 'displayMirrorOn' : 'displayMirrorOff');
+ return this.i18n(this.isMirrored_(displays) ? 'toggleOn' : 'toggleOff');
+ },
+
+ /**
+ * @param {boolean} unifiedDesktopAvailable
+ * @param {boolean} unifiedDesktopMode
+ * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
+ * @return {boolean}
+ * @private
+ */
+ showUnifiedDesktop_: function(
+ unifiedDesktopAvailable, unifiedDesktopMode, displays) {
+ return unifiedDesktopMode ||
+ (unifiedDesktopAvailable && displays.length > 1 &&
+ !this.isMirrored_(displays));
+ },
+
+ /**
+ * @param {boolean} unifiedDesktopMode
+ * @return {string}
+ * @private
+ */
+ getUnifiedDesktopText_: function(unifiedDesktopMode) {
+ return this.i18n(unifiedDesktopMode ? 'toggleOn' : 'toggleOff');
},
/**
+ * @param {boolean} unifiedDesktopMode
* @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
* @return {boolean}
* @private
*/
- showMirror_: function(displays) {
- return this.isMirrored_(displays) || displays.length == 2;
+ showMirror_: function(unifiedDesktopMode, displays) {
+ return this.isMirrored_(displays) ||
+ (!unifiedDesktopMode && displays.length == 2);
},
/**
@@ -269,12 +330,14 @@ Polymer({
if (this.selectedDisplay.modes.length == 0 ||
this.currentSelectedModeIndex_ == -1) {
// If currentSelectedModeIndex_ == -1, selectedDisplay and
- // selectedModeIndex_ are not in sync.
+ // |selectedModePref_.value| are not in sync.
return this.i18n(
'displayResolutionText', this.selectedDisplay.bounds.width.toString(),
this.selectedDisplay.bounds.height.toString());
}
- var mode = this.selectedDisplay.modes[this.selectedModeIndex_];
+ var mode = this.selectedDisplay.modes[
+ /** @type {number} */(this.selectedModePref_.value)];
+ assert(mode);
var best =
this.selectedDisplay.isInternal ? mode.uiScale == 1.0 : mode.isNative;
var widthStr = mode.width.toString();
@@ -294,14 +357,10 @@ Polymer({
var id = e.detail;
for (var i = 0; i < this.displays.length; ++i) {
var display = this.displays[i];
- if (id != display.id)
- continue;
- if (this.selectedDisplay != display) {
- // Set currentSelectedModeIndex_ to -1 so that getResolutionText_ does
- // not flicker. selectedDisplayChanged will update selectedModeIndex_
- // and currentSelectedModeIndex_ correctly.
- this.currentSelectedModeIndex_ = -1;
- this.selectedDisplay = display;
+ if (id == display.id) {
+ if (this.selectedDisplay != display)
+ this.setSelectedDisplay_(display);
+ return;
}
}
},
@@ -355,13 +414,14 @@ Polymer({
*/
onSelectedModeChange_: function() {
if (this.currentSelectedModeIndex_ == -1 ||
- this.currentSelectedModeIndex_ == this.selectedModeIndex_) {
+ this.currentSelectedModeIndex_ == this.selectedModePref_.value) {
// Don't change the selected display mode until we have received an update
// from Chrome and the mode differs from the current mode.
return;
}
/** @type {!chrome.system.display.DisplayProperties} */ var properties = {
- displayMode: this.selectedDisplay.modes[this.selectedModeIndex_]
+ displayMode: this.selectedDisplay.modes[
+ /** @type {number} */(this.selectedModePref_.value)]
};
settings.display.systemDisplayApi.setDisplayProperties(
this.selectedDisplay.id, properties,
@@ -404,6 +464,16 @@ Polymer({
id, properties, this.setPropertiesCallback_.bind(this));
},
+ /** @private */
+ onUnifiedDesktopTap_: function() {
+ /** @type {!chrome.system.display.DisplayProperties} */ var properties = {
+ isUnified: !this.unifiedDesktopMode_,
+ };
+ settings.display.systemDisplayApi.setDisplayProperties(
+ this.primaryDisplayId, properties,
+ this.setPropertiesCallback_.bind(this));
+ },
+
/**
* @param {!Event} e
* @private
@@ -415,6 +485,11 @@ Polymer({
},
/** @private */
+ onCloseOverscanDialog_: function() {
+ this.$$('#overscan button').focus();
+ },
+
+ /** @private */
updateDisplayInfo_: function() {
var displayIds = '';
var primaryDisplay = undefined;
@@ -431,12 +506,11 @@ Polymer({
}
this.displayIds = displayIds;
this.primaryDisplayId = (primaryDisplay && primaryDisplay.id) || '';
- this.selectedDisplay = selectedDisplay || primaryDisplay ||
+ selectedDisplay = selectedDisplay || primaryDisplay ||
(this.displays && this.displays[0]);
- // Save the selected mode index received from Chrome so that we do not
- // send an unnecessary setDisplayProperties call (which would log an error).
- this.currentSelectedModeIndex_ =
- this.getSelectedModeIndex_(this.selectedDisplay);
+ this.setSelectedDisplay_(selectedDisplay);
+
+ this.unifiedDesktopMode_ = !!primaryDisplay && primaryDisplay.isUnified;
this.$.displayLayout.updateDisplays(this.displays, this.layouts);
},
diff --git a/chromium/chrome/browser/resources/settings/device_page/keyboard.html b/chromium/chrome/browser/resources/settings/device_page/keyboard.html
index b57ec09c636..ecd014a5e2c 100644
--- a/chromium/chrome/browser/resources/settings/device_page/keyboard.html
+++ b/chromium/chrome/browser/resources/settings/device_page/keyboard.html
@@ -1,9 +1,9 @@
-<link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../controls/settings_dropdown_menu.html">
+<link rel="import" href="../controls/settings_slider.html">
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../route.html">
@@ -14,21 +14,21 @@
<style include="settings-shared"></style>
<div class="settings-box first">
<div class="start">$i18n{keyboardKeySearch}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{keyboardKeySearch}"
pref="{{prefs.settings.language.xkb_remap_search_key_to}}"
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{keyboardKeyCtrl}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{keyboardKeyCtrl}"
pref="{{prefs.settings.language.xkb_remap_control_key_to}}"
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{keyboardKeyAlt}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{keyboardKeyAlt}"
pref="{{prefs.settings.language.xkb_remap_alt_key_to}}"
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
@@ -36,7 +36,7 @@
<template is="dom-if" if="[[showCapsLock_]]">
<div class="settings-box" id="capsLockKey">
<div class="start">$i18n{keyboardKeyCapsLock}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{keyboardKeyCapsLock}"
pref="{{prefs.settings.language.remap_caps_lock_key_to}}"
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
@@ -45,7 +45,7 @@
<template is="dom-if" if="[[showDiamondKey_]]">
<div class="settings-box" id="diamondKey">
<div class="start">$i18n{keyboardKeyDiamond}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{keyboardKeyDiamond}"
pref="{{prefs.settings.language.remap_diamond_key_to}}"
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
@@ -53,14 +53,14 @@
</template>
<div class="settings-box">
<div class="start">$i18n{keyboardKeyEscape}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{keyboardKeyEscape}"
pref="{{prefs.settings.language.remap_escape_key_to}}"
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{keyboardKeyBackspace}</div>
- <settings-dropdown-menu
+ <settings-dropdown-menu label="$i18n{keyboardKeyBackspace}"
pref="{{prefs.settings.language.remap_backspace_key_to}}"
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
@@ -82,28 +82,28 @@
opened="[[prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]">
<div class="settings-box continuation settings-checkbox-spacer">
<div class="start" id="repeatDelayLabel">$i18n{keyRepeatDelay}</div>
- <cr-slider id="delaySlider"
- value="{{prefs.settings.language.xkb_auto_repeat_delay_r2.value}}"
+ <settings-slider id="delaySlider"
+ pref="{{prefs.settings.language.xkb_auto_repeat_delay_r2}}"
tick-values="[[autoRepeatDelays_]]"
disabled="[[
!prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]"
aria-labelledby="repeatDelayLabel"
label-min="$i18n{keyRepeatDelayLong}"
label-max="$i18n{keyRepeatDelayShort}">
- </cr-slider>
+ </settings-slider>
</div>
<div class="settings-box continuation settings-checkbox-spacer">
<div class="start" id="repeatRateLabel">$i18n{keyRepeatRate}</div>
- <cr-slider id="repeatRateSlider"
- value="{{
- prefs.settings.language.xkb_auto_repeat_interval_r2.value}}"
+ <settings-slider id="repeatRateSlider"
+ pref="{{
+ prefs.settings.language.xkb_auto_repeat_interval_r2}}"
tick-values="[[autoRepeatIntervals_]]"
disabled="[[
!prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]"
aria-labelledby="repeatRateLabel"
label-min="$i18n{keyRepeatRateSlow}"
label-max="$i18n{keyRepeatRateFast}">
- </cr-slider>
+ </settings-slider>
</div>
</iron-collapse>
<div id="keyboardOverlay" class="settings-box"
diff --git a/chromium/chrome/browser/resources/settings/device_page/layout_behavior.js b/chromium/chrome/browser/resources/settings/device_page/layout_behavior.js
index dcea057a8a4..77a56a3fc0e 100644
--- a/chromium/chrome/browser/resources/settings/device_page/layout_behavior.js
+++ b/chromium/chrome/browser/resources/settings/device_page/layout_behavior.js
@@ -36,7 +36,7 @@ var LayoutBehavior = {
calculatedBoundsMap_: new Map(),
/** @private {string} */
- dragLayoutId: '',
+ dragLayoutId_: '',
/** @private {string} */
dragParentId_: '',
@@ -52,7 +52,7 @@ var LayoutBehavior = {
* @param {!Array<!chrome.system.display.DisplayLayout>} layouts
*/
initializeDisplayLayout: function(displays, layouts) {
- this.dragLayoutId = '';
+ this.dragLayoutId_ = '';
this.dragParentId_ = '';
this.mirroring = displays.length > 0 && !!displays[0].mirroringSourceId;
@@ -85,7 +85,7 @@ var LayoutBehavior = {
* @return {!chrome.system.display.Bounds}
*/
updateDisplayBounds: function(id, newBounds) {
- this.dragLayoutId = id;
+ this.dragLayoutId_ = id;
// Find the closest parent.
var closestId = this.findClosest_(id, newBounds);
@@ -134,7 +134,7 @@ var LayoutBehavior = {
*/
finishUpdateDisplayBounds: function(id) {
this.highlightEdge_('', undefined); // Remove any highlights.
- if (id != this.dragLayoutId || !this.dragBounds_ ||
+ if (id != this.dragLayoutId_ || !this.dragBounds_ ||
!this.dragLayoutPosition_) {
return;
}
diff --git a/chromium/chrome/browser/resources/settings/device_page/pointers.html b/chromium/chrome/browser/resources/settings/device_page/pointers.html
index 82c3dcbd604..6c7eaa1026f 100644
--- a/chromium/chrome/browser/resources/settings/device_page/pointers.html
+++ b/chromium/chrome/browser/resources/settings/device_page/pointers.html
@@ -1,7 +1,7 @@
-<link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
<link rel="import" href="../controls/settings_radio_group.html">
+<link rel="import" href="../controls/settings_slider.html">
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="device_page_browser_proxy.html">
<link rel="import" href="../settings_shared_css.html">
@@ -29,19 +29,24 @@
<!-- Subsection title only appears if both mouse and touchpad exist. -->
<h2 hidden$="[[!hasTouchpad]]">$i18n{mouseTitle}</h2>
<div class="settings-box first">
- <settings-toggle-button class="start"
+ <!-- Do not change the mouse button pref before the mouse is released.
+ See crbug.com/686949 -->
+ <settings-toggle-button id="mouseSwapButton" class="start"
pref="{{prefs.settings.mouse.primary_right}}"
- label="$i18n{mouseSwapButtons}">
+ label="$i18n{mouseSwapButtons}"
+ on-settings-boolean-control-change="onMouseSwapButtonsChange_"
+ on-down="onMouseSwapButtonsDown_" on-up="onMouseSwapButtonsUp_"
+ no-set-pref>
</settings-toggle-button>
</div>
<div class="settings-box">
<div class="start" id="mouseSpeedLabel">$i18n{mouseSpeed}</div>
- <cr-slider value="{{prefs.settings.mouse.sensitivity2.value}}"
+ <settings-slider pref="{{prefs.settings.mouse.sensitivity2}}"
tick-values="[[sensitivityValues_]]"
aria-labelledby="mouseSpeedLabel"
label-min="$i18n{pointerSlow}"
label-max="$i18n{pointerFast}">
- </cr-slider>
+ </settings-slider>
</div>
</div>
<div id="touchpad" hidden$="[[!hasTouchpad]]"
@@ -60,13 +65,13 @@
</div>
<div class="settings-box">
<div class="start" id="touchpadSpeedLabel">$i18n{touchpadSpeed}</div>
- <cr-slider id="touchpadSensitivity"
- value="{{prefs.settings.touchpad.sensitivity2.value}}"
+ <settings-slider id="touchpadSensitivity"
+ pref="{{prefs.settings.touchpad.sensitivity2}}"
tick-values="[[sensitivityValues_]]"
aria-labelledby="touchpadSpeedLabel"
label-min="$i18n{pointerSlow}"
label-max="$i18n{pointerFast}">
- </cr-slider>
+ </settings-slider>
</div>
<div class="settings-box">$i18n{scrollLabel}</div>
<div class="list-frame">
diff --git a/chromium/chrome/browser/resources/settings/device_page/pointers.js b/chromium/chrome/browser/resources/settings/device_page/pointers.js
index dda8bf02cc6..6219906a8e6 100644
--- a/chromium/chrome/browser/resources/settings/device_page/pointers.js
+++ b/chromium/chrome/browser/resources/settings/device_page/pointers.js
@@ -20,8 +20,8 @@ Polymer({
hasTouchpad: Boolean,
/**
- * TODO(michaelpg): cr-slider should optionally take a min and max so we
- * don't have to generate a simple range of natural numbers ourselves.
+ * TODO(michaelpg): settings-slider should optionally take a min and max so
+ * we don't have to generate a simple range of natural numbers ourselves.
* @const {!Array<number>}
* @private
*/
@@ -32,6 +32,10 @@ Polymer({
},
},
+ // Used to correctly identify when the mouse button has been released.
+ // crbug.com/686949.
+ receivedMouseSwapButtonsDown_: false,
+
/**
* Prevents the link from activating its parent paper-radio-button.
* @param {!Event} e
@@ -46,8 +50,29 @@ Polymer({
* @param {boolean} hasMouse
* @param {boolean} hasTouchpad
* @return {string}
+ * @private
*/
getSubsectionClass_: function(hasMouse, hasTouchpad) {
return hasMouse && hasTouchpad ? 'subsection' : '';
},
+
+ /** @private */
+ onMouseSwapButtonsDown_: function() {
+ this.receivedMouseSwapButtonsDown_ = true;
+ },
+
+ /** @private */
+ onMouseSwapButtonsUp_: function() {
+ this.receivedMouseSwapButtonsDown_ = false;
+ /** @type {!SettingsToggleButtonElement} */ (this.$.mouseSwapButton)
+ .sendPrefChange();
+ },
+
+ /** @private */
+ onMouseSwapButtonsChange_: function(event) {
+ if (!this.receivedMouseSwapButtonsDown_) {
+ /** @type {!SettingsToggleButtonElement} */ (this.$.mouseSwapButton)
+ .sendPrefChange();
+ }
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/device_page/power.html b/chromium/chrome/browser/resources/settings/device_page/power.html
index 19a56440d0f..5e4725f6984 100644
--- a/chromium/chrome/browser/resources/settings/device_page/power.html
+++ b/chromium/chrome/browser/resources/settings/device_page/power.html
@@ -16,13 +16,14 @@
</div>
<div class="md-select-wrapper" hidden$="[[!showPowerSourceDropdown_]]">
<select id="powerSource" class="md-select"
+ aria-label="$i18n{powerSourceLabel}"
on-change="onPowerSourceChange_">
- <option value="" selected$="[[isEqual_('', selectedPowerSourceId_)]]">
+ <option value="" selected="[[isEqual_('', selectedPowerSourceId_)]]">
$i18n{powerSourceBattery}
</option>
<template is="dom-repeat" items="[[powerSources_]]">
<option value="[[item.id]]"
- selected$="[[isEqual_(item.id, selectedPowerSourceId_)]]">
+ selected="[[isEqual_(item.id, selectedPowerSourceId_)]]">
[[item.description]]
</option>
</template>
diff --git a/chromium/chrome/browser/resources/settings/device_page/storage.html b/chromium/chrome/browser/resources/settings/device_page/storage.html
index b08f439423f..c3c769af371 100644
--- a/chromium/chrome/browser/resources/settings/device_page/storage.html
+++ b/chromium/chrome/browser/resources/settings/device_page/storage.html
@@ -257,7 +257,8 @@
</div>
</template>
- <settings-drive-cache-dialog id="storageDriveCache">
+ <settings-drive-cache-dialog id="storageDriveCache"
+ on-close="onCloseDriveCacheDialog_">
</settings-drive-cache-dialog>
</template>
<script src="storage.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/device_page/storage.js b/chromium/chrome/browser/resources/settings/device_page/storage.js
index 4517f980cf0..f064d17a4b4 100644
--- a/chromium/chrome/browser/resources/settings/device_page/storage.js
+++ b/chromium/chrome/browser/resources/settings/device_page/storage.js
@@ -302,4 +302,9 @@ Polymer({
return '';
}
},
+
+ /** @private */
+ onCloseDriveCacheDialog_: function() {
+ this.$$('#deleteButton').focus();
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/device_page/stylus.html b/chromium/chrome/browser/resources/settings/device_page/stylus.html
index acc3c4b0672..155822fc316 100644
--- a/chromium/chrome/browser/resources/settings/device_page/stylus.html
+++ b/chromium/chrome/browser/resources/settings/device_page/stylus.html
@@ -40,7 +40,9 @@
</div>
<div class="settings-box">
- <div class="start">$i18n{stylusNoteTakingApp}</div>
+ <div id="stylusNoteTakingAppLabel" class="start">
+ $i18n{stylusNoteTakingApp}
+ </div>
<div id="no-apps" class="secondary"
hidden$="[[!showNoApps_(appChoices_, waitingForAndroid_)]]">
@@ -54,11 +56,10 @@
<div id="select-app" class="md-select-wrapper"
hidden$="[[!showApps_(appChoices_, waitingForAndroid_)]]">
- <select id="menu" class="md-select"
- disabled="[[!prefs.settings.enable_stylus_tools.value]]"
- on-change="onSelectedAppChanged_">
+ <select id="menu" class="md-select" on-change="onSelectedAppChanged_"
+ aria-labelledby="stylusNoteTakingAppLabel">
<template is="dom-repeat" items="[[appChoices_]]">
- <option value="[[item.value]]" selected$="[[item.preferred]]">
+ <option value="[[item.value]]" selected="[[item.preferred]]">
[[item.name]]
</option>
</template>
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/downloads_page/compiled_resources2.gyp
index 679ee9e4791..00906d3d4d1 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/downloads_page/compiled_resources2.gyp
@@ -15,6 +15,7 @@
'target_name': 'downloads_page',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'../settings_ui/compiled_resources2.gyp:settings_ui_types',
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
index a64812684db..9af0f95b090 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
+++ b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -1,3 +1,4 @@
+<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
@@ -12,7 +13,7 @@
<div class="settings-box first two-line">
<div class="start">
<div>$i18n{downloadLocation}</div>
- <div class="secondary">
+ <div class="secondary" no-search>
<if expr="not chromeos">
[[prefs.download.default_directory.value]]
</if>
@@ -23,10 +24,10 @@
</div>
<div class="secondary-action">
<controlled-button class="secondary-button" id="changeDownloadsPath"
+ label="$i18n{changeDownloadLocation}"
on-tap="selectDownloadLocation_"
pref="[[prefs.download.default_directory]]"
end-justified>
- $i18n{changeDownloadLocation}
</controlled-button>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js
index 143180c5900..76bb8d7108f 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js
+++ b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js
@@ -58,7 +58,9 @@ Polymer({
/** @private */
selectDownloadLocation_: function() {
- this.browserProxy_.selectDownloadLocation();
+ listenOnce(this, 'transitionend', function() {
+ this.browserProxy_.selectDownloadLocation();
+ }.bind(this));
},
// <if expr="chromeos">
diff --git a/chromium/chrome/browser/resources/settings/focus_row_behavior.html b/chromium/chrome/browser/resources/settings/focus_row_behavior.html
new file mode 100644
index 00000000000..3ccc8839a5f
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/focus_row_behavior.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr/ui/focus_row.html">
+<script src="focus_row_behavior.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/focus_row_behavior.js b/chromium/chrome/browser/resources/settings/focus_row_behavior.js
new file mode 100644
index 00000000000..286c4eb65d6
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/focus_row_behavior.js
@@ -0,0 +1,172 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @param {{lastFocused: Object}} listItem
+ * @constructor
+ * @implements {cr.ui.FocusRow.Delegate}
+ */
+function FocusRowDelegate(listItem) {
+ /** @private */
+ this.listItem_ = listItem;
+}
+
+FocusRowDelegate.prototype = {
+ /**
+ * @override
+ * @param {!cr.ui.FocusRow} row
+ * @param {!Event} e
+ */
+ onFocus: function(row, e) {
+ this.listItem_.lastFocused = e.path[0];
+ },
+
+ /**
+ * @override
+ * @param {!cr.ui.FocusRow} row The row that detected a keydown.
+ * @param {!Event} e
+ * @return {boolean} Whether the event was handled.
+ */
+ onKeydown: function(row, e) {
+ // Prevent iron-list from changing the focus on enter.
+ if (e.key == 'Enter')
+ e.stopPropagation();
+
+ return false;
+ },
+};
+
+/**
+ * @param {!Element} root
+ * @param {cr.ui.FocusRow.Delegate} delegate
+ * @constructor
+ * @extends {cr.ui.FocusRow}
+ */
+function VirtualFocusRow(root, delegate) {
+ cr.ui.FocusRow.call(this, root, /* boundary */ null, delegate);
+}
+
+VirtualFocusRow.prototype = {
+ __proto__: cr.ui.FocusRow.prototype
+};
+
+
+/**
+ * Any element that is being used as an iron-list row item can extend this
+ * behavior, which encapsulates focus controls of mouse and keyboards.
+ * To use this behavior:
+ * - The parent element should pass a "last-focused" attribute double-bound
+ * to the row items, to track the last-focused element across rows.
+ * - There must be a container in the extending element with the
+ * [focus-row-container] attribute that contains all focusable controls.
+ * - On each of the focusable controls, there must be a [focus-row-control]
+ * attribute, and a [focus-type=] attribute unique for each control.
+ *
+ * @polymerBehavior
+ */
+var FocusRowBehavior = {
+ properties: {
+ /** @private {VirtualFocusRow} */
+ row_: Object,
+
+ /** @private {boolean} */
+ mouseFocused_: Boolean,
+
+ /** @type {Element} */
+ lastFocused: {
+ type: Object,
+ notify: true,
+ },
+
+ /**
+ * This is different from tabIndex, since the template only does a one-way
+ * binding on both attributes, and the behavior actually make use of this
+ * fact. For example, when a control within a row is focused, it will have
+ * tabIndex = -1 and ironListTabIndex = 0.
+ * @type {number}
+ */
+ ironListTabIndex: {
+ type: Number,
+ observer: 'ironListTabIndexChanged_',
+ },
+ },
+
+ /** @override */
+ attached: function() {
+ this.classList.add('no-outline');
+
+ Polymer.RenderStatus.afterNextRender(this, function() {
+ var rowContainer = this.root.querySelector('[focus-row-container]');
+ assert(!!rowContainer);
+ this.row_ = new VirtualFocusRow(rowContainer, new FocusRowDelegate(this));
+ this.ironListTabIndexChanged_();
+ this.addItems_();
+
+ // Adding listeners asynchronously to reduce blocking time, since this
+ // behavior will be used by items in potentially long lists.
+ this.listen(this, 'focus', 'onFocus_');
+ this.listen(this, 'dom-change', 'addItems_');
+ this.listen(this, 'mousedown', 'onMouseDown_');
+ this.listen(this, 'blur', 'onBlur_');
+ });
+ },
+
+ /** @override */
+ detached: function() {
+ this.unlisten(this, 'focus', 'onFocus_');
+ this.unlisten(this, 'dom-change', 'addItems_');
+ this.unlisten(this, 'mousedown', 'onMouseDown_');
+ this.unlisten(this, 'blur', 'onBlur_');
+ if (this.row_)
+ this.row_.destroy();
+ },
+
+ /** @private */
+ addItems_: function() {
+ if (this.row_) {
+ this.row_.destroy();
+
+ var controls = this.root.querySelectorAll('[focus-row-control]');
+
+ for (var i = 0; i < controls.length; i++) {
+ this.row_.addItem(
+ controls[i].getAttribute('focus-type'),
+ /** @type {HTMLElement} */ (controls[i]));
+ }
+ }
+ },
+
+ /** @private */
+ onFocus_: function() {
+ if (this.mouseFocused_) {
+ this.mouseFocused_ = false; // Consume and reset flag.
+ return;
+ }
+
+ if (this.lastFocused) {
+ this.row_.getEquivalentElement(this.lastFocused).focus();
+ } else {
+ var firstFocusable = assert(this.row_.getFirstFocusable());
+ firstFocusable.focus();
+ }
+
+ this.tabIndex = -1;
+ },
+
+ /** @private */
+ ironListTabIndexChanged_: function() {
+ if (this.row_)
+ this.row_.makeActive(this.ironListTabIndex == 0);
+ },
+
+ /** @private */
+ onMouseDown_: function() {
+ this.mouseFocused_ = true; // Set flag to not do any control-focusing.
+ },
+
+ /** @private */
+ onBlur_: function() {
+ this.mouseFocused_ = false; // Reset flag since it's not active anymore.
+ }
+}; \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.html b/chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.html
deleted file mode 100644
index b63affc3122..00000000000
--- a/chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="focusable_iron_list_item_behavior.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.js b/chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.js
deleted file mode 100644
index 997217725ef..00000000000
--- a/chromium/chrome/browser/resources/settings/focusable_iron_list_item_behavior.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/** @polymerBehavior */
-var FocusableIronListItemBehavior = {
- properties: {
- /** @private {boolean} */
- focusedByKey_: Boolean,
- },
-
- listeners: {
- 'keyup': 'onKeyUp_',
- 'keydown': 'onKeyDown_',
- 'mousedown': 'onMouseDown_',
- 'blur': 'onBlur_',
- },
-
- /**
- * Flag that `this` is focused by keyboard, so mouse click doesn't apply
- * the .no-outline class.
- * @private
- */
- onKeyUp_: function() {
- // If refocusing on child, row itself isn't focused by keyboard anymore.
- if (!this.$$('[focused]'))
- this.focusedByKey_ = true;
- },
-
- /**
- * Unflag when moving away via keyboard (e.g. tabbing onto its children).
- * @private
- */
- onKeyDown_: function() {
- this.focusedByKey_ = false;
- },
-
- /**
- * When clicking on a row, do not show focus outline if the element wasn't
- * already in focus.
- * @private
- */
- onMouseDown_: function() {
- if (!this.focusedByKey_)
- this.classList.add('no-outline');
- },
-
- /**
- * Reset when moving away from the row entirely.
- * @private
- */
- onBlur_: function() {
- this.classList.remove('no-outline');
- this.focusedByKey_ = false;
- },
-}; \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/settings/icons.html b/chromium/chrome/browser/resources/settings/icons.html
index 39ac0e83288..93497c72527 100644
--- a/chromium/chrome/browser/resources/settings/icons.html
+++ b/chromium/chrome/browser/resources/settings/icons.html
@@ -1,6 +1,9 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
+<!--
+List icons here rather than importing large sets of (e.g. Polymer) icons.
+-->
<iron-iconset-svg name="settings" size="24">
<svg>
<defs>
@@ -66,7 +69,6 @@
</if>
<g id="help-outline"><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"></path></g>
<g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"></path></g>
- <g id="input"><path d="M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1v2h10v3z"></path></g>
<if expr="chromeos">
<g id="keyboard"><path d="M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z"></path></g>
</if>
@@ -80,6 +82,7 @@
<g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"></path></g>
</if>
<g id="mic"><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"></path></g>
+ <g id="midi"><path d="M21,19.1H3V5h18V19.1z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z"></path><path fill="none" d="M21,19.1H3V5h18V19.1z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z"></path><path d="M14,5h3v8h-3V5z"></path><path d="M15,12h1v8h-1V12z"></path><path fill="none" d="M0,0h24v24H0V0z"></path><rect x="7" y="5" width="3" height="8"></rect><rect x="8" y="12" width="1" height="8"></rect></g>
<if expr="chromeos">
<g id="mouse"><path d="M13 1.07V9h7c0-4.08-3.05-7.44-7-7.93zM4 15c0 4.42 3.58 8 8 8s8-3.58 8-8v-4H4v4zm7-13.93C7.05 1.56 4 4.92 4 9h7V1.07z"></path></g>
</if>
@@ -90,7 +93,6 @@
<g id="notifications"><path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"></path></g>
<g id="pdf"><path d="M7 11.5h1v-1H7v1zM19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-9.5 8.5c0 .83-.67 1.5-1.5 1.5H7v2H5.5V9H8c.83 0 1.5.67 1.5 1.5v1zm10-1H17v1h1.5V13H17v2h-1.5V9h4v1.5zm-5 3c0 .83-.67 1.5-1.5 1.5h-2.5V9H13c.83 0 1.5.67 1.5 1.5v3zm-2.5 0h1v-3h-1v3z"></path><path fill="none" d="M0 0h24v24H0z"></path></g>
<g id="palette"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path></g>
- <g id="people"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"></path></g>
<g id="photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"></path></g>
<g id="power-settings-new"><path d="M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z"></path></g>
<g id="protocol-handler"><path d="M21.72 11.33l-6.644-7.035a.97.97 0 0 0-1.38-.01l-1.67 1.72-1.617-1.712a.97.97 0 0 0-1.38-.01l-6.737 6.935c-.187.191-.29.447-.292.719-.002.272.099.529.28.722l6.644 7.034a.949.949 0 0 0 1.38.011l1.671-1.718 1.615 1.71a.949.949 0 0 0 1.381.01l6.74-6.935a1.054 1.054 0 0 0 .01-1.44zM6.947 12.464l3.657 3.785-.974.98-5.273-5.456 5.349-5.378.929.962-3.677 3.7a.998.998 0 0 0-.292.702 1 1 0 0 0 .28.705zm7.35 4.768l-.931-.963 3.68-3.7a1.012 1.012 0 0 0 .007-1.407l-3.656-3.784.974-.98 5.273 5.456-5.348 5.378z"></path></g>
@@ -99,6 +101,11 @@
<g id="rotate-right"><path d="M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z"></path></g>
<g id="security"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"></path></g>
<if expr="chromeos">
+ <g id="signal-cellular-0-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path></g>
+ <g id="signal-cellular-1-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path><path d="M12 12L2 22h10z"></path></g>
+ <g id="signal-cellular-2-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path><path d="M14 10L2 22h12z"></path></g>
+ <g id="signal-cellular-3-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path><path d="M17 7L2 22h15z"></path></g>
+ <g id="signal-cellular-4-bar"><path d="M2 22h20V2z"></path></g>
<g id="sim-card-alert"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 15h-2v-2h2v2zm0-4h-2V8h2v5z"></path></g>
<g id="smartphone"><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"></path></g>
</if>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
index 2244ae41649..799eefff6f9 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
@@ -37,6 +37,7 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
'<(DEPTH)/ui/webui/resources/cr_elements/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_network_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(EXTERNS_GYP):networking_private',
'<(INTERFACES_GYP):networking_private_interface',
@@ -134,7 +135,6 @@
{
'target_name': 'network_summary_item',
'dependencies': [
- '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
'<(DEPTH)/ui/webui/resources/cr_elements/network/compiled_resources2.gyp:cr_onc_types',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
@@ -142,5 +142,14 @@
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'tether_connection_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
],
}
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html
index ad9b1ba2140..59baa4bb7ab 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -2,6 +2,7 @@
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_icon.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
@@ -11,6 +12,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../prefs/prefs.html">
<link rel="import" href="../route.html">
<link rel="import" href="internet_shared_css.html">
@@ -32,10 +34,6 @@
-webkit-padding-end: 8px;
}
- cr-policy-network-indicator {
- -webkit-margin-start: 10px;
- }
-
iron-collapse {
margin: 10px 0;
}
@@ -44,15 +42,10 @@
-webkit-margin-end: 10px;
}
- /* Use <span> for subtitles so as not to interfere with
- * settings-box:first-of-type. */
- span.subtitle {
- font-weight: 700;
- padding: 20px;
- }
-
- .advanced {
- font-weight: 700;
+ paper-toggle-button,
+ cr-policy-network-indicator,
+ cr-policy-indicator {
+ -webkit-margin-start: var(--settings-control-spacing);
}
.indented {
@@ -73,18 +66,13 @@
#networkState {
-webkit-padding-start: 8px;
- /* TODO(stevenjb): Finalize font-size / style for this. */
- font-size: 125%;
+ font-size: 107.69%; /* 14px / 13px */
font-weight: 500;
}
#networkState[connected] {
color: var(--google-green-500);
}
-
- #proxyDiv {
- max-width: 500px;
- }
</style>
<!-- Title section: Icon + name + connection state. -->
<div class="settings-box first">
@@ -97,10 +85,10 @@
</div>
<template is="dom-if"
if="[[isPolicySource(networkProperties.Source))]]">
- <cr-policy-network-indicator
+ <cr-policy-indicator
indicator-type="[[getIndicatorTypeForSource(
networkProperties.Source)]]">
- </cr-policy-network-indicator>
+ </cr-policy-indicator>
</template>
</div>
<div id="buttonDiv" class="layout horizontal center">
@@ -125,7 +113,7 @@
<paper-button class="primary-button" on-tap="onConnectTap_"
hidden$="[[!showConnect_(networkProperties, globalPolicy)]]"
disabled="[[!enableConnect_(networkProperties, defaultNetwork,
- globalPolicy)]]">
+ globalPolicy)]]">
$i18n{networkButtonConnect}
</paper-button>
<paper-button class="primary-button" on-tap="onDisconnectTap_"
@@ -169,7 +157,7 @@
</cr-policy-network-indicator>
<paper-toggle-button checked="{{preferNetwork_}}"
disabled="[[isNetworkPolicyEnforced(
- networkProperties.Priority)]]"
+ networkProperties.Priority)]]"
aria-labelledby="preferNetworkToggleLabel">
</paper-toggle-button>
</div>
@@ -190,6 +178,16 @@
</paper-toggle-button>
</div>
</template>
+ <!-- Data roaming (Cellular only). -->
+ <template is="dom-if"
+ if="[[isType_(NetworkType_.CELLULAR, networkProperties)]]">
+ <div class="settings-box">
+ <settings-toggle-button id="allowDataRoaming" class="start"
+ pref="{{prefs.cros.signed.data_roaming_enabled}}"
+ label="$i18n{networkAllowDataRoaming}">
+ </settings-toggle-button>
+ </div>
+ </template>
<!-- SIM Info (Cellular only). -->
<template is="dom-if" if="[[showCellularSim_(networkProperties)]]">
<div class="settings-box single-column stretch">
@@ -218,66 +216,85 @@
</template>
</div>
- <!-- Advanced toggle. -->
- <div class="settings-box" actionable on-tap="toggleAdvancedExpanded_"
- hidden$="[[!showAdvanced_(networkProperties)]]">
- <div class="advanced flex">$i18n{networkSectionAdvanced}</div>
- <cr-expand-button id="expandButton" expanded="{{advancedExpanded_}}"
- alt="$i18n{networkSectionAdvancedExpandA11yLabel}">
- </cr-expand-button>
- </div>
+ <template is="dom-if" if="[[showAdvanced_(networkProperties)]]">
+ <!-- Advanced toggle. -->
+ <div class="settings-box" actionable on-tap="toggleAdvancedExpanded_">
+ <div class="flex">$i18n{networkSectionAdvanced}</div>
+ <cr-expand-button expanded="{{advancedExpanded_}}"
+ alt="$i18n{networkSectionAdvancedA11yLabel}">
+ </cr-expand-button>
+ </div>
- <!-- Advanced section -->
- <iron-collapse opened="[[advancedExpanded_]]">
- <div class="layout vertical indented">
- <div class="settings-box single-column stretch"
- hidden$="[[!hasAdvancedOrDeviceFields_(networkProperties)]]">
- <!-- Advanced properties -->
- <network-property-list
- hidden$="[[!hasAdvancedFields_(networkProperties)]]"
- fields="[[getAdvancedFields_(networkProperties)]]"
- property-dict="[[networkProperties]]">
- </network-property-list>
- <!-- Device properties -->
- <network-property-list
- hidden$="[[!hasDeviceFields_(networkProperties)]]"
- fields="[[getDeviceFields_(networkProperties)]]"
- property-dict="[[networkProperties]]">
- </network-property-list>
+ <!-- Advanced section -->
+ <iron-collapse opened="[[advancedExpanded_]]">
+ <div class="layout vertical indented">
+ <div class="settings-box single-column stretch"
+ hidden$="[[!hasAdvancedOrDeviceFields_(networkProperties)]]">
+ <!-- Advanced properties -->
+ <network-property-list
+ hidden$="[[!hasAdvancedFields_(networkProperties)]]"
+ fields="[[getAdvancedFields_(networkProperties)]]"
+ property-dict="[[networkProperties]]">
+ </network-property-list>
+ <!-- Device properties -->
+ <network-property-list
+ hidden$="[[!hasDeviceFields_(networkProperties)]]"
+ fields="[[getDeviceFields_(networkProperties)]]"
+ property-dict="[[networkProperties]]">
+ </network-property-list>
+ </div>
</div>
+ </iron-collapse>
+ </template>
- <!-- Network sub-section title -->
- <div class="layout vertical"
- hidden$="[[!hasNetworkSection_(networkProperties)]]">
- <span class="subtitle">$i18n{networkSectionNetwork}</span>
- </div>
+ <template is="dom-if" if="[[hasNetworkSection_(networkProperties)]]">
+ <!-- Network toggle -->
+ <div class="settings-box" actionable on-tap="toggleNetworkExpanded_">
+ <div class="start">$i18n{networkSectionNetwork}</div>
+ <cr-expand-button expanded="{{networkExpanded_}}"
+ alt="$i18n{networkSectionNetworkExpandA11yLabel}">
+ </cr-expand-button>
+ </div>
- <!-- APN -->
- <template is="dom-if"
- if="[[isType_(NetworkType_.CELLULAR, networkProperties)]]">
- <network-apnlist editable on-apn-change="onNetworkPropertyChange_"
- network-properties="[[networkProperties]]">
- </network-apnlist>
- </template>
+ <iron-collapse opened="[[networkExpanded_]]">
+ <div class="layout vertical indented">
+ <!-- APN -->
+ <template is="dom-if"
+ if="[[isType_(NetworkType_.CELLULAR, networkProperties)]]">
+ <network-apnlist editable on-apn-change="onNetworkPropertyChange_"
+ network-properties="[[networkProperties]]">
+ </network-apnlist>
+ </template>
- <!-- IP Config, Nameservers, Proxy -->
- <template is="dom-if"
- if="[[isRememberedOrConnected_(networkProperties)]]">
- <network-ip-config editable on-ip-change="onIPConfigChange_"
- network-properties="[[networkProperties]]">
- </network-ip-config>
- <network-nameservers editable
- on-nameservers-change="onIPConfigChange_"
- network-properties="[[networkProperties]]">
- </network-nameservers>
- <span class="subtitle">$i18n{networkSectionProxy}</span>
- <network-proxy editable prefs="{{prefs}}"
- on-proxy-change="onProxyChange_"
- network-properties="[[networkProperties]]">
- </network-proxy>
- </template>
+ <!-- IP Config, Nameservers -->
+ <template is="dom-if"
+ if="[[isRememberedOrConnected_(networkProperties)]]">
+ <network-ip-config editable on-ip-change="onIPConfigChange_"
+ network-properties="[[networkProperties]]">
+ </network-ip-config>
+ <network-nameservers editable
+ on-nameservers-change="onIPConfigChange_"
+ network-properties="[[networkProperties]]">
+ </network-nameservers>
+ </template>
+ </div>
+ </iron-collapse>
+
+ <!-- Proxy toggle -->
+ <div class="settings-box" actionable on-tap="toggleProxyExpanded_">
+ <div class="start">$i18n{networkSectionProxy}</div>
+ <cr-expand-button expanded="{{proxyExpanded_}}"
+ alt="$i18n{networkSectionProxyExpandA11yLabel}">
+ </cr-expand-button>
</div>
- </iron-collapse>
+
+ <iron-collapse opened="[[proxyExpanded_]]">
+ <network-proxy editable prefs="{{prefs}}"
+ on-proxy-change="onProxyChange_"
+ network-properties="[[networkProperties]]">
+ </network-proxy>
+ </iron-collapse>
+ </template>
</template>
</template>
<script src="internet_detail_page.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js
index 66f461924d4..ade3f525328 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -113,6 +113,12 @@ Polymer({
/** @private */
advancedExpanded_: Boolean,
+ /** @private */
+ networkExpanded_: Boolean,
+
+ /** @private */
+ proxyExpanded_: Boolean,
+
/**
* Object providing network type values for data binding.
* @const
@@ -139,6 +145,13 @@ Polymer({
networksChangedListener_: null,
/**
+ * Set to true to once the initial properties have been received. This
+ * prevents setProperties from being called when setting default properties.
+ * @private {boolean}
+ */
+ networkPropertiesReceived_: false,
+
+ /**
* settings.RouteObserverBehavior
* @param {!settings.Route} route
* @protected
@@ -164,6 +177,7 @@ Polymer({
this.close_();
}
// Set basic networkProperties until they are loaded.
+ this.networkPropertiesReceived_ = false;
var type = /** @type {!chrome.networkingPrivate.NetworkType} */ (
queryParams.get('type')) ||
CrOnc.Type.WI_FI;
@@ -261,12 +275,25 @@ Polymer({
* @private
*/
getPropertiesCallback_: function(properties) {
- this.networkProperties = properties;
+ if (chrome.runtime.lastError) {
+ var message = chrome.runtime.lastError.message;
+ if (message == 'Error.InvalidNetworkGuid') {
+ console.error('Details page: GUID no longer exists: ' + this.guid);
+ } else {
+ console.error(
+ 'Unexpected networkingPrivate.getManagedProperties error: ' +
+ message + ' For: ' + this.guid);
+ }
+ this.close_();
+ return;
+ }
if (!properties) {
- // If |properties| is null, the network is no longer visible, close this.
- console.error('Network no longer exists: ' + this.guid);
+ console.error('No properties for: ' + this.guid);
this.close_();
+ return;
}
+ this.networkProperties = properties;
+ this.networkPropertiesReceived_ = true;
},
/**
@@ -287,6 +314,7 @@ Polymer({
Connectable: state.Connectable,
ConnectionState: state.ConnectionState,
};
+ this.networkPropertiesReceived_ = true;
},
/**
@@ -295,6 +323,9 @@ Polymer({
* @private
*/
setNetworkProperties_: function(onc) {
+ if (!this.networkPropertiesReceived_)
+ return;
+
assert(!!this.guid);
this.networkingPrivate.setProperties(this.guid, onc, function() {
if (chrome.runtime.lastError) {
@@ -435,9 +466,9 @@ Polymer({
if (this.connectNotAllowed_(networkProperties, globalPolicy))
return false;
var type = networkProperties.Type;
- if (type == CrOnc.Type.CELLULAR || type == CrOnc.Type.WI_MAX)
+ if (type == CrOnc.Type.CELLULAR)
return false;
- if (type == CrOnc.Type.WI_FI &&
+ if ((type == CrOnc.Type.WI_FI || type == CrOnc.Type.WI_MAX) &&
networkProperties.ConnectionState !=
CrOnc.ConnectionState.NOT_CONNECTED) {
return false;
@@ -531,17 +562,39 @@ Polymer({
this.networkingPrivate.startActivate(this.guid);
},
+ /** @const {string} */ CR_EXPAND_BUTTON_TAG: 'CR-EXPAND-BUTTON',
+
/**
* @param {Event} event
* @private
*/
toggleAdvancedExpanded_: function(event) {
- if (event.target.id == 'expandButton')
+ if (event.target.tagName == this.CR_EXPAND_BUTTON_TAG)
return; // Already handled.
this.advancedExpanded_ = !this.advancedExpanded_;
},
/**
+ * @param {Event} event
+ * @private
+ */
+ toggleNetworkExpanded_: function(event) {
+ if (event.target.tagName == this.CR_EXPAND_BUTTON_TAG)
+ return; // Already handled.
+ this.networkExpanded_ = !this.networkExpanded_;
+ },
+
+ /**
+ * @param {Event} event
+ * @private
+ */
+ toggleProxyExpanded_: function(event) {
+ if (event.target.tagName == this.CR_EXPAND_BUTTON_TAG)
+ return; // Already handled.
+ this.proxyExpanded_ = !this.proxyExpanded_;
+ },
+
+ /**
* Event triggered for elements associated with network properties.
* @param {!{detail: !{field: string, value: (string|!Object)}}} event
* @private
@@ -658,12 +711,13 @@ Polymer({
},
/**
+ * @param {!CrOnc.NetworkProperties} networkProperties
* @return {boolean} True if the shared message should be shown.
* @private
*/
- showShared_: function() {
- return this.networkProperties.Source == 'Device' ||
- this.networkProperties.Source == 'DevicePolicy';
+ showShared_: function(networkProperties) {
+ return networkProperties.Source == 'Device' ||
+ networkProperties.Source == 'DevicePolicy';
},
/**
@@ -672,7 +726,7 @@ Polymer({
* @private
*/
showAutoConnect_: function(networkProperties) {
- return this.networkProperties.Type != CrOnc.Type.ETHERNET &&
+ return networkProperties.Type != CrOnc.Type.ETHERNET &&
this.isRemembered_(networkProperties);
},
@@ -840,36 +894,38 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
- * @return {boolean} True if the network section should be shown.
+ * @return {boolean}
* @private
*/
hasNetworkSection_: function(networkProperties) {
- if (this.networkProperties.Type == CrOnc.Type.VPN)
+ if (networkProperties.Type == CrOnc.Type.VPN)
return false;
- if (this.networkProperties.Type == CrOnc.Type.CELLULAR)
+ if (networkProperties.Type == CrOnc.Type.CELLULAR)
return true;
return this.isRememberedOrConnected_(networkProperties);
},
/**
* @param {string} type The network type.
+ * @param {!CrOnc.NetworkProperties} networkProperties
* @return {boolean} True if the network type matches 'type'.
* @private
*/
- isType_: function(type) {
- return this.networkProperties.Type == type;
+ isType_: function(type, networkProperties) {
+ return networkProperties.Type == type;
},
/**
- * @return {boolean} True if the Cellular SIM section should be shown.
+ * @param {!CrOnc.NetworkProperties} networkProperties
+ * @return {boolean}
* @private
*/
- showCellularSim_: function() {
- if (this.networkProperties.Type != 'Cellular' ||
- !this.networkProperties.Cellular) {
+ showCellularSim_: function(networkProperties) {
+ if (networkProperties.Type != 'Cellular' ||
+ !networkProperties.Cellular) {
return false;
}
- return this.networkProperties.Cellular.Family == 'GSM';
+ return networkProperties.Cellular.Family == 'GSM';
},
/**
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html b/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html
index 8fd0ece8658..a9ff9b13ae2 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html
@@ -1,55 +1,75 @@
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="settings-internet-known-networks-page">
<template>
<style include="settings-shared"></style>
- <div class="settings-box first single-column">
- <div class="settings-box continuation">
- <div>$i18n{knownNetworksMessage}</div>
+
+ <div class="settings-box first">
+ <div>$i18n{knownNetworksMessage}</div>
+ </div>
+
+ <div class="settings-box">
+ <div class="secondary">$i18n{knownNetworksPreferred}</div>
+ </div>
+ <div class="list-frame vertical-list">
+ <div class="list-item"
+ hidden$="[[havePreferred_(networkStateList_)]]">
+ $i18n{internetNoNetworks}
</div>
- <div class="settings-box first single-column self-stretch">
- <div class="secondary">$i18n{knownNetworksPreferred}</div>
- <div class="settings-box self-stretch start"
- hidden$="[[havePreferred_(networkStateList_)]]">
- $i18n{internetNoNetworks}
- </div>
- <template is="dom-repeat" items="[[networkStateList_]]"
- filter="networkIsPreferred_">
- <div class="settings-box self-stretch">
- <div class="start">[[item.Name]]</div>
+ <template is="dom-repeat" items="[[networkStateList_]]"
+ filter="networkIsPreferred_">
+ <div class="list-item">
+ <div class="start">[[item.Name]]</div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ actionable on-tap="fireShowDetails_" tabindex$="[[tabindex]]"
+ aria-label$="[[item.Name]]">
+ </button>
+ <div class="secondary-action">
<paper-icon-button preferred icon="cr:more-vert"
tabindex$="[[tabindex]]" on-tap="onMenuButtonTap_"
title="$i18n{moreActions}">
</paper-icon-button>
</div>
- </template>
- </div>
- <div class="settings-box first single-column self-stretch"
- hidden$="[[!haveNotPreferred_(networkStateList_)]]">
- <div class="secondary">$i18n{knownNetworksAll}</div>
- <template is="dom-repeat" items="[[networkStateList_]]"
- filter="networkIsNotPreferred_">
- <div class="settings-box self-stretch">
- <div class="start">[[item.Name]]</div>
+ </div>
+ </template>
+ </div>
+
+ <div class="settings-box">
+ <div class="secondary">$i18n{knownNetworksAll}</div>
+ </div>
+ <div class="list-frame vertical-list"
+ hidden$="[[!haveNotPreferred_(networkStateList_)]]">
+ <template is="dom-repeat" items="[[networkStateList_]]"
+ filter="networkIsNotPreferred_">
+ <div class="list-item">
+ <div class="start">[[item.Name]]</div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ actionable on-tap="fireShowDetails_" tabindex$="[[tabindex]]"
+ aria-label$="[[item.Name]]">
+ </button>
+ <div class="secondary-action">
<paper-icon-button icon="cr:more-vert" tabindex$="[[tabindex]]"
on-tap="onMenuButtonTap_" title="$i18n{moreActions}">
</paper-icon-button>
</div>
- </template>
- </div>
+ </div>
+ </template>
</div>
<dialog id="dotsMenu" is="cr-action-menu">
<button class="dropdown-item" role="option"
- hidden="[[selectedIsPreferred_]]" on-tap="onAddPreferredTap_">
+ hidden="[[!showAddPreferred_]]" on-tap="onAddPreferredTap_">
$i18n{knownNetworksMenuAddPreferred}
</button>
<button class="dropdown-item" role="option"
- hidden="[[!selectedIsPreferred_]]" on-tap="onRemovePreferredTap_">
+ hidden="[[!showRemovePreferred_]]" on-tap="onRemovePreferredTap_">
$i18n{knownNetworksMenuRemovePreferred}
</button>
<button class="dropdown-item" role="option" on-tap="onForgetTap_">
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js b/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js
index bf8b2b3f6f0..16e3b9e93b8 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.js
@@ -10,6 +10,8 @@
Polymer({
is: 'settings-internet-known-networks-page',
+ behaviors: [CrPolicyNetworkBehavior],
+
properties: {
/**
* The type of networks to list.
@@ -36,14 +38,17 @@ Polymer({
return [];
}
},
+
+ /** @private */
+ showAddPreferred_: Boolean,
+
+ /** @private */
+ showRemovePreferred_: Boolean,
},
/** @private {string} */
selectedGuid_: '',
- /** @private {boolean} */
- selectedIsPreferred_: false,
-
/**
* Listener function for chrome.networkingPrivate.onNetworksChanged event.
* @type {function(!Array<string>)}
@@ -144,8 +149,21 @@ Polymer({
this.selectedGuid_ =
/** @type {!{model: !{item: !CrOnc.NetworkStateProperties}}} */ (event)
.model.item.GUID;
- this.selectedIsPreferred_ = button.hasAttribute('preferred');
- /** @type {!CrActionMenuElement} */ (this.$.dotsMenu).showAt(button);
+ // We need to make a round trip to Chrome in order to retrieve the managed
+ // properties for the network. The delay is not noticeable (~5ms) and is
+ // preferable to initiating a query for every known network at load time.
+ this.networkingPrivate.getManagedProperties(
+ this.selectedGuid_, function(properties) {
+ var preferred = button.hasAttribute('preferred');
+ if (this.isNetworkPolicyEnforced(properties.Priority)) {
+ this.showAddPreferred_ = false;
+ this.showRemovePreferred_ = false;
+ } else {
+ this.showAddPreferred_ = !preferred;
+ this.showRemovePreferred_ = preferred;
+ }
+ /** @type {!CrActionMenuElement} */ (this.$.dotsMenu).showAt(button);
+ }.bind(this));
event.stopPropagation();
},
@@ -166,4 +184,18 @@ Polymer({
this.networkingPrivate.forgetNetwork(this.selectedGuid_);
/** @type {!CrActionMenuElement} */ (this.$.dotsMenu).close();
},
+
+ /**
+ * Fires a 'show-details' event with an item containing a |networkStateList_|
+ * entry in the event model.
+ * @param {Event} event
+ * @private
+ */
+ fireShowDetails_: function(event) {
+ var state =
+ /** @type {!{model: !{item: !CrOnc.NetworkStateProperties}}} */ (event)
+ .model.item;
+ this.fire('show-detail', state);
+ event.stopPropagation();
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_page.html b/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
index 3806140c437..d72fd9b6074 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -40,7 +40,6 @@
<div actionable class="settings-box two-line"
on-tap="onExpandAddConnectionsTap_">
<div class="start layout horizontal center">
- <iron-icon icon="cr:add"></iron-icon>
<div>$i18n{internetAddConnection}</div>
</div>
<cr-expand-button alt="$i18n{internetAddConnectionExpandA11yLabel}"
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_page.js b/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
index 4227537b47f..c2524548461 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -156,6 +156,13 @@ Polymer({
var type = queryParams.get('type');
if (type)
this.subpageType_ = type;
+ } else if (route == settings.Route.KNOWN_NETWORKS) {
+ // Handle direct navigation to the known networks page,
+ // e.g. chrome://settings/internet/knownNetworks?type=WiFi
+ var queryParams = settings.getQueryParameters();
+ var type = queryParams.get('type');
+ if (type)
+ this.knownNetworksType_ = type;
}
},
@@ -209,8 +216,10 @@ Polymer({
* @private
*/
onShowKnownNetworks_: function(event) {
+ var params = new URLSearchParams;
+ params.append('type', event.detail.Type);
this.knownNetworksType_ = event.detail.type;
- settings.navigateTo(settings.Route.KNOWN_NETWORKS);
+ settings.navigateTo(settings.Route.KNOWN_NETWORKS, params);
},
/**
@@ -320,7 +329,7 @@ Polymer({
* @private
*/
deviceIsEnabled_: function(deviceState) {
- return deviceState.State ==
+ return !!deviceState && deviceState.State ==
chrome.networkingPrivate.DeviceStateType.ENABLED;
},
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html
index 546bf98048f..07617fbfcec 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html
@@ -11,17 +11,21 @@
<template>
<style include="settings-shared">
#networkListDiv {
+ /* cr-network-list is padded to the right to allow space for a ripple */
+ -webkit-padding-end: calc(var(--settings-box-row-padding) -
+ var(--cr-icon-ripple-padding));
-webkit-padding-start: var(--settings-box-row-padding);
margin-top: var(--settings-page-vertical-margin);
min-height: var(--settings-box-min-height);
}
#addButton {
- -webkit-margin-end: var(--cr-icon-padding);
+ -webkit-margin-end: var(--settings-control-spacing);
}
#onoff[on] {
color: var(--settings-toggle-color);
+ font-weight: 500;
}
.vpn-header {
@@ -49,7 +53,7 @@
on-tap="onAddButtonTap_" tabindex$="[[tabindex]]">
</paper-icon-button>
<paper-toggle-button id="deviceEnabledButton"
- aria-label="[[getToggleA11yString_(deviceState)]]"
+ aria-label$="[[getToggleA11yString_(deviceState)]]"
checked="[[deviceIsEnabled_(deviceState)]]"
enabled="[[enableToggleIsEnabled_(deviceState)]]"
on-tap="onDeviceEnabledTap_">
@@ -58,8 +62,7 @@
</template>
<template is="dom-if" if="[[knownNetworksIsVisible_(deviceState)]]">
- <div actionable class="settings-box continuation"
- on-tap="onKnownNetworksTap_">
+ <div actionable class="settings-box" on-tap="onKnownNetworksTap_">
<div class="start">$i18n{knownNetworksButton}</div>
<button class="subpage-arrow" is="paper-icon-button-light"
aria-label="$i18n{knownNetworksButton}">
@@ -90,13 +93,13 @@
</div>
<!-- Third party VPNs. -->
- <template is="dom-if" if="isEqual_('VPN', deviceState.Type)]]">
+ <template is="dom-if" if="[[isEqual_('VPN', deviceState.Type)]]">
<template is="dom-repeat" items="[[thirdPartyVpnProviders]]">
<div id="[[item.ProviderName]]"
class="vpn-header layout horizontal center">
<div class="flex">[[item.ProviderName]]</div>
<paper-icon-button icon="settings:add-circle"
- aria-label="[[getAddThirdPartyVpnA11yString_(item)]]"
+ aria-label$="[[getAddThirdPartyVpnA11yString_(item)]]"
on-tap="onAddThirdPartyVpnTap_" tabindex$="[[tabindex]]">
</paper-icon-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
index 4189f6b1567..5ff70c39541 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -29,9 +29,12 @@ Polymer({
/**
* Device state for the network type.
- * @type {?DeviceStateProperties|undefined}
+ * @type {?DeviceStateProperties}
*/
- deviceState: Object,
+ deviceState: {
+ type: Object,
+ value: null,
+ },
/** @type {!chrome.networkingPrivate.GlobalPolicy|undefined} */
globalPolicy: Object,
@@ -175,6 +178,8 @@ Polymer({
configured: false
};
this.networkingPrivate.getNetworks(filter, function(networkStates) {
+ if (!this.deviceState)
+ return;
if (this.deviceState.Type != CrOnc.Type.VPN) {
this.networkStateList_ = networkStates;
return;
@@ -294,6 +299,7 @@ Polymer({
/** @private */
onAddButtonTap_: function() {
+ assert(this.deviceState);
chrome.send('addNetwork', [this.deviceState.Type]);
},
@@ -322,7 +328,7 @@ Polymer({
* @private
*/
onKnownNetworksTap_: function() {
- this.fire('show-known-networks', {type: CrOnc.Type.WI_FI});
+ this.fire('show-known-networks', {Type: CrOnc.Type.WI_FI});
},
/**
@@ -411,11 +417,13 @@ Polymer({
this.networkingPrivate.startConnect(state.GUID, function() {
if (chrome.runtime.lastError) {
var message = chrome.runtime.lastError.message;
- if (message != 'connecting') {
- console.error(
- 'Unexpected networkingPrivate.startConnect error: ' + message +
- 'For: ' + state.GUID);
+ if (message == 'connecting' || message == 'connect-canceled' ||
+ message == 'connected' || message == 'Error.InvalidNetworkGuid') {
+ return;
}
+ console.error(
+ 'Unexpected networkingPrivate.startConnect error: ' + message +
+ ' For: ' + state.GUID);
}
});
},
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html b/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html
index a4803bcec08..9a5cd4972bd 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html
@@ -17,7 +17,8 @@
<div class="start">$i18n{networkSectionAccessPoint}</div>
<div class="md-select-wrapper">
<select id="selectApn" class="md-select" on-change="onSelectApnChange_"
- value="[[selectedApn_]]">
+ value="[[selectedApn_]]"
+ aria-label="$i18n{networkSectionAccessPoint}">
<template is="dom-repeat" items="[[apnSelectList_]]">
<option value="[[item.AccessPointName]]">[[apnDesc_(item)]]</option>
</template>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.html b/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.html
index c0feb2ff6b6..ca74a19a813 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.html
@@ -17,8 +17,7 @@
hidden$="[[!showIPEditFields_(editable, automatic_)]]">
<network-property-list
fields="[[ipConfigFields_]]" property-dict="[[ipConfig_]]"
- edit-field-types="[[getIPEditFields_(
- editable, ipConfig_, automatic_)]]"
+ edit-field-types="[[getIPEditFields_(editable, automatic_)]]"
on-property-change="onIPChange_">
</network-property-list>
</div>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.js b/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.js
index 43f34e18b65..695ba5065fa 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.js
@@ -35,19 +35,22 @@ Polymer({
*/
automatic_: {
type: Boolean,
- value: false,
+ value: true,
observer: 'automaticChanged_',
},
/**
* The currently visible IP Config property dictionary. The 'RoutingPrefix'
* property is a human-readable mask instead of a prefix length.
- * @private {!{
+ * @private {?{
* ipv4: !CrOnc.IPConfigUIProperties,
* ipv6: !CrOnc.IPConfigUIProperties
- * }|undefined}
+ * }}
*/
- ipConfig_: Object,
+ ipConfig_: {
+ type: Object,
+ value: null,
+ },
/**
* Array of properties to pass to the property list.
@@ -84,49 +87,39 @@ Polymer({
this.savedStaticIp_ = undefined;
// Update the 'automatic' property.
- var ipConfigType =
- CrOnc.getActiveValue(this.networkProperties.IPAddressConfigType);
- this.automatic_ = (ipConfigType != CrOnc.IPConfigType.STATIC);
-
- // Update the 'ipConfig' property.
- var ipv4 =
- CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
- var ipv6 =
- CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV6);
- this.ipConfig_ = {
- ipv4: this.getIPConfigUIProperties_(ipv4),
- ipv6: this.getIPConfigUIProperties_(ipv6)
- };
+ if (this.networkProperties.IPAddressConfigType ) {
+ var ipConfigType =
+ CrOnc.getActiveValue(this.networkProperties.IPAddressConfigType);
+ this.automatic_ = (ipConfigType != CrOnc.IPConfigType.STATIC);
+ }
+
+ if (this.networkProperties.IPConfigs) {
+ // Update the 'ipConfig' property.
+ var ipv4 =
+ CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
+ var ipv6 =
+ CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV6);
+ this.ipConfig_ = {
+ ipv4: this.getIPConfigUIProperties_(ipv4),
+ ipv6: this.getIPConfigUIProperties_(ipv6)
+ };
+ }
},
- /**
- * Polymer automatic changed method.
- */
+ /** @private */
automaticChanged_: function() {
- if (!this.automatic_ || !this.ipConfig_)
+ if (!this.automatic_ || !this.ipConfig_) {
+ // When switching from automatic, don't send any changes, ip-change will
+ // be fired in onIPChange when a field is changed.
return;
- if (this.automatic_ || !this.savedStaticIp_) {
- // Save the static IP configuration when switching to automatic.
- this.savedStaticIp_ = this.ipConfig_.ipv4;
- var configType =
- this.automatic_ ? CrOnc.IPConfigType.DHCP : CrOnc.IPConfigType.STATIC;
- this.fire('ip-change', {
- field: 'IPAddressConfigType',
- value: configType,
- });
- } else {
- // Restore the saved static IP configuration.
- var ipconfig = {
- Gateway: this.savedStaticIp_.Gateway,
- IPAddress: this.savedStaticIp_.IPAddress,
- RoutingPrefix: this.savedStaticIp_.RoutingPrefix,
- Type: this.savedStaticIp_.Type,
- };
- this.fire('ip-change', {
- field: 'StaticIPConfig',
- value: this.getIPConfigProperties_(ipconfig),
- });
}
+ // Save the static IP configuration when switching to automatic.
+ this.savedStaticIp_ = this.ipConfig_.ipv4;
+ // Send the change.
+ this.fire('ip-change', {
+ field: 'IPAddressConfigType',
+ value: CrOnc.IPConfigType.DHCP,
+ });
},
/**
@@ -181,7 +174,7 @@ Polymer({
* @private
*/
getIPEditFields_: function() {
- if (!this.editable || this.automatic__)
+ if (!this.editable || this.automatic_)
return {};
return {
'ipv4.IPAddress': 'String',
@@ -203,6 +196,7 @@ Polymer({
var value = event.detail.value;
// Note: |field| includes the 'ipv4.' prefix.
this.set('ipConfig_.' + field, value);
+ // This will also set IPAddressConfigType to STATIC.
this.fire('ip-change', {
field: 'StaticIPConfig',
value: this.getIPConfigProperties_(this.ipConfig_.ipv4)
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html b/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html
index 63590f64027..6ab48419761 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html
@@ -7,12 +7,18 @@
<dom-module id="network-nameservers">
<template>
- <style include="internet-shared md-select"></style>
+ <style include="internet-shared md-select">
+ paper-input-container {
+ -webkit-padding-start: 4px;
+ }
+ </style>
+
<div class="settings-box first">
<div class="start">$i18n{networkSectionNameservers}</div>
<div class="md-select-wrapper">
<select id="nameserverType" class="md-select" on-change="onTypeChange_"
- value="[[nameserversType_]]">
+ value="[[nameserversType_]]"
+ aria-label="$i18n{networkSectionNameservers}">
<template is="dom-repeat" items="[[nameserverTypeNames_]]">
<option value="[[item]]">[[nameserverTypeDesc_(item)]]</option>
</template>
@@ -21,7 +27,7 @@
</div>
</div>
- <div class="settings-box continuation single-column indent"
+ <div class="settings-box continuation single-column"
hidden$="[[!nameservers_.length]]">
<template is="dom-repeat" items="[[nameservers_]]">
<paper-input-container no-label-float>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_property_list.html b/chromium/chrome/browser/resources/settings/internet_page/network_property_list.html
index a751c4920ab..101b8dabfaf 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_property_list.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_property_list.html
@@ -25,7 +25,7 @@
}
cr-policy-network-indicator {
- padding: 0 var(--cr-icon-padding);
+ -webkit-margin-start: var(--settings-control-spacing);
}
</style>
<template is="dom-repeat" items="[[fields]]"
@@ -35,7 +35,7 @@
<div>[[getPropertyLabel_(item, prefix)]]</div>
<!-- Uneditable property value -->
<div class="layout horizontal"
- hidden$="[[isEditable_(item, '', propertyDict, editFieldTypes)]]">
+ hidden="[[isEditable_(item, '', propertyDict, editFieldTypes)]]">
<div class="secondary">
[[getPropertyValue_(item, prefix, propertyDict)]]
</div>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy.html b/chromium/chrome/browser/resources/settings/internet_page/network_proxy.html
index f2c2b8d900c..1941afc3b65 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy.html
@@ -35,31 +35,23 @@
margin-bottom: 10px;
}
- /* Use .middle spacing but no flex. */
- .settings-box .middle {
- flex: none;
- }
-
#exceptionsDiv {
padding: 10px 0;
}
- #exceptionsDiv network-proxy-exclusions {
+ network-proxy-exclusions {
margin: 10px 0;
}
-
- #proxyDiv paper-toggle-button {
- padding: 10px 0;
- }
</style>
<!-- Policy indicator. Only one dom-if below will be shown. -->
<template is="dom-if"
if="[[shouldShowNetworkPolicyIndicator_(networkProperties)]]">
- <div class="settings-box continuation single-column">
+ <div class="list-frame">
<div class="layout horizontal center">
<cr-policy-network-indicator
- property="[[networkProperties.ProxySettings.Type]]">
+ property="[[networkProperties.ProxySettings.Type]]"
+ no-extension-indicator>
</cr-policy-network-indicator>
<div>$i18n{networkProxyEnforcedPolicy}</div>
</div>
@@ -67,7 +59,7 @@
</template>
<template is="dom-if"
if="[[shouldShowExtensionIndicator_(networkProperties)]]">
- <div class="settings-box continuation single-column">
+ <div class="list-frame">
<extension-controlled-indicator
extension-id="[[prefs.proxy.extensionId]]"
extension-name="[[prefs.proxy.controlledByName]]"
@@ -77,25 +69,26 @@
</template>
<!-- Allow shared proxies -->
- <div class="settings-box continuation"
+ <div class="settings-box continuation indent"
hidden$="[[!shouldShowAllowShared_(
networkProperties.ProxySettings.Type)]]">
<settings-toggle-button id="allowShared" class="start"
pref="{{prefs.settings.use_shared_proxies}}"
label="$i18n{networkProxyAllowShared}"
- on-change="onAllowSharedProxiesChange_"
+ on-settings-boolean-control-change="onAllowSharedProxiesChange_"
no-set-pref>
</settings-toggle-button>
</div>
<!-- Proxy type dropdown -->
- <div class="settings-box continuation">
+ <div class="settings-box continuation indent">
<div class="start">$i18n{networkProxyConnectionType}</div>
<div class="md-select-wrapper">
<select id="proxyType" class="md-select" on-change="onTypeChange_"
value="[[proxy_.Type]]"
disabled="[[!isEditable_('Type', networkProperties, editable,
- useSharedProxies_)]]">
+ useSharedProxies_)]]"
+ aria-label="$i18n{networkProxyConnectionType}">
<template is="dom-repeat" items="[[proxyTypes_]]">
<option value="[[item]]">[[getProxyTypeDesc_(item)]]</option>
</template>
@@ -108,7 +101,7 @@
<div class="settings-box continuation indent"
hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.PAC)]]">
<div>$i18n{networkProxyAutoConfig}</div>
- <paper-input no-label-float class="middle flex" value="{{proxy_.PAC}}"
+ <paper-input no-label-float class="middle" value="{{proxy_.PAC}}"
disabled="[[!isEditable_('PAC', networkProperties, editable,
useSharedProxies_)]]"
on-change="onPACChange_">
@@ -119,22 +112,24 @@
<div class="settings-box continuation indent"
hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.WPAD)]]">
<div>$i18n{networkSectionWpad}</div>
- <div class="middle flex">[[WPAD_]]</div>
+ <div class="middle">[[WPAD_]]</div>
</div>
<!-- Manual -->
- <div id="proxyDiv" class="settings-box continuation single-column indent"
+ <div class="settings-box continuation indent"
hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.MANUAL)]]">
- <div class="flex layout horizontal">
- <div id="networkProxyToggleLabel" class="flex">
- $i18n{networkProxyUseSame}
- </div>
- <paper-toggle-button checked="{{useSameProxy_}}"
- disabled="[[!isEditable_('Type', networkProperties, editable,
- useSharedProxies_)]]"
- aria-labelledby="networkProxyToggleLabel">
- </paper-toggle-button>
+ <div id="networkProxyToggleLabel" class="flex">
+ $i18n{networkProxyUseSame}
</div>
+ <paper-toggle-button checked="{{useSameProxy_}}"
+ disabled="[[!isEditable_('Type', networkProperties, editable,
+ useSharedProxies_)]]"
+ aria-labelledby="networkProxyToggleLabel">
+ </paper-toggle-button>
+ </div>
+
+ <div class="list-frame"
+ hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.MANUAL)]]">
<div hidden$="[[!useSameProxy_]]" class="layout vertical">
<network-proxy-input
on-proxy-change="onProxyInputChange_"
@@ -205,7 +200,8 @@
<!-- Confirm Allow shared proxies dialog -->
<dialog is="cr-dialog" id="confirmAllowSharedDialog"
- close-text="$i18n{close}" on-cancel="onAllowSharedDialogCancel_">
+ close-text="$i18n{close}" on-cancel="onAllowSharedDialogCancel_"
+ on-close="onAllowSharedDialogClose_">
<div class="title">$i18n{networkProxyAllowSharedWarningTitle}</div>
<div class="body">$i18n{networkProxyAllowSharedWarningMessage}</div>
<div class="button-container">
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy.js b/chromium/chrome/browser/resources/settings/internet_page/network_proxy.js
index 9e96db902cf..9f34cf68d87 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy.js
@@ -174,21 +174,23 @@ Polymer({
/** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getSimpleActiveProperties(
proxySettings.Manual.SecureHTTPProxy)) ||
- proxy.Manual.HTTPProxy;
+ {Host: '', Port: 80};
proxy.Manual.FTPProxy =
/** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getSimpleActiveProperties(
proxySettings.Manual.FTPProxy)) ||
- proxy.Manual.HTTPProxy;
+ {Host: '', Port: 80};
proxy.Manual.SOCKS =
/** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getSimpleActiveProperties(proxySettings.Manual.SOCKS)) ||
- proxy.Manual.HTTPProxy;
+ {Host: '', Port: 80};
var jsonHttp = proxy.Manual.HTTPProxy;
this.useSameProxy_ =
- CrOnc.proxyMatches(jsonHttp, proxy.Manual.SecureHTTPProxy) &&
- CrOnc.proxyMatches(jsonHttp, proxy.Manual.FTPProxy) &&
- CrOnc.proxyMatches(jsonHttp, proxy.Manual.SOCKS);
+ (CrOnc.proxyMatches(jsonHttp, proxy.Manual.SecureHTTPProxy) &&
+ CrOnc.proxyMatches(jsonHttp, proxy.Manual.FTPProxy) &&
+ CrOnc.proxyMatches(jsonHttp, proxy.Manual.SOCKS)) ||
+ (!proxy.Manual.SecureHTTPProxy.Host &&
+ !proxy.Manual.FTPProxy.Host && !proxy.Manual.SOCKS.Host);
}
if (proxySettings.ExcludeDomains) {
proxy.ExcludeDomains = /** @type {!Array<string>|undefined} */ (
@@ -256,33 +258,36 @@ Polymer({
* @private
*/
sendProxyChange_: function() {
- if (this.proxy_.Type == CrOnc.ProxySettingsType.MANUAL) {
- var proxy =
- /** @type {!CrOnc.ProxySettings} */ (Object.assign({}, this.proxy_));
+ var proxy =
+ /** @type {!CrOnc.ProxySettings} */ (Object.assign({}, this.proxy_));
+ if (proxy.Type == CrOnc.ProxySettingsType.MANUAL) {
var manual = proxy.Manual;
- var defaultProxy = manual.HTTPProxy;
- if (!defaultProxy || !defaultProxy.Host)
- return;
- if (this.useSameProxy_ || !this.get('SecureHTTPProxy.Host', manual)) {
+ var defaultProxy = manual.HTTPProxy || {Host: '', Port: 80};
+ if (this.useSameProxy_) {
proxy.Manual.SecureHTTPProxy = /** @type {!CrOnc.ProxyLocation} */ (
Object.assign({}, defaultProxy));
- }
- if (this.useSameProxy_ || !this.get('FTPProxy.Host', manual)) {
proxy.Manual.FTPProxy = /** @type {!CrOnc.ProxyLocation} */ (
Object.assign({}, defaultProxy));
- }
- if (this.useSameProxy_ || !this.get('SOCKS.Host', manual)) {
proxy.Manual.SOCKS = /** @type {!CrOnc.ProxyLocation} */ (
Object.assign({}, defaultProxy));
+ } else {
+ // Remove properties with empty hosts to unset them.
+ if (manual.HTTPProxy && !manual.HTTPProxy.Host)
+ delete manual.HTTPProxy;
+ if (manual.SecureHTTPProxy && !manual.SecureHTTPProxy.Host)
+ delete manual.SecureHTTPProxy;
+ if (manual.FTPProxy && !manual.FTPProxy.Host)
+ delete manual.FTPProxy;
+ if (manual.SOCKS && !manual.SOCKS.Host)
+ delete manual.SOCKS;
}
- this.savedManual_ = Object.assign({}, proxy.Manual);
+ this.savedManual_ = Object.assign({}, manual);
this.savedExcludeDomains_ = proxy.ExcludeDomains;
- this.proxy_ = proxy;
- } else if (this.proxy_.Type == CrOnc.ProxySettingsType.PAC) {
- if (!this.proxy_.PAC)
+ } else if (proxy.Type == CrOnc.ProxySettingsType.PAC) {
+ if (!proxy.PAC)
return;
}
- this.fire('proxy-change', {field: 'ProxySettings', value: this.proxy_});
+ this.fire('proxy-change', {field: 'ProxySettings', value: proxy});
this.proxyModified_ = false;
},
@@ -436,7 +441,12 @@ Polymer({
isSaveManualProxyEnabled_: function() {
if (!this.proxyModified_)
return false;
- return !!this.get('HTTPProxy.Host', this.proxy_.Manual);
+ var manual = this.proxy_.Manual;
+ var httpHost = this.get('HTTPProxy.Host', manual);
+ if (this.useSameProxy_)
+ return !!httpHost;
+ return !!httpHost || !!this.get('SecureHTTPProxy.Host', manual) ||
+ !!this.get('FTPProxy.Host', manual) || !!this.get('SOCKS.Host', manual);
},
/**
@@ -479,4 +489,9 @@ Polymer({
.resetToPrefValue();
this.$.confirmAllowSharedDialog.close();
},
+
+ /** @private */
+ onAllowSharedDialogClose_: function() {
+ this.$$('#allowShared').focus();
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.js b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.js
index 9d807dc71f0..131b480655b 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.js
@@ -46,8 +46,6 @@ Polymer({
* @private
*/
onValueChange_: function() {
- if (!this.value.Host)
- return;
var port = parseInt(this.value.Port, 10);
if (isNaN(port))
port = 80;
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html
index 73a8126e57b..7ed34a037c7 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html
@@ -46,7 +46,7 @@
}
paper-toggle-button {
- -webkit-margin-start: var(--checkbox-spacing);
+ -webkit-margin-start: var(--settings-control-spacing);
}
</style>
@@ -67,7 +67,7 @@
<div class="error">$i18n{networkSimCardLocked}</div>
</div>
<div class="secondary-action">
- <paper-button on-tap="onUnlockPinTap_">
+ <paper-button id="unlockPinButton" on-tap="onUnlockPinTap_">
$i18n{networkSimUnlock}
</paper-button>
</div>
@@ -79,21 +79,23 @@
<div id="simLockToggleLabel" class="start">
$i18n{networkSimLockEnable}
</div>
- <paper-button on-tap="onChangePinTap_"
+ <paper-button id="changePinButton" on-tap="onChangePinTap_"
hidden$="[[!networkProperties.Cellular.SIMLockStatus.LockEnabled]]">
$i18n{networkSimChangePin}
</paper-button>
- <paper-toggle-button on-change="onSimLockEnabledChange_"
- checked="[[networkProperties.Cellular.SIMLockStatus.LockEnabled]]"
+ <paper-toggle-button id="simLockButton"
+ on-change="onSimLockEnabledChange_" checked="{{lockEnabled_}}"
aria-labelledby="simLockToggleLabel">
</paper-toggle-button>
</div>
<!-- Enter PIN dialog -->
- <dialog is="cr-dialog" id="enterPinDialog" close-text="$i18n{close}">
+ <dialog is="cr-dialog" id="enterPinDialog" close-text="$i18n{close}"
+ on-cancel="onEnterPinDialogCancel_"
+ on-close="onEnterPinDialogClose_">
<div class="title">$i18n{networkSimEnterPinTitle}</div>
<div class="body">
- <paper-input id="enterPin" class="pin" no-label-float
+ <paper-input id="enterPin" class="pin" no-label-float autofocus
label="$i18n{networkSimEnterPin}">
<iron-a11y-keys keys="enter" on-keys-pressed="sendEnterPin_">
</iron-a11y-keys>
@@ -110,10 +112,11 @@
</dialog>
<!-- Change PIN dialog -->
- <dialog is="cr-dialog" id="changePinDialog" close-text="$i18n{close}">
+ <dialog is="cr-dialog" id="changePinDialog" close-text="$i18n{close}"
+ on-close="onChangePinDialogClose_">
<div class="title">$i18n{networkSimChangePinTitle}</div>
<div class="body">
- <paper-input id="changePinOld" class="pin" no-label-float
+ <paper-input id="changePinOld" class="pin" no-label-float autofocus
label="$i18n{networkSimEnterOldPin}">
</paper-input>
<paper-input id="changePinNew1" class="pin" no-label-float
@@ -136,10 +139,11 @@
</dialog>
<!-- Unlock PIN dialog -->
- <dialog is="cr-dialog" id="unlockPinDialog" close-text="$i18n{close}">
+ <dialog is="cr-dialog" id="unlockPinDialog" close-text="$i18n{close}"
+ on-close="onUnlockPinDialogClose_">
<div class="title">$i18n{networkSimLockedTitle}</div>
<div class="body">
- <paper-input id="unlockPin" class="pin" no-label-float
+ <paper-input id="unlockPin" class="pin" no-label-float autofocus
label="$i18n{networkSimEnterPin}">
<iron-a11y-keys keys="enter" on-keys-pressed="sendUnlockPin_">
</iron-a11y-keys>
@@ -156,13 +160,14 @@
</dialog>
<!-- Unlock PUK dialog -->
- <dialog is="cr-dialog" id="unlockPukDialog" close-text="$i18n{close}">
+ <dialog is="cr-dialog" id="unlockPukDialog" close-text="$i18n{close}"
+ on-close="onUnlockPinDialogClose_">
<div class="title">$i18n{networkSimLockedTitle}</div>
<div class="body">
<div>
Enter the 8-digit PIN Unblocking Key provided by your carrier
</div>
- <paper-input id="unlockPuk" class="puk" no-label-float
+ <paper-input id="unlockPuk" class="puk" no-label-float autofocus
label="$i18n{networkSimEnterPuk}">
</paper-input>
<paper-input id="unlockPin1" class="pin" no-label-float
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js
index 8772be4c69a..1dc2ef757a7 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js
@@ -40,6 +40,16 @@ Polymer({
networkingPrivate: Object,
/**
+ * Reflects networkProperties.Cellular.SIMLockStatus.LockEnabled for the
+ * toggle button.
+ * @private
+ */
+ lockEnabled_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
* Set to true when a PUK is required to unlock the SIM.
* @private
*/
@@ -61,14 +71,17 @@ Polymer({
sendSimLockEnabled_: false,
+ /** @private */
networkPropertiesChanged_: function() {
if (!this.networkProperties || !this.networkProperties.Cellular)
return;
var simLockStatus = this.networkProperties.Cellular.SIMLockStatus;
this.pukRequired_ =
!!simLockStatus && simLockStatus.LockType == CrOnc.LockType.PUK;
+ this.lockEnabled_ = simLockStatus.LockEnabled;
},
+ /** @private */
pukRequiredChanged_: function() {
if (this.$.unlockPukDialog.open) {
if (this.pukRequired_)
@@ -99,8 +112,7 @@ Polymer({
if (!showUnlockPuk)
return;
- this.error_ = ErrorType.NONE;
- this.$.unlockPukDialog.showModal();
+ this.showUnlockPukDialog_();
},
/**
@@ -113,8 +125,8 @@ Polymer({
return;
this.sendSimLockEnabled_ = event.target.checked;
this.error_ = ErrorType.NONE;
- this.$.enterPinDialog.showModal();
this.$.enterPin.value = '';
+ this.$.enterPinDialog.showModal();
},
/**
@@ -125,9 +137,10 @@ Polymer({
sendEnterPin_: function(event) {
var guid = (this.networkProperties && this.networkProperties.GUID) || '';
var pin = this.$.enterPin.value;
- if (!this.validatePin_(pin))
+ if (!this.validatePin_(pin)) {
+ this.onEnterPinDialogCancel_();
return;
-
+ }
var simState = /** @type {!CrOnc.CellularSimState} */ ({
currentPin: pin,
requirePin: this.sendSimLockEnabled_,
@@ -153,10 +166,10 @@ Polymer({
return;
event.preventDefault();
this.error_ = ErrorType.NONE;
- this.$.changePinDialog.showModal();
this.$.changePinOld.value = '';
this.$.changePinNew1.value = '';
this.$.changePinNew2.value = '';
+ this.$.changePinDialog.showModal();
},
/**
@@ -194,8 +207,8 @@ Polymer({
onUnlockPinTap_: function(event) {
event.preventDefault();
this.error_ = ErrorType.NONE;
- this.$.unlockPinDialog.showModal();
this.$.unlockPin.value = '';
+ this.$.unlockPinDialog.showModal();
},
/**
@@ -220,17 +233,13 @@ Polymer({
}.bind(this));
},
- /**
- * Opens the Unlock PUK dialog.
- * @param {Event} event
- * @private
- */
- unlockPuk_: function(event) {
+ /** @private */
+ showUnlockPukDialog_: function() {
this.error_ = ErrorType.NONE;
- this.$.unlockPukDialog.showModal();
this.$.unlockPuk.value = '';
this.$.unlockPin1.value = '';
this.$.unlockPin2.value = '';
+ this.$.unlockPukDialog.showModal();
},
/**
@@ -342,6 +351,27 @@ Polymer({
return false;
}
return true;
- }
+ },
+
+ /** @private */
+ onEnterPinDialogCancel_: function() {
+ this.lockEnabled_ =
+ this.networkProperties.Cellular.SIMLockStatus.LockEnabled;
+ },
+
+ /** @private */
+ onEnterPinDialogClose_: function() {
+ this.$$('#simLockButton').focus();
+ },
+
+ /** @private */
+ onChangePinDialogClose_: function() {
+ this.$$('#changePinButton').focus();
+ },
+
+ /** @private */
+ onUnlockPinDialogClose_: function() {
+ this.$$('#unlockPinButton').focus();
+ },
});
})();
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html
index fd3668d9e3c..e188e094f90 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -2,7 +2,6 @@
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_list_item.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
@@ -17,10 +16,6 @@
padding: 0 var(--settings-box-row-padding);
}
- .padded {
- @apply(--settings-list-frame-padding);
- }
-
#details {
align-items: center;
display: flex;
@@ -30,16 +25,9 @@
#details[no-flex] {
flex: none;
}
-
- #networkList {
- margin: 5px 0 10px;
- max-height: 200px;
- min-height: 50px;
- }
</style>
<div actionable class="settings-box two-line" on-tap="onShowDetailsTap_">
- <div id="details"
- no-flex$="[[showSimInfo_(deviceState)]]">
+ <div id="details" no-flex$="[[showSimInfo_(deviceState)]]">
<cr-network-list-item item="[[activeNetworkState]]" class="flex">
</cr-network-list-item>
</div>
@@ -53,15 +41,15 @@
<template is="dom-if" if="[[showDetailsIsVisible_(deviceState)]]">
<button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="[[getDetailsA11yString_(activeNetworkState,
- deviceSate)]]">
+ aria-label$="[[getDetailsA11yString_(activeNetworkState,
+ deviceState, networkStateList)]]">
</button>
</template>
<template is="dom-if" if="[[enableToggleIsVisible_(deviceState)]]">
<div class="secondary-action">
<paper-toggle-button id="deviceEnabledButton"
- aria-label="[[getToggleA11yString_(deviceState)]]"
+ aria-label$="[[getToggleA11yString_(deviceState)]]"
checked="[[deviceIsEnabled_(deviceState)]]"
enabled="[[enableToggleIsEnabled_(deviceState)]]"
on-tap="onDeviceEnabledTap_">
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
index 757487cba46..377c807b242 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -13,7 +13,7 @@ var DeviceStateProperties;
Polymer({
is: 'network-summary-item',
- behaviors: [Polymer.IronA11yKeysBehavior, I18nBehavior],
+ behaviors: [I18nBehavior],
properties: {
/**
@@ -159,12 +159,17 @@ Polymer({
* @private
*/
onShowDetailsTap_: function(event) {
- if (this.shouldShowList_())
+ if (!this.deviceIsEnabled_(this.deviceState)) {
+ this.fire(
+ 'device-enabled-toggled',
+ {enabled: true, type: this.deviceState.Type});
+ } else if (this.shouldShowList_()) {
this.fire('show-networks', this.deviceState);
- else if (this.activeNetworkState.GUID)
+ } else if (this.activeNetworkState.GUID) {
this.fire('show-detail', this.activeNetworkState);
- else if (this.networkStateList.length > 0)
+ } else if (this.networkStateList.length > 0) {
this.fire('show-detail', this.networkStateList[0]);
+ }
event.stopPropagation();
},
diff --git a/chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html b/chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
new file mode 100644
index 00000000000..b42d5012dd3
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.html
@@ -0,0 +1,80 @@
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="../icons.html">
+<link rel="import" href="../settings_shared_css.html">
+
+<dom-module id="tether-connection-dialog">
+ <template>
+ <style include="settings-shared">
+ .body,
+ #host-device-text-container {
+ display: flex;
+ flex-direction: column;
+ }
+
+ #host-device-container {
+ align-items: center;
+ display: flex;
+ }
+
+ iron-icon {
+ --iron-icon-fill-color: var(--google-blue-500);
+ }
+
+ #tether-explanation,
+ #tether-carrier-warning,
+ #tether-description-title {
+ margin-top: var(--settings-page-vertical-margin);
+ }
+ </style>
+ <dialog is="cr-dialog" id="dialog" on-cancel="onDialogCanceled_"
+ close-text="$i18n{close}" on-closed="onDialogCanceled_">
+ <div class="title">$i18n{tetherConnectionDialogTitle}</div>
+ <div class="body">
+ <div id="host-device-container">
+ <iron-icon icon="[[getReceptionIcon_(tetherData_)]]"></iron-icon>
+ <div id="host-device-text-container">
+ <span id="host-device-text-name">
+ [[tetherData_.tetherNostDeviceName]]
+ </span>
+ <span id="host-device-text-battery" class="secondary">
+ [[i18n('tetherConnectionBatteryPercentage',
+ tetherData_.batteryPercentage)]]
+ </span>
+ </div>
+ </div>
+ <div id="tether-explanation">
+ [[i18n('tetherConnectionExplanation', tetherData_.batteryPercentage)]]
+ </div>
+ <div id="tether-carrier-warning">
+ $i18n{tetherConnectionCarrierWarning}
+ </div>
+ <div id="tether-description-title">
+ [[i18n('tetherConnectionDescriptionTitle',
+ tetherData_.tetherNostDeviceName)]]
+ </div>
+ <ul>
+ <li>$i18n{tetherConnectionDescriptionCellData}</li>
+ <li>
+ [[i18n('tetherConnectionDescriptionBattery',
+ tetherData_.batteryPercentage)]]
+ </li>
+ <li hidden$="[[!tetherData_.isTetherHostCurrentlyOnWifi]]">
+ $i18n{tetherConnectionDescriptionWiFi}
+ </li>
+ </ul>
+ </div>
+ <div class="button-container">
+ <paper-button class="secondary-button" on-tap="onNotNowTap_">
+ $i18n{tetherConnectionNotNowButton}
+ </paper-button>
+ <paper-button class="primary-button" on-tap="close">
+ $i18n{tetherConnectionConnectButton}
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="tether_connection_dialog.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.js b/chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.js
new file mode 100644
index 00000000000..b949a58761e
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/internet_page/tether_connection_dialog.js
@@ -0,0 +1,81 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @typedef {{
+ * tetherNostDeviceName: string,
+ * batteryPercentage: number,
+ * connectionStrength: number,
+ * isTetherHostCurrentlyOnWifi: boolean
+ * }}
+ */
+var TetherConnectionData;
+
+Polymer({
+ is: 'tether-connection-dialog',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /**
+ * The data used to display the tether connection dialog.
+ * @private {!TetherConnectionData|undefined}
+ */
+ tetherData_: {
+ type: Object,
+ // TODO(khorimoto): Remove this and use real data when available.
+ value: {
+ tetherNostDeviceName: 'Pixel XL',
+ batteryPercentage: 100,
+ connectionStrength: 4,
+ isTetherHostCurrentlyOnWifi: false
+ },
+ },
+ },
+
+ open: function() {
+ var dialog = this.getDialog_();
+ if (!dialog.open)
+ this.getDialog_().showModal();
+ },
+
+ close: function() {
+ var dialog = this.getDialog_();
+ if (dialog.open)
+ dialog.close();
+ },
+
+ /**
+ * @return {!CrDialogElement}
+ * @private
+ */
+ getDialog_: function() {
+ return /** @type {!CrDialogElement} */ (this.$.dialog);
+ },
+
+ /** @private */
+ onNotNowTap_: function() {
+ this.getDialog_().cancel();
+ },
+
+ /**
+ * @param {!TetherConnectionData|undefined} tetherData
+ * @return {string}
+ * @private
+ */
+ getReceptionIcon_: function(tetherData) {
+ var connectionStrength;
+
+ if (!tetherData || !tetherData.connectionStrength) {
+ connectionStrength = 0;
+ } else {
+ // Ensure that 0 <= connectionStrength <= 4, since these values are the
+ // limits of the cellular strength icons.
+ connectionStrength =
+ Math.min(Math.max(tetherData.connectionStrength, 0), 4);
+ }
+
+ return 'settings:signal-cellular-' + connectionStrength + '-bar';
+ }
+});
diff --git a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
index 332323927da..2b966234656 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
@@ -1,44 +1,58 @@
+<link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="languages.html">
+<link rel="import" href="../settings_page/settings_subpage_search.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="settings-add-languages-dialog">
<template>
<style include="settings-shared">
- dialog {
- display: flex;
- flex-direction: column;
- }
-
.body {
+ -webkit-padding-end: 0 !important;
display: flex;
flex-direction: column;
- max-height: 250px;
+ height: 350px;
overflow: auto;
}
+ settings-subpage-search {
+ -webkit-padding-end: 24px;
+ }
+
+ iron-list {
+ flex: 1;
+ }
+
.ripple-padding {
/* Create a little extra space for checkbox ink ripple to flow into. */
-webkit-padding-start: 20px;
}
+
+ paper-checkbox {
+ --paper-checkbox-label: {
+ white-space: nowrap;
+ }
+ }
</style>
<dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
<div class="title">$i18n{addLanguagesDialogTitle}</div>
- <div class="body">
- <!-- TODO(michaelpg): Dynamic language search/filtering. -->
+ <div class="body" scrollable>
+ <settings-subpage-search label="[[searchLabel]]"
+ on-search-changed="onSearchChanged_" autofocus>
+ </settings-subpage-search>
<iron-list class="ripple-padding" scroll-target="[[$$('.body')]]"
- items="[[getAvailableLanguages_(
- languages.supported, languages.enabled.*)]]">
+ items="[[getLanguages_(
+ languages.supported, languages.enabled.*, filterValue_)]]">
<template>
- <paper-checkbox class="list-item" checked="[[willAdd_(item.code)]]"
+ <paper-checkbox class="list-item no-outline"
+ checked="[[willAdd_(item.code)]]" tabindex$="[[tabIndex]]"
title$="[[item.nativeDisplayName]]"
- on-change="onLanguageCheckboxChange_"
- tabindex$="[[tabIndex]]">
- [[item.displayName]]
+ on-change="onLanguageCheckboxChange_">
+ [[getDisplayText_(item)]]
</paper-checkbox>
</template>
</iron-list>
diff --git a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js
index 8c687d7ea02..dc0e2b8e707 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js
@@ -9,6 +9,10 @@
Polymer({
is: 'settings-add-languages-dialog',
+ behaviors: [
+ CrScrollableBehavior,
+ ],
+
properties: {
/** @type {!LanguagesModel|undefined} */
languages: {
@@ -22,7 +26,9 @@ Polymer({
/** @private {!Set<string>} */
languagesToAdd_: {
type: Object,
- value: function() { return new Set(); },
+ value: function() {
+ return new Set();
+ },
},
/** @private */
@@ -30,48 +36,64 @@ Polymer({
type: Boolean,
value: true,
},
+
+ /** @private */
+ filterValue_: {
+ type: String,
+ value: '',
+ },
},
+ /** @override */
attached: function() {
this.$.dialog.showModal();
-
- // Prevent flashing the Cancel button's focus state.
- this.$$('.cancel-button').blur();
- setTimeout(this.afterShown_.bind(this));
},
/**
- * Re-initializes the dialog after it is shown.
+ * @param {!CustomEvent} e
* @private
*/
- afterShown_: function() {
- // Only fire iron-resize after the list displayed to prevent flickering.
- this.$$('iron-list').fire('iron-resize');
-
- // Focus the top checkbox, assuming there are languages left to enable.
- var firstCheckbox = this.$$('iron-list paper-checkbox');
- if (firstCheckbox)
- firstCheckbox.focus();
+ onSearchChanged_: function(e) {
+ this.filterValue_ = /** @type {string} */ (e.detail);
},
/**
- * Returns the supported languages that are not yet enabled, based on
- * the LanguageHelper's enabled languages list.
- * @param {!Array<!chrome.languageSettingsPrivate.Language>}
- * supportedLanguages
- * @param {!Object} enabledLanguagesChange Polymer change record for
- * |enabledLanguages|.
- * @return {!Array<!chrome.languageSettingsPrivate.Language>}
+ * @return {!Array<!chrome.languageSettingsPrivate.Language>} A list of
+ * languages to be displayed.
* @private
*/
- getAvailableLanguages_: function(supportedLanguages, enabledLanguagesChange) {
- return supportedLanguages.filter(function(language) {
- return !this.languageHelper.isLanguageEnabled(language.code);
+ getLanguages_: function() {
+ return this.languages.supported.filter(function(language) {
+ var isAvailableLanguage =
+ !this.languageHelper.isLanguageEnabled(language.code);
+
+ if (!isAvailableLanguage)
+ return false;
+
+ if (!this.filterValue_)
+ return isAvailableLanguage;
+
+ return language.displayName.toLowerCase().includes(
+ this.filterValue_.toLowerCase());
}.bind(this));
},
/**
+ * @param {!chrome.languageSettingsPrivate.Language} language
+ * @return {string} The text to be displayed.
+ * @private
+ */
+ getDisplayText_: function(language) {
+ var displayText = language.displayName;
+ // If the native name is different, add it.
+ if (language.displayName != language.nativeDisplayName)
+ displayText += ' - ' + language.nativeDisplayName;
+ return displayText;
+ },
+
+ /**
* True if the user has chosen to add this language (checked its checkbox).
+ * @param {string} languageCode
* @return {boolean}
* @private
*/
@@ -90,11 +112,11 @@ Polymer({
// willAdd_ is called to initialize the checkbox state (in case the
// iron-list re-uses a previous checkbox), and the checkbox can only be
// changed after that by user action.
- var code = e.model.item.code;
+ var language = e.model.item;
if (e.target.checked)
- this.languagesToAdd_.add(code);
+ this.languagesToAdd_.add(language.code);
else
- this.languagesToAdd_.delete(code);
+ this.languagesToAdd_.delete(language.code);
this.disableActionButton_ = !this.languagesToAdd_.size;
},
@@ -110,8 +132,8 @@ Polymer({
*/
onActionButtonTap_: function() {
this.$.dialog.close();
- this.languagesToAdd_.forEach(function(language) {
- this.languageHelper.enableLanguage(language);
+ this.languagesToAdd_.forEach(function(languageCode) {
+ this.languageHelper.enableLanguage(languageCode);
}.bind(this));
},
});
diff --git a/chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
index 164f93e97d9..8450323bb11 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
@@ -62,6 +62,7 @@
'target_name': 'add_languages_dialog',
'dependencies': [
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-checkbox/compiled_resources2.gyp:paper-checkbox-extracted',
+ '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_scrollable_behavior',
'languages',
'languages_types',
],
diff --git a/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html b/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
index 58585d3e5c4..67d72119b8c 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
@@ -5,6 +5,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="../global_scroll_target_behavior.html">
<link rel="import" href="../prefs/prefs.html">
<link rel="import" href="../prefs/prefs_behavior.html">
<link rel="import" href="../settings_shared_css.html">
@@ -19,14 +20,6 @@
#newWord {
width: var(--paper-input-max-width);
- --paper-input-container-label: {
- font-size: inherit;
- };
- }
-
- iron-list {
- /* TODO(michaelpg): Size to fit the viewport. */
- height: 300px;
}
iron-list .word {
@@ -51,25 +44,26 @@
</div>
<div class="settings-box continuation block">
<h2>$i18n{customDictionaryWords}</h2>
- <div class="list-frame">
- <template is="dom-if" if="[[hasWords_(words_.length)]]">
- <iron-list id="list" items="{{words_}}">
- <template>
- <div class="list-item">
- <div class="word text-elide">[[item]]</div>
- <paper-icon-button icon="cr:clear" on-tap="onRemoveWordTap_"
- tabindex$="[[tabIndex]]">
- </paper-icon-button>
- </div>
- </template>
- </iron-list>
- </template>
- <template is="dom-if" if="[[!hasWords_(words_.length)]]">
- <div id="noWordsLabel" class="list-item">
- $i18n{noCustomDictionaryWordsFound}
- </div>
- </template>
- </div>
+ </div>
+ <div class="list-frame">
+ <template is="dom-if" if="[[hasWords_(words_.length)]]">
+ <iron-list id="list" items="{{words_}}"
+ scroll-target="[[subpageScrollTarget]]">
+ <template>
+ <div class="list-item">
+ <div class="word text-elide">[[item]]</div>
+ <paper-icon-button icon="cr:clear" on-tap="onRemoveWordTap_"
+ tabindex$="[[tabIndex]]">
+ </paper-icon-button>
+ </div>
+ </template>
+ </iron-list>
+ </template>
+ <template is="dom-if" if="[[!hasWords_(words_.length)]]">
+ <div id="noWordsLabel" class="list-item">
+ $i18n{noCustomDictionaryWordsFound}
+ </div>
+ </template>
</div>
</template>
<script src="edit_dictionary_page.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.js b/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.js
index c8c3939de95..840368e1034 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.js
@@ -9,10 +9,21 @@
Polymer({
is: 'settings-edit-dictionary-page',
+ behaviors: [settings.GlobalScrollTargetBehavior],
+
properties: {
/** @private {string} */
newWordValue_: String,
+ /**
+ * Needed by GlobalScrollTargetBehavior.
+ * @override
+ */
+ subpageRoute: {
+ type: Object,
+ value: settings.Route.EDIT_DICTIONARY,
+ },
+
/** @private {!Array<string>} */
words_: {
type: Array,
@@ -110,15 +121,17 @@ Polymer({
var index = this.words_.indexOf(word);
if (index == -1) {
this.languageSettingsPrivate.addSpellcheckWord(word);
- this.push('words_', word);
- index = this.words_.length - 1;
+ this.unshift('words_', word);
+ if (this.words_.length == 1) {
+ // When adding a word to an _empty_ list, the template is expanded. This
+ // is a workaround to resize the iron-list as well.
+ // TODO(dschuyler): Remove this hack after iron-list no longer needs
+ // this workaround to update the list at the same time the template
+ // wrapping the list is expanded.
+ Polymer.dom.flush();
+ this.$$('#list').notifyResize();
+ }
}
-
- // Scroll to the word (usually the bottom, or to the index if the word
- // is already present).
- this.async(function(){
- this.root.querySelector('#list').scrollToIndex(index);
- });
},
/**
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages.js b/chromium/chrome/browser/resources/settings/languages_page/languages.js
index e713a964228..40d9eb021d8 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages.js
@@ -145,8 +145,11 @@ Polymer({
'languages)',
],
+ /** @private {?Function} */
+ boundOnInputMethodChanged_: null,
+
/** @override */
- created: function() {
+ attached: function() {
this.languageSettingsPrivate =
settings.languageSettingsPrivateApiForTest ||
/** @type {!LanguageSettingsPrivate} */(chrome.languageSettingsPrivate);
@@ -195,13 +198,29 @@ Polymer({
}
Promise.all(promises).then(function(results) {
+ if (!this.isConnected) {
+ // Return early if this element was detached from the DOM before this
+ // async callback executes (can happen during testing).
+ return;
+ }
+
this.createModel_(results[1], results[2], results[3], results[4]);
this.resolver_.resolve();
}.bind(this));
if (cr.isChromeOS) {
+ this.boundOnInputMethodChanged_ = this.onInputMethodChanged_.bind(this);
this.inputMethodPrivate.onChanged.addListener(
- this.onInputMethodChanged_.bind(this));
+ assert(this.boundOnInputMethodChanged_));
+ }
+ },
+
+ /** @override */
+ detached: function() {
+ if (cr.isChromeOS) {
+ this.inputMethodPrivate.onChanged.removeListener(
+ assert(this.boundOnInputMethodChanged_));
+ this.boundOnInputMethodChanged_ = null;
}
},
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages_page.html b/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
index acf1628c244..111cc244684 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -7,6 +7,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
@@ -70,7 +71,8 @@
<settings-languages languages="{{languages}}" prefs="{{prefs}}"
language-helper="{{languageHelper}}">
</settings-languages>
- <settings-animated-pages id="pages" section="languages">
+ <settings-animated-pages id="pages" section="languages"
+ focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<div class$="settings-box first [[getLanguageListTwoLine_()]]"
actionable on-tap="toggleExpandButton_">
@@ -178,12 +180,13 @@
</paper-icon-button>
</div>
</template>
- <div class="list-item">
- <a is="action-link" class="list-button"
- id="manageInputMethods"
- on-tap="onManageInputMethodsTap_">
+ <div class="list-item" on-tap="onManageInputMethodsTap_" actionable>
+ <div class="start" id="manageInputMethods">
$i18n{manageInputMethods}
- </a>
+ </div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{manageInputMethods}"
+ aria-describedby="customSpelling"></button>
</div>
</div>
<div class="settings-box">
@@ -222,11 +225,13 @@
</paper-toggle-button>
</div>
</template>
- <div class="list-item">
- <a is="action-link" class="list-button"
- on-tap="onEditDictionaryTap_">
+ <div class="list-item" on-tap="onEditDictionaryTap_" actionable>
+ <div class="start" id="customSpelling">
$i18n{manageSpellCheck}
- </a>
+ </div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{manageSpellCheck}"
+ aria-describedby="customSpelling"></button>
</div>
</div>
</iron-collapse>
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages_page.js b/chromium/chrome/browser/resources/settings/languages_page/languages_page.js
index 429e2e31223..a04ef195710 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages_page.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -58,6 +58,25 @@ Polymer({
/** @private */
showAddLanguagesDialog_: Boolean,
+
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+// <if expr="not is_macosx">
+ map.set(
+ settings.Route.EDIT_DICTIONARY.path,
+ '#spellCheckCollapse .subpage-arrow');
+// </if>
+// <if expr="chromeos">
+ map.set(
+ settings.Route.INPUT_METHODS.path,
+ '#inputMethodsCollapse .subpage-arrow');
+// </if>
+ return map;
+ },
+ },
},
/**
@@ -91,6 +110,7 @@ Polymer({
var dialog = this.$$('settings-add-languages-dialog');
dialog.addEventListener('close', function() {
this.showAddLanguagesDialog_ = false;
+ this.$.addLanguages.focus();
}.bind(this));
});
},
diff --git a/chromium/chrome/browser/resources/settings/lazy_load.html b/chromium/chrome/browser/resources/settings/lazy_load.html
new file mode 100644
index 00000000000..2853b3c1eae
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/lazy_load.html
@@ -0,0 +1,15 @@
+<link rel="import" href="a11y_page/a11y_page.html">
+<link rel="import" href="downloads_page/downloads_page.html">
+<link rel="import" href="languages_page/languages_page.html">
+<link rel="import" href="passwords_and_forms_page/passwords_and_forms_page.html">
+<link rel="import" href="printing_page/printing_page.html">
+<link rel="import" href="privacy_page/privacy_page.html">
+<link rel="import" href="reset_page/reset_page.html">
+
+<if expr="chromeos">
+<link rel="import" href="date_time_page/date_time_page.html">
+</if>
+
+<if expr="not chromeos">
+<link rel="import" href="system_page/system_page.html">
+</if>
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp
index b937368b823..8287c382830 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp
@@ -46,6 +46,7 @@
'<(DEPTH)/ui/webui/resources/cr_elements/cr_lazy_render/compiled_resources2.gyp:cr_lazy_render',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
+ '../compiled_resources2.gyp:focus_row_behavior',
'startup_urls_page_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/on_startup_page.html b/chromium/chrome/browser/resources/settings/on_startup_page/on_startup_page.html
index 940c0530989..9d5f504a970 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/on_startup_page.html
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/on_startup_page.html
@@ -14,8 +14,9 @@
<settings-radio-group id="onStartupRadioGroup"
pref="{{prefs.session.restore_on_startup}}">
<controlled-radio-button name="[[prefValues_.OPEN_NEW_TAB]]"
- pref="[[prefs.session.restore_on_startup]]">
- $i18n{onStartupOpenNewTab}
+ pref="[[prefs.session.restore_on_startup]]"
+ label="$i18n{onStartupOpenNewTab}"
+ no-extension-indicator>
</controlled-radio-button>
<template is="dom-if" if="[[showIndicator_(
ntpExtension_, prefs.session.restore_on_startup.value)]]">
@@ -27,12 +28,12 @@
</extension-controlled-indicator>
</template>
<controlled-radio-button name="[[prefValues_.CONTINUE]]"
- pref="[[prefs.session.restore_on_startup]]">
- $i18n{onStartupContinue}
+ pref="[[prefs.session.restore_on_startup]]"
+ label="$i18n{onStartupContinue}">
</controlled-radio-button>
<controlled-radio-button name="[[prefValues_.OPEN_SPECIFIC]]"
- pref="[[prefs.session.restore_on_startup]]">
- $i18n{onStartupOpenSpecific}
+ pref="[[prefs.session.restore_on_startup]]"
+ label="$i18n{onStartupOpenSpecific}">
</controlled-radio-button>
</settings-radio-group>
</div>
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html
index 534ae38693b..796d30b661e 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html
@@ -12,8 +12,7 @@
<div class="title">[[dialogTitle_]]</div>
<div class="body">
<paper-input always-float-label id="url" label="$i18n{onStartupSiteUrl}"
- value="{{url_}}" on-input="validate_" on-keypress="onKeypress_"
- autofocus>
+ value="{{url_}}" on-input="validate_" autofocus>
</paper-input>
</div>
<div class="button-container">
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.js b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.js
index 3b576580d14..706bf18fcb5 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.js
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.js
@@ -67,15 +67,6 @@ Polymer({
}.bind(this));
},
- /**
- * @param {!KeyboardEvent} e
- * @private
- */
- onKeypress_: function(e) {
- if (e.key == 'Enter' && !this.$.actionButton.disabled)
- this.onActionButtonTap_();
- },
-
/** @private */
validate_: function() {
this.browserProxy_.validateStartupPage(this.url_).then(function(isValid) {
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html
index 1a68b89d2e7..10136a4aa35 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html
@@ -5,6 +5,7 @@
<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="startup_urls_page_browser_proxy.html">
+<link rel="import" href="../focus_row_behavior.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="settings-startup-url-entry">
@@ -14,7 +15,7 @@
overflow: hidden;
}
</style>
- <div class="list-item">
+ <div class="list-item" focus-row-container>
<div class="favicon-image"
style="background-image: [[getIconSet_(model.url)]]">
</div>
@@ -23,9 +24,8 @@
<div class="text-elide secondary">[[model.url]]</div>
</div>
<template is="dom-if" if="[[editable]]">
- <paper-icon-button id="dots" icon="cr:more-vert"
- tabindex$="[[tabindex]]" on-tap="onDotsTap_"
- title="$i18n{moreActions}">
+ <paper-icon-button id="dots" icon="cr:more-vert" on-tap="onDotsTap_"
+ title="$i18n{moreActions}" focus-row-control focus-type="menu">
</paper-icon-button>
<template is="cr-lazy-render" id="menu">
<dialog is="cr-action-menu">
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js
index 27de5f0e600..2c582027c26 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js
@@ -20,6 +20,8 @@ settings.EDIT_STARTUP_URL_EVENT = 'edit-startup-url';
Polymer({
is: 'settings-startup-url-entry',
+ behaviors: [FocusRowBehavior],
+
properties: {
editable: {
type: Boolean,
@@ -53,7 +55,10 @@ Polymer({
onEditTap_: function(e) {
e.preventDefault();
this.$$('dialog[is=cr-action-menu]').close();
- this.fire(settings.EDIT_STARTUP_URL_EVENT, this.model);
+ this.fire(settings.EDIT_STARTUP_URL_EVENT, {
+ model: this.model,
+ anchor: this.$$('#dots'),
+ });
},
/** @private */
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html b/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
index 877bddf7374..451ca112c15 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html
@@ -23,8 +23,7 @@
border-top: var(--settings-separator-line);
}
- #container settings-startup-url-entry:not([editable]) {
- background: none;
+ #container settings-startup-url-entry {
cursor: default;
}
</style>
@@ -33,7 +32,8 @@
<iron-list items="[[startupPages_]]" scroll-target="container">
<template>
<settings-startup-url-entry model="[[item]]"
- tabindex$="[[tabIndex]]"
+ tabindex$="[[tabIndex]]" iron-list-tab-index="[[tabIndex]]"
+ last-focused="{{lastFocused_}}"
editable="[[!prefs.session.startup_urls.controlledBy]]">
</settings-startup-url-entry>
</template>
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js b/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js
index d7b8ee023f7..c17ed77f632 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js
@@ -15,9 +15,6 @@ Polymer({
properties: {
prefs: Object,
- /** @type {settings.StartupUrlsPageBrowserProxy} */
- browserProxy_: Object,
-
/**
* Pages to load upon browser startup.
* @private {!Array<!StartupPageInfo>}
@@ -29,8 +26,20 @@ Polymer({
/** @private {?StartupPageInfo} */
startupUrlDialogModel_: Object,
+
+ /** @private {Object}*/
+ lastFocused_: Object,
},
+ /** @private {?settings.StartupUrlsPageBrowserProxy} */
+ browserProxy_: null,
+
+ /**
+ * The element to return focus to, when the startup-url-dialog is closed.
+ * @private {?HTMLElement}
+ */
+ startupUrlDialogAnchor_: null,
+
/** @override */
attached: function() {
this.browserProxy_ = settings.StartupUrlsPageBrowserProxyImpl.getInstance();
@@ -45,7 +54,8 @@ Polymer({
this.browserProxy_.loadStartupPages();
this.addEventListener(settings.EDIT_STARTUP_URL_EVENT, function(event) {
- this.startupUrlDialogModel_ = event.detail;
+ this.startupUrlDialogModel_ = event.detail.model;
+ this.startupUrlDialogAnchor_ = event.detail.anchor;
this.showStartupUrlDialog_ = true;
event.stopPropagation();
}.bind(this));
@@ -58,12 +68,18 @@ Polymer({
onAddPageTap_: function(e) {
e.preventDefault();
this.showStartupUrlDialog_ = true;
+ this.startupUrlDialogAnchor_ = /** @type {!HTMLElement} */ (
+ this.$$('#addPage a[is=action-link]'));
},
/** @private */
destroyUrlDialog_: function() {
this.showStartupUrlDialog_ = false;
this.startupUrlDialogModel_ = null;
+ if (this.startupUrlDialogAnchor_) {
+ this.startupUrlDialogAnchor_.focus();
+ this.startupUrlDialogAnchor_ = null;
+ }
},
/** @private */
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html
index e78bb988140..37f31c765f6 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html
@@ -1,9 +1,9 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-textarea.html">
<link rel="import" href="../settings_shared_css.html">
@@ -12,6 +12,13 @@
<dom-module id="settings-address-edit-dialog">
<template>
<style include="settings-shared md-select">
+ :host {
+ --iron-autogrow-textarea: {
+ box-sizing: border-box;
+ padding: 0;
+ };
+ }
+
.address-row {
display: flex;
}
@@ -22,18 +29,27 @@
width: calc((var(--paper-input-max-width) - 16px) / 2);
}
- .md-select.address-column {
- -webkit-margin-end: 0;
- margin-bottom: 0;
- }
-
#select-row {
display: block;
}
+ .md-select-wrapper {
+ /* Mitigate for md-select's start padding, to make it look aligned with
+ * other elements on the page. */
+ -webkit-margin-start: -12px;
+ }
+
+ .md-select {
+ --md-select-width: var(--paper-input-max-width);
+ }
+
#select-label {
- color: var(--light-theme-secondary-color);
- font-size: 12px
+ /* Mimic other paper-input floating labels. */
+ color: var(--light-theme-secondary-color);
+ transform: scale(0.75);
+ transform-origin: left;
+ width: 133%;
+ @apply(--paper-input-container-label-floating);
}
.long {
@@ -44,17 +60,32 @@
-webkit-margin-start: 8px;
}
- #dialog .body {
- max-height: 450px;
+ #dialog {
+ --cr-dialog-body-container: {
+ max-height: 450px;
+ };
}
@media all and (max-height: 714px) {
- #dialog .body {
- max-height: 270px;
+ #dialog {
+ --cr-dialog-body-container: {
+ max-height: 270px;
+ };
}
}
+
+ paper-textarea {
+ /**
+ * Workaround for iron-autogrow-textarea's display:inline-block creating
+ * too much vertical space than intended.
+ */
+ --layout-relative : {
+ line-height: 1;
+ };
+ }
</style>
- <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
+ <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"
+ show-scroll-borders>
<div class="title">[[title_]]</div>
<div class="body">
<template is="dom-repeat" items="[[addressWrapper_]]">
@@ -72,9 +103,6 @@
always-float-label autofocus value="{{item.value}}"
on-value-changed="updateCanSave_"
class$="address-column [[long_(item)]]">
- <iron-a11y-keys keys="enter"
- on-keys-pressed="onSaveButtonTap_">
- </iron-a11y-keys>
</paper-input>
</template>
</template>
@@ -83,8 +111,8 @@
<div id="select-row" class="address-row">
<div id="select-label">$i18n{addressCountry}</div>
<span class="md-select-wrapper">
- <select class="md-select address-column long"
- value="[[countryCode_]]" on-change="onCountryChange_">
+ <select class="md-select" aria-labelledby="select-label"
+ value="[[countryCode_]]" on-change="onCountryChange_">
<option value=""></option>
<template is="dom-repeat" items="[[countries_]]">
<option value="[[getCode_(item)]]"
@@ -97,8 +125,6 @@
</span>
</div>
<div class="address-row">
- <iron-a11y-keys keys="enter" on-keys-pressed="onSaveButtonTap_">
- </iron-a11y-keys>
<paper-input id="phoneInput" type="text" label="$i18n{addressPhone}"
always-float-label class="address-column"
on-value-changed="updateCanSave_" value="{{phoneNumber_}}">
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js
index 502d07a6a19..06e84498c47 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js
@@ -113,7 +113,7 @@ Polymer({
},
updateCanSave_: function() {
- var inputs = this.$.dialog.querySelectorAll('.address-column');
+ var inputs = this.$.dialog.querySelectorAll('.address-column, select');
for (var i = 0; i < inputs.length; ++i) {
if (inputs[i].value) {
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
index fd464fcc022..45c69f23c67 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
@@ -1,10 +1,14 @@
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/html/action_link.html">
<link rel="import" href="chrome://resources/html/action_link_css.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="../controls/extension_controlled_indicator.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
+<link rel="import" href="../prefs/prefs.html">
<link rel="import" href="address_edit_dialog.html">
<link rel="import" href="credit_card_edit_dialog.html">
<link rel="import" href="passwords_shared_css.html">
@@ -52,8 +56,27 @@
}
</style>
<div class="settings-box first">
+ <settings-toggle-button id="autofillToggle" class="start primary-toggle"
+ aria-label="$i18n{autofill}" no-extension-indicator
+ label="[[getOnOffLabel_(prefs.autofill.enabled.value)]]"
+ pref="{{prefs.autofill.enabled}}">
+ </settings-toggle-button>
+ </div>
+ <template is="dom-if" if="[[prefs.autofill.enabled.extensionId]]">
+ <div class="settings-box continuation">
+ <extension-controlled-indicator class="start"
+ id="autofillExtensionIndicator"
+ extension-id="[[prefs.autofill.enabled.extensionId]]"
+ extension-name="[[prefs.autofill.enabled.controlledByName]]"
+ extension-can-be-disabled="[[
+ prefs.autofill.enabled.extensionCanBeDisabled]]">
+ </extension-controlled-indicator>
+ </div>
+ </template>
+ <div class="settings-box continuation">
<h2 class="start">$i18n{addresses}</h2>
- <paper-button class="secondary-button header-aligned-button"
+ <paper-button id="addAddress"
+ class="secondary-button header-aligned-button"
on-tap="onAddAddressTap_">
$i18n{add}
</paper-button>
@@ -105,7 +128,8 @@
</template>
<div class="settings-box first">
<h2 class="start">$i18n{creditCards}</h2>
- <paper-button class="secondary-button header-aligned-button"
+ <paper-button id="addCreditCard"
+ class="secondary-button header-aligned-button"
on-tap="onAddCreditCardTap_">
$i18n{add}
</paper-button>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
index ebda21bd5eb..cc1a2d8a72f 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
@@ -191,6 +191,13 @@ AutofillManagerImpl.prototype = {
},
/**
+ * The element to return focus to, when the currently active dialog is
+ * closed.
+ * @private {?HTMLElement}
+ */
+ activeDialogAnchor_: null,
+
+ /**
* @type {AutofillManager}
* @private
*/
@@ -209,7 +216,7 @@ AutofillManagerImpl.prototype = {
setCreditCardsListener_: null,
/** @override */
- ready: function() {
+ attached: function() {
// Create listener functions.
/** @type {function(!Array<!AutofillManager.AddressEntry>)} */
var setAddressesListener = function(list) {
@@ -277,6 +284,7 @@ AutofillManagerImpl.prototype = {
var dotsButton = /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget);
/** @type {!CrActionMenuElement} */ (
this.$.addressSharedMenu).showAt(dotsButton);
+ this.activeDialogAnchor_ = dotsButton;
},
/**
@@ -288,11 +296,14 @@ AutofillManagerImpl.prototype = {
e.preventDefault();
this.activeAddress = {};
this.showAddressDialog_ = true;
+ this.activeDialogAnchor_ = this.$.addAddress;
},
/** @private */
onAddressDialogClosed_: function() {
this.showAddressDialog_ = false;
+ this.activeDialogAnchor_.focus();
+ this.activeDialogAnchor_ = null;
},
/**
@@ -341,6 +352,7 @@ AutofillManagerImpl.prototype = {
var dotsButton = /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget);
/** @type {!CrActionMenuElement} */ (
this.$.creditCardSharedMenu).showAt(dotsButton);
+ this.activeDialogAnchor_ = dotsButton;
},
/**
@@ -357,11 +369,14 @@ AutofillManagerImpl.prototype = {
expirationYear: date.getFullYear().toString(),
};
this.showCreditCardDialog_ = true;
+ this.activeDialogAnchor_ = this.$.addCreditCard;
},
/** @private */
onCreditCardDialogClosed_: function() {
this.showCreditCardDialog_ = false;
+ this.activeDialogAnchor_.focus();
+ this.activeDialogAnchor_ = null;
},
/**
@@ -427,5 +442,14 @@ AutofillManagerImpl.prototype = {
saveCreditCard_: function(event) {
this.autofillManager_.saveCreditCard(event.detail);
},
+
+ /**
+ * @private
+ * @param {boolean} toggleValue
+ * @return {string}
+ */
+ getOnOffLabel_: function(toggleValue) {
+ return toggleValue ? this.i18n('toggleOn') : this.i18n('toggleOff');
+ }
});
})();
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp
index 3341d4a5022..d56031218f4 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp
@@ -22,6 +22,7 @@
'target_name': 'autofill_section',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):autofill_private',
'address_edit_dialog',
'credit_card_edit_dialog',
@@ -50,6 +51,7 @@
'dependencies': [
'../compiled_resources2.gyp:global_scroll_target_behavior',
'<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):passwords_private',
'password_edit_dialog',
],
@@ -58,6 +60,7 @@
{
'target_name': 'password_edit_dialog',
'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
'<(EXTERNS_GYP):passwords_private',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
index c58be1787fe..0408217a808 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
@@ -2,7 +2,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="../settings_vars_css.html">
@@ -14,8 +13,14 @@
width: var(--paper-input-max-width);
}
+ .md-select-wrapper {
+ /* Mitigate for md-select's start padding, to make it look aligned with
+ * other elements on the page. */
+ -webkit-margin-start: -12px;
+ }
+
.md-select-wrapper + .md-select-wrapper {
- -webkit-margin-start: 16px;
+ -webkit-margin-start: 8px;
}
#expired {
@@ -46,22 +51,19 @@
<dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
<div class="title">[[title_]]</div>
<div class="body">
- <div>
- <iron-a11y-keys keys="enter" on-keys-pressed="onSaveButtonTap_">
- </iron-a11y-keys>
- <paper-input id="nameInput" label="$i18n{creditCardName}"
- value="{{creditCard.name}}" always-float-label autofocus
- on-input="onCreditCardNameOrNumberChanged_">
- </paper-input>
- <paper-input id="numberInput" label="$i18n{creditCardNumber}"
- value="{{creditCard.cardNumber}}" always-float-label
- on-input="onCreditCardNameOrNumberChanged_">
- </paper-input>
- </div>
+ <paper-input id="nameInput" label="$i18n{creditCardName}"
+ value="{{creditCard.name}}" always-float-label autofocus
+ on-input="onCreditCardNameOrNumberChanged_">
+ </paper-input>
+ <paper-input id="numberInput" label="$i18n{creditCardNumber}"
+ value="{{creditCard.cardNumber}}" always-float-label
+ on-input="onCreditCardNameOrNumberChanged_">
+ </paper-input>
<label>$i18n{creditCardExpiration}</label>
<span class="md-select-wrapper">
<select class="md-select" id="month" value="[[expirationMonth_]]"
- on-change="onMonthChange_">
+ on-change="onMonthChange_"
+ aria-label="$i18n{creditCardExpirationMonth}">
<template is="dom-repeat" items="[[monthList_]]">
<option>[[item]]</option>
</template>
@@ -70,7 +72,8 @@
</span>
<span class="md-select-wrapper">
<select class="md-select" id="year" value="[[expirationYear_]]"
- on-change="onYearChange_">
+ on-change="onYearChange_"
+ aria-label="$i18n{creditCardExpirationYear}">
<template is="dom-repeat" items="[[yearList_]]">
<option>[[item]]</option>
</template>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
index 57539bbc64e..bb501574384 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
@@ -9,6 +9,20 @@
<dom-module id="password-edit-dialog">
<template>
<style include="settings-shared">
+ paper-input[readonly] {
+ /* Lighter than label to appear uneditable. */
+ color: var(--paper-grey-500);
+
+ /* For readonly inputs we don't want to show focus styles. */
+ --paper-input-container-underline-focus: {
+ display: none;
+ };
+
+ --paper-input-container-label-focus: {
+ color: var(--paper-input-container-color, --secondary-text-color);
+ };
+ }
+
#passwordGroup {
align-items: center;
display: flex;
@@ -26,16 +40,19 @@
<div class="title">$i18n{passwordDetailsTitle}</div>
<div class="body">
<paper-input id="websiteInput" label="$i18n{editPasswordWebsiteLabel}"
- value="[[item.loginPair.originUrl]]" readonly>
+ value="[[item.loginPair.urls.link]]" readonly always-float-label
+ on-tap="onReadonlyInputTap_">
</paper-input>
<paper-input id="usernameInput" label="$i18n{editPasswordUsernameLabel}"
- value="[[item.loginPair.username]]" readonly>
+ value="[[item.loginPair.username]]" readonly always-float-label
+ on-tap="onReadonlyInputTap_">
</paper-input>
<div id="passwordGroup">
- <paper-input id="passwordInput"
+ <paper-input id="passwordInput" always-float-label
label="$i18n{editPasswordPasswordLabel}"
type="[[getPasswordInputType_(password)]]"
- value="[[getPassword_(item, password)]]" readonly>
+ value="[[getPassword_(item, password)]]" readonly
+ on-tap="onReadonlyInputTap_">
</paper-input>
<paper-icon-button id="showPasswordButton"
icon="settings:visibility" on-tap="onShowPasswordButtonTap_"
@@ -45,8 +62,9 @@
</div>
</div>
<div class="button-container">
- <paper-button id="cancelButton" class="cancel-button"
- on-tap="onCancelButtonTap_">$i18n{passwordsDone}</paper-button>
+ <paper-button class="action-button" on-tap="onActionButtonTap_">
+ $i18n{passwordsDone}
+ </paper-button>
</div>
</dialog>
</template>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js
index bfa1e2d2839..cb9aa3f7adb 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js
@@ -82,20 +82,20 @@ Polymer({
},
/**
- * Handler for tapping the 'cancel' button. Should just dismiss the dialog.
+ * Handler for tapping the 'done' button. Should just dismiss the dialog.
* @private
*/
- onCancelButtonTap_: function() {
+ onActionButtonTap_: function() {
this.close();
},
/**
- * Handler for tapping the save button.
+ * @param {!Event} event
* @private
*/
- onSaveButtonTap_: function() {
- // TODO(hcarmona): what to save?
- this.close();
- },
+ onReadonlyInputTap_: function(event) {
+ /** @type {!PaperInputElement} */ (Polymer.dom(event).localTarget)
+ .inputElement.select();
+ }
});
})();
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html
index f86e431fae1..f5501392092 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html
@@ -3,9 +3,10 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="autofill_section.html">
<link rel="import" href="passwords_section.html">
+<link rel="import" href="../controls/extension_controlled_indicator.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../prefs/prefs.html">
<link rel="import" href="../prefs/prefs_behavior.html">
<link rel="import" href="../route.html">
@@ -16,12 +17,12 @@
<dom-module id="settings-passwords-and-forms-page">
<template>
<style include="settings-shared"></style>
- <settings-animated-pages id="pages" section="passwordsAndForms">
+ <settings-animated-pages id="pages" section="passwordsAndForms"
+ focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<div class="settings-box first two-line">
- <div class="start two-line" on-tap="onAutofillTap_"
- id="autofillManagerButton"
- actionable$="[[prefs.autofill.enabled.value]]">
+ <div class="start two-line" on-tap="onAutofillTap_" actionable
+ id="autofillManagerButton">
<div class="flex">
$i18n{autofill}
<div class="secondary" id="autofillSecondary">
@@ -32,17 +33,10 @@
aria-label="$i18n{autofill}"
aria-describedby="autofillSecondary"></button>
</div>
- <div class="secondary-action">
- <paper-toggle-button id="autofillToggle"
- aria-label="$i18n{autofill}"
- checked="{{prefs.autofill.enabled.value}}">
- </paper-toggle-button>
- </div>
</div>
<div class="settings-box two-line">
- <div class="start two-line" on-tap="onPasswordsTap_"
- id="passwordManagerButton"
- actionable$="[[prefs.credentials_enable_service.value]]">
+ <div class="start two-line" on-tap="onPasswordsTap_" actionable
+ id="passwordManagerButton">
<div class="flex">
$i18n{passwords}
<div class="secondary" id="passwordsSecondary">
@@ -53,19 +47,13 @@
aria-label="$i18n{passwords}"
aria-describedby="passwordsSecondary"></button>
</div>
- <div class="secondary-action">
- <paper-toggle-button id="passwordToggle"
- aria-label="$i18n{passwords}"
- checked="{{prefs.credentials_enable_service.value}}">
- </paper-toggle-button>
- </div>
</div>
</neon-animatable>
<template is="dom-if" route-path="/autofill">
<settings-subpage
associated-control="[[$$('#autofillManagerButton')]]"
page-title="$i18n{autofill}">
- <settings-autofill-section id="autofillSection">
+ <settings-autofill-section id="autofillSection" prefs="{{prefs}}">
</settings-autofill-section>
</settings-subpage>
</template>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js
index b5cfb554c72..abf59371208 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js
@@ -2,14 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-/**
- * @fileoverview 'settings-passwords-and-forms-page' is the settings page
- * for passwords and auto fill.
- */
-
-(function() {
-'use strict';
-
Polymer({
is: 'settings-passwords-and-forms-page',
@@ -18,6 +10,19 @@ Polymer({
properties: {
/** @private Filter applied to passwords and password exceptions. */
passwordFilter_: String,
+
+ /** @type {?Map<string, string>} */
+ focusConfig: Object,
+ },
+
+ /** @override */
+ ready: function() {
+ this.focusConfig_ = new Map();
+ this.focusConfig_.set(
+ settings.Route.AUTOFILL.path, '#autofillManagerButton .subpage-arrow');
+ this.focusConfig_.set(
+ settings.Route.MANAGE_PASSWORDS.path,
+ '#passwordManagerButton .subpage-arrow');
},
/**
@@ -26,11 +31,7 @@ Polymer({
* @private
*/
onAutofillTap_: function(event) {
- // Ignore clicking on the toggle button and verify autofill is enabled.
- if (Polymer.dom(event).localTarget != this.$.autofillToggle &&
- this.getPref('autofill.enabled').value) {
- settings.navigateTo(settings.Route.AUTOFILL);
- }
+ settings.navigateTo(settings.Route.AUTOFILL);
},
/**
@@ -39,12 +40,6 @@ Polymer({
* @private
*/
onPasswordsTap_: function(event) {
- // Ignore clicking on the toggle button and only expand if the manager is
- // enabled.
- if (Polymer.dom(event).localTarget != this.$.passwordToggle &&
- this.getPref('credentials_enable_service').value) {
- settings.navigateTo(settings.Route.MANAGE_PASSWORDS);
- }
+ settings.navigateTo(settings.Route.MANAGE_PASSWORDS);
},
});
-})();
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
index 04806d49b6b..ac37e5665c7 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -2,9 +2,12 @@
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/action_link.html">
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../controls/settings_toggle_button.html">
+<link rel="import" href="../controls/extension_controlled_indicator.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../global_scroll_target_behavior.html">
<link rel="import" href="../prefs/prefs.html">
<link rel="import" href="../settings_shared_css.html">
@@ -53,7 +56,27 @@
-webkit-user-select: text;
}
</style>
- <div class="settings-box first three-line">
+ <div class="settings-box first">
+ <settings-toggle-button id="passwordToggle" class="start primary-toggle"
+ aria-label="$i18n{passwords}" no-extension-indicator
+ label="[[getOnOffLabel_(prefs.credentials_enable_service.value)]]"
+ pref="{{prefs.credentials_enable_service}}">
+ </settings-toggle-button>
+ </div>
+ <template is="dom-if"
+ if="[[prefs.credentials_enable_service.extensionId]]">
+ <div class="settings-box continuation">
+ <extension-controlled-indicator class="start"
+ id="passwordsExtensionIndicator"
+ extension-id="[[prefs.credentials_enable_service.extensionId]]"
+ extension-name="[[
+ prefs.credentials_enable_service.controlledByName]]"
+ extension-can-be-disabled="[[
+ prefs.credentials_enable_service.extensionCanBeDisabled]]">
+ </extension-controlled-indicator>
+ </div>
+ </template>
+ <div class="settings-box three-line">
<settings-toggle-button id="autosigninCheckbox" class="start"
pref="{{prefs.credentials_enable_autosignin}}"
label="$i18n{passwordsAutosigninLabel}"
@@ -84,26 +107,34 @@
scroll-target="[[subpageScrollTarget]]">
<template>
<div class="list-item">
- <div class="website-column no-min-width">
+ <div class="website-column no-min-width"
+ title="[[item.loginPair.urls.link]]">
<a id="originUrl" target="_blank" class="selectable no-min-width"
- href="[[item.linkUrl]]">
+ href="[[item.loginPair.urls.link]]">
<span class="text-elide">
- [[item.loginPair.originUrl]]
+ [[item.loginPair.urls.shown]]
</span>
</a>
</div>
<div class="username-column selectable text-elide"
id="username">[[item.loginPair.username]]</div>
- <div class="password-column">
- <!-- Password type and disabled in order to match mock. -->
- <input id="password" type="password" disabled
- value="[[getEmptyPassword_(item.numCharactersInPassword)]]">
- </input>
- <paper-icon-button id="passwordMenu" icon="cr:more-vert"
+ <div class="password-column text-elide">
+ <template is="dom-if" if="[[!item.federationText]]">
+ <!-- Password type and disabled in order to match mock. -->
+ <input id="password" type="password" disabled
+ value="[[getEmptyPassword_(item.numCharactersInPassword)]]">
+ </input>
+ </template>
+ <template is="dom-if" if="[[item.federationText]]">
+ <span class="selectable text-elide">
+ [[item.federationText]]
+ </span>
+ </template>
+ </div>
+ <paper-icon-button id="passwordMenu" icon="cr:more-vert"
on-tap="onPasswordMenuTap_" title="$i18n{moreActions}"
tabindex$="[[tabIndex]]">
- </paper-icon-button>
- </div>
+ </paper-icon-button>
</div>
</template>
</iron-list>
@@ -131,8 +162,8 @@
filter="[[passwordExceptionFilter_(filter)]]">
<div class="list-item">
<div class="start">
- <a id="exception" href="[[item.linkUrl]]" target="_blank"
- class="selectable">[[item.exceptionUrl]]</a>
+ <a id="exception" href="[[item.urls.link]]" target="_blank"
+ class="selectable">[[item.urls.shown]]</a>
</div>
<paper-icon-button id="removeExceptionButton"
icon="cr:close" on-tap="onRemoveExceptionButtonTap_"
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
index a70b96c77bc..ff917dd9604 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
@@ -20,8 +20,8 @@ PasswordManager.PasswordUiEntry;
/** @typedef {chrome.passwordsPrivate.LoginPair} */
PasswordManager.LoginPair;
-/** @typedef {chrome.passwordsPrivate.ExceptionPair} */
-PasswordManager.ExceptionPair;
+/** @typedef {chrome.passwordsPrivate.ExceptionEntry} */
+PasswordManager.ExceptionEntry;
/** @typedef {chrome.passwordsPrivate.PlaintextPasswordEventParameters} */
PasswordManager.PlaintextPasswordEvent;
@@ -54,19 +54,19 @@ PasswordManager.prototype = {
/**
* Add an observer to the list of password exceptions.
- * @param {function(!Array<!PasswordManager.ExceptionPair>):void} listener
+ * @param {function(!Array<!PasswordManager.ExceptionEntry>):void} listener
*/
addExceptionListChangedListener: assertNotReached,
/**
* Remove an observer from the list of password exceptions.
- * @param {function(!Array<!PasswordManager.ExceptionPair>):void} listener
+ * @param {function(!Array<!PasswordManager.ExceptionEntry>):void} listener
*/
removeExceptionListChangedListener: assertNotReached,
/**
* Request the list of password exceptions.
- * @param {function(!Array<!PasswordManager.ExceptionPair>):void} callback
+ * @param {function(!Array<!PasswordManager.ExceptionEntry>):void} callback
*/
getExceptionList: assertNotReached,
@@ -144,7 +144,7 @@ PasswordManagerImpl.prototype = {
getPlaintextPassword: function(loginPair, callback) {
var listener = function(reply) {
// Only handle the reply for our loginPair request.
- if (reply.loginPair.originUrl == loginPair.originUrl &&
+ if (reply.loginPair.urls.origin == loginPair.urls.origin &&
reply.loginPair.username == loginPair.username) {
chrome.passwordsPrivate.onPlaintextPasswordRetrieved.removeListener(
listener);
@@ -159,8 +159,8 @@ PasswordManagerImpl.prototype = {
/** @typedef {!{model: !{item: !chrome.passwordsPrivate.PasswordUiEntry}}} */
var PasswordUiEntryEvent;
-/** @typedef {!{model: !{item: !chrome.passwordsPrivate.ExceptionPair}}} */
-var ExceptionPairEntryEvent;
+/** @typedef {!{model: !{item: !chrome.passwordsPrivate.ExceptionEntry}}} */
+var ExceptionEntryEntryEvent;
(function() {
'use strict';
@@ -168,7 +168,7 @@ var ExceptionPairEntryEvent;
Polymer({
is: 'passwords-section',
- behaviors: [settings.GlobalScrollTargetBehavior],
+ behaviors: [settings.GlobalScrollTargetBehavior, I18nBehavior],
properties: {
/** Preferences state. */
@@ -185,7 +185,7 @@ Polymer({
/**
* An array of sites to display.
- * @type {!Array<!PasswordManager.ExceptionPair>}
+ * @type {!Array<!PasswordManager.ExceptionEntry>}
*/
passwordExceptions: Array,
@@ -216,6 +216,13 @@ Polymer({
},
/**
+ * The element to return focus to, when the currently active dialog is
+ * closed.
+ * @private {?HTMLElement}
+ */
+ activeDialogAnchor_: null,
+
+ /**
* @type {PasswordManager}
* @private
*/
@@ -228,13 +235,13 @@ Polymer({
setSavedPasswordsListener_: null,
/**
- * @type {?function(!Array<PasswordManager.ExceptionPair>):void}
+ * @type {?function(!Array<PasswordManager.ExceptionEntry>):void}
* @private
*/
setPasswordExceptionsListener_: null,
/** @override */
- ready: function() {
+ attached: function() {
// Create listener functions.
var setSavedPasswordsListener = function(list) {
this.savedPasswords = list;
@@ -267,7 +274,7 @@ Polymer({
/** @type {function(!Array<PasswordManager.PasswordUiEntry>):void} */(
this.setSavedPasswordsListener_));
this.passwordManager_.removeExceptionListChangedListener(
- /** @type {function(!Array<PasswordManager.ExceptionPair>):void} */(
+ /** @type {function(!Array<PasswordManager.ExceptionEntry>):void} */(
this.setPasswordExceptionsListener_));
},
@@ -278,7 +285,7 @@ Polymer({
*/
setPassword: function(loginPair, password) {
if (this.activePassword &&
- this.activePassword.loginPair.originUrl == loginPair.originUrl &&
+ this.activePassword.loginPair.urls.origin == loginPair.urls.origin &&
this.activePassword.loginPair.username == loginPair.username) {
this.$$('password-edit-dialog').password = password;
}
@@ -298,6 +305,8 @@ Polymer({
/** @private */
onPasswordEditDialogClosed_: function() {
this.showPasswordEditDialog_ = false;
+ this.activeDialogAnchor_.focus();
+ this.activeDialogAnchor_ = null;
},
/**
@@ -311,19 +320,19 @@ Polymer({
return savedPasswords;
return savedPasswords.filter(function(password) {
- return password.loginPair.originUrl.includes(filter) ||
+ return password.loginPair.urls.shown.includes(filter) ||
password.loginPair.username.includes(filter);
});
},
/**
* @param {string} filter
- * @return {function(!chrome.passwordsPrivate.ExceptionPair): boolean}
+ * @return {function(!chrome.passwordsPrivate.ExceptionEntry): boolean}
* @private
*/
passwordExceptionFilter_: function(filter) {
return function(exception) {
- return exception.exceptionUrl.includes(filter);
+ return exception.urls.shown.includes(filter);
};
},
@@ -338,11 +347,11 @@ Polymer({
/**
* Fires an event that should delete the password exception.
- * @param {!ExceptionPairEntryEvent} e The polymer event.
+ * @param {!ExceptionEntryEntryEvent} e The polymer event.
* @private
*/
onRemoveExceptionButtonTap_: function(e) {
- this.passwordManager_.removeException(e.model.item.exceptionUrl);
+ this.passwordManager_.removeException(e.model.item.urls.origin);
},
/**
@@ -351,7 +360,9 @@ Polymer({
* @return {string} password
* @private
*/
- getEmptyPassword_: function(length) { return ' '.repeat(length); },
+ getEmptyPassword_: function(length) {
+ return ' '.repeat(length);
+ },
/**
* Opens the password action menu.
@@ -359,13 +370,14 @@ Polymer({
*/
onPasswordMenuTap_: function(e) {
var menu = /** @type {!CrActionMenuElement} */(this.$.menu);
- var target = /** @type {!Element} */(Polymer.dom(e).localTarget);
+ var target = /** @type {!HTMLElement} */(Polymer.dom(e).localTarget);
var passwordUiEntryEvent = /** @type {!PasswordUiEntryEvent} */(e);
this.activePassword =
/** @type {!chrome.passwordsPrivate.PasswordUiEntry} */ (
passwordUiEntryEvent.model.item);
menu.showAt(target);
+ this.activeDialogAnchor_ = target;
},
/**
@@ -390,5 +402,14 @@ Polymer({
this.setPassword(item.loginPair, item.plaintextPassword);
}.bind(this));
},
+
+ /**
+ * @private
+ * @param {boolean} toggleValue
+ * @return {string}
+ */
+ getOnOffLabel_: function(toggleValue) {
+ return toggleValue ? this.i18n('toggleOn') : this.i18n('toggleOff');
+ }
});
})();
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
index 952457ca9fc..2a2b921b16b 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
@@ -7,11 +7,6 @@
flex-direction: column;
}
- .column-header {
- color: var(--google-grey-500);
- font-weight: 500;
- }
-
paper-icon-button {
@apply(--cr-paper-icon-button-margin);
color: var(--paper-grey-600);
diff --git a/chromium/chrome/browser/resources/settings/people_page/change_picture.html b/chromium/chrome/browser/resources/settings/people_page/change_picture.html
index 9a0941ad244..b4c4823163b 100644
--- a/chromium/chrome/browser/resources/settings/people_page/change_picture.html
+++ b/chromium/chrome/browser/resources/settings/people_page/change_picture.html
@@ -62,7 +62,7 @@
#authorCredit,
#authorCredit a {
- color: var(--paper-grey-500);
+ color: var(--paper-grey-600);
}
#previewPane {
diff --git a/chromium/chrome/browser/resources/settings/people_page/change_picture.js b/chromium/chrome/browser/resources/settings/people_page/change_picture.js
index 4bed8bffdb5..f07d3cda4f0 100644
--- a/chromium/chrome/browser/resources/settings/people_page/change_picture.js
+++ b/chromium/chrome/browser/resources/settings/people_page/change_picture.js
@@ -145,6 +145,9 @@ Polymer({
// when navigating away. The selector element doesn't fire its upward
// data binding unless its selected item has changed.
this.selectedItem_ = this.$.selector.selectedItem;
+ // Focus the container by default so that the arrow keys work (and since
+ // we use the focus highlight to show which picture is selected).
+ this.$.container.focus();
} else {
// Ensure we deactivate the camera when we navigate away.
this.selectedItem_ = null;
@@ -339,6 +342,7 @@ Polymer({
*/
onPhotoTaken_: function(event) {
this.browserProxy_.photoTaken(event.detail.photoDataUrl);
+ this.$.container.focus();
},
/**
diff --git a/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
index 9c9d3243856..3eb9053ae74 100644
--- a/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -61,10 +61,13 @@
'target_name': 'fingerprint_list',
'dependencies': [
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-ripple/compiled_resources2.gyp:paper-ripple-extracted',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+ '<(EXTERNS_GYP):web_animations',
- 'fingerprint_browser_proxy',
+ 'fingerprint_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -83,82 +86,87 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'manage_profile',
+ 'target_name': 'lock_screen',
'dependencies': [
'../compiled_resources2.gyp:route',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
- 'manage_profile_browser_proxy',
- 'sync_browser_proxy',
+ 'easy_unlock_browser_proxy',
+ 'easy_unlock_turn_off_dialog',
+ 'fingerprint_browser_proxy',
+ 'lock_screen_constants',
+ 'lock_state_behavior',
+ 'password_prompt_dialog',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'manage_profile_browser_proxy',
+ 'target_name': 'lock_screen_constants',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_profile_avatar_selector/compiled_resources2.gyp:cr_profile_avatar_selector',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'password_prompt_dialog',
+ 'target_name': 'lock_state_behavior',
'dependencies': [
'../compiled_resources2.gyp:route',
'<(EXTERNS_GYP):quick_unlock_private',
- 'lock_screen_constants',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'people_page',
+ 'target_name': 'manage_profile',
'dependencies': [
'../compiled_resources2.gyp:route',
- '../settings_page/compiled_resources2.gyp:settings_animated_pages',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
- 'easy_unlock_browser_proxy',
- 'easy_unlock_turn_off_dialog',
- 'lock_screen_constants',
- 'lock_state_behavior',
- 'profile_info_browser_proxy',
+ 'manage_profile_browser_proxy',
'sync_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'profile_info_browser_proxy',
+ 'target_name': 'manage_profile_browser_proxy',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_profile_avatar_selector/compiled_resources2.gyp:cr_profile_avatar_selector',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'lock_state_behavior',
+ 'target_name': 'password_prompt_dialog',
'dependencies': [
'../compiled_resources2.gyp:route',
'<(EXTERNS_GYP):quick_unlock_private',
+ 'lock_screen_constants',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'lock_screen_constants',
+ 'target_name': 'people_page',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '../compiled_resources2.gyp:route',
+ '../settings_page/compiled_resources2.gyp:settings_animated_pages',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+ 'lock_screen',
+ 'lock_screen_constants',
+ 'lock_state_behavior',
+ 'profile_info_browser_proxy',
+ 'sync_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'lock_screen',
+ 'target_name': 'profile_info_browser_proxy',
'dependencies': [
- '../compiled_resources2.gyp:route',
- 'fingerprint_browser_proxy',
- 'lock_screen_constants',
- 'lock_state_behavior',
- 'password_prompt_dialog',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -167,9 +175,8 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
-
- 'fingerprint_browser_proxy',
- 'fingerprint_progress_arc',
+ 'fingerprint_browser_proxy',
+ 'fingerprint_progress_arc',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -177,9 +184,9 @@
'target_name': 'setup_pin_dialog',
'dependencies': [
'../compiled_resources2.gyp:route',
- 'lock_screen_constants',
- 'password_prompt_dialog',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ 'lock_screen_constants',
+ 'password_prompt_dialog',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -188,10 +195,11 @@
'dependencies': [
'../compiled_resources2.gyp:route',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
- 'sync_browser_proxy',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+ 'sync_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -208,6 +216,7 @@
'target_name': 'user_list',
'dependencies': [
'../compiled_resources2.gyp:route',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):settings_private',
'<(EXTERNS_GYP):users_private',
],
diff --git a/chromium/chrome/browser/resources/settings/people_page/fingerprint_browser_proxy.js b/chromium/chrome/browser/resources/settings/people_page/fingerprint_browser_proxy.js
index 5b4865433ba..dbc693c05e5 100644
--- a/chromium/chrome/browser/resources/settings/people_page/fingerprint_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/people_page/fingerprint_browser_proxy.js
@@ -19,6 +19,16 @@ settings.FingerprintResultType = {
};
/**
+ * An object describing a attempt from the fingerprint hardware. The structure
+ * of this data must be kept in sync with C++ FingerprintHandler.
+ * @typedef {{
+ * result: settings.FingerprintResultType,
+ * indexes: !Array<number>,
+ * }}
+ */
+settings.FingerprintAttempt;
+
+/**
* An object describing a scan from the fingerprint hardware. The structure of
* this data must be kept in sync with C++ FingerprintHandler.
* @typedef {{
diff --git a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html
index d08e3ebeae3..be274800f32 100644
--- a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html
+++ b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html
@@ -1,10 +1,12 @@
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html">
<link rel="import" href="fingerprint_browser_proxy.html">
<link rel="import" href="setup_fingerprint_dialog.html">
<link rel="import" href="../i18n_setup.html">
@@ -27,9 +29,17 @@
@apply(--settings-list-frame-padding);
}
+ .list-item {
+ background-color: white;
+ }
+
paper-input {
--paper-input-container-color: transparent;
}
+
+ paper-ripple {
+ color: var(--google-grey-700);
+ }
</style>
<h2 class="settings-box">$i18n{lockScreenRegisteredFingerprints}</h2>
@@ -37,6 +47,7 @@
<iron-list id="fingerprintsList" items="[[fingerprints_]]">
<template>
<div class="list-item">
+ <paper-ripple noink></paper-ripple>
<paper-input value="{{item}}"
on-change="onFingerprintLabelChanged_">
</paper-input>
@@ -48,7 +59,7 @@
</template>
</iron-list>
<div class="continuation">
- <paper-button class="add-link action-button"
+ <paper-button id="addFingerprint" class="add-link action-button"
on-tap="openAddFingerprintDialog_">
$i18n{lockScreenAddFingerprint}
</paper-button>
@@ -57,7 +68,8 @@
<i class="settings-box continuation">$i18n{lockScreenFingerprintWarning}</i>
<settings-setup-fingerprint-dialog id="setupFingerprint"
- on-add-fingerprint="updateFingerprintsList_">
+ on-add-fingerprint="updateFingerprintsList_"
+ on-close="onSetupFingerprintDialogClose_">
</settings-setup-fingerprint-dialog>
</template>
<script src="fingerprint_list.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js
index 439ed478fd2..849a713a62f 100644
--- a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js
+++ b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js
@@ -5,12 +5,17 @@
(function() {
'use strict';
+/**
+ * The duration in ms of a background flash when a user touches the fingerprint
+ * sensor on this page.
+ * @const {number}
+ */
+var FLASH_DURATION_MS = 500;
+
Polymer({
is: 'settings-fingerprint-list',
- behaviors: [
- I18nBehavior,
- ],
+ behaviors: [I18nBehavior, WebUIListenerBehavior],
properties: {
/**
@@ -30,10 +35,42 @@ Polymer({
/** @override */
attached: function() {
+ this.addWebUIListener(
+ 'on-fingerprint-attempt-received', this.onAttemptReceived_.bind(this));
this.browserProxy_ = settings.FingerprintBrowserProxyImpl.getInstance();
this.updateFingerprintsList_();
},
+ /**
+ * Sends a ripple when the user taps the sensor with a registered fingerprint.
+ * @param {!settings.FingerprintAttempt} fingerprintAttempt
+ * @private
+ */
+ onAttemptReceived_: function(fingerprintAttempt) {
+ /** @type {NodeList<!HTMLElement>} */ var listItems =
+ this.$.fingerprintsList.querySelectorAll('.list-item');
+ /** @type {Array<number>} */ var filteredIndexes =
+ fingerprintAttempt.indexes.filter(function(index) {
+ return index >= 0 && index < listItems.length;
+ });
+
+ // Flash the background and produce a ripple for each list item that
+ // corresponds to the attempted finger.
+ filteredIndexes.forEach(function(index) {
+ var listItem = listItems[index];
+ var ripple = listItem.querySelector('paper-ripple');
+
+ // Activate the ripple.
+ if (ripple)
+ ripple.simulatedRipple();
+
+ // Flash the background.
+ listItem.animate({
+ backgroundColor: ['var(--google-grey-300)', 'white'],
+ }, FLASH_DURATION_MS);
+ });
+ },
+
/** @private */
updateFingerprintsList_: function() {
this.browserProxy_.getFingerprintsList().then(
@@ -43,7 +80,7 @@ Polymer({
/**
* @param {!settings.FingerprintInfo} fingerprintInfo
* @private
- * */
+ */
onFingerprintsChanged_: function(fingerprintInfo) {
this.fingerprints_ = fingerprintInfo.fingerprintsList;
this.$.fingerprintsList.notifyResize();
@@ -78,5 +115,10 @@ Polymer({
openAddFingerprintDialog_: function() {
this.$.setupFingerprint.open();
},
+
+ /** @private */
+ onSetupFingerprintDialogClose_: function() {
+ this.$$('#addFingerprint').focus();
+ },
});
})();
diff --git a/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.html b/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.html
index 989941b2586..04f2a04c9c1 100644
--- a/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.html
+++ b/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.html
@@ -41,7 +41,7 @@
importStatusEnum_.SUCCEEDED, importStatus_)]]">
<iron-icon id="successIcon" icon="settings:check-circle">
</iron-icon>
- <div hidden$="[[!prefs.import_bookmarks.value]]">
+ <div hidden$="[[!prefs.import_dialog_bookmarks.value]]">
<div class="description">$i18n{importSuccess}</div>
<settings-toggle-button class="start"
label="$i18n{showBookmarksBar}"
@@ -54,6 +54,7 @@
importStatusEnum_.SUCCEEDED, importStatus_)]]">
<span class="md-select-wrapper">
<select id="browserSelect" class="md-select"
+ aria-label="$i18n{importFromLabel}"
on-change="onBrowserProfileSelectionChange_">
<template is="dom-repeat" items="[[browserProfiles_]]">
<option value="[[item.index]]">[[item.name]]</option>
@@ -64,27 +65,27 @@
<div class="description">$i18n{importDescription}</div>
<settings-checkbox
hidden="[[!selected_.history]]"
- pref="{{prefs.import_history}}"
+ pref="{{prefs.import_dialog_history}}"
label="$i18n{importHistory}">
</settings-checkbox>
<settings-checkbox
hidden="[[!selected_.favorites]]"
- pref="{{prefs.import_bookmarks}}"
+ pref="{{prefs.import_dialog_bookmarks}}"
label="$i18n{importFavorites}">
</settings-checkbox>
<settings-checkbox
hidden="[[!selected_.passwords]]"
- pref="{{prefs.import_saved_passwords}}"
+ pref="{{prefs.import_dialog_saved_passwords}}"
label="$i18n{importPasswords}">
</settings-checkbox>
<settings-checkbox
hidden="[[!selected_.search]]"
- pref="{{prefs.import_search_engine}}"
+ pref="{{prefs.import_dialog_search_engine}}"
label="$i18n{importSearch}">
</settings-checkbox>
<settings-checkbox
hidden="[[!selected_.autofillFormData]]"
- pref="{{prefs.import_autofill_form_data}}"
+ pref="{{prefs.import_dialog_autofill_form_data}}"
label="$i18n{importAutofillFormData}">
</settings-checkbox>
</div>
diff --git a/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.js b/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.js
index 6e0f1c2c000..d98afd2bcb2 100644
--- a/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.js
+++ b/chromium/chrome/browser/resources/settings/people_page/import_data_dialog.js
@@ -77,14 +77,16 @@ Polymer({
/** @private */
prefsChanged_: function() {
this.noImportDataTypeSelected_ =
- !(this.getPref('import_history').value && this.selected_.history) &&
- !(this.getPref('import_bookmarks').value && this.selected_.favorites) &&
- !(this.getPref('import_saved_passwords').value &&
- this.selected_.passwords) &&
- !(this.getPref('import_search_engine').value &&
- this.selected_.search) &&
- !(this.getPref('import_autofill_form_data').value &&
- this.selected_.autofillFormData);
+ !(this.getPref('import_dialog_history').value &&
+ this.selected_.history) &&
+ !(this.getPref('import_dialog_bookmarks').value &&
+ this.selected_.favorites) &&
+ !(this.getPref('import_dialog_saved_passwords').value &&
+ this.selected_.passwords) &&
+ !(this.getPref('import_dialog_search_engine').value &&
+ this.selected_.search) &&
+ !(this.getPref('import_dialog_autofill_form_data').value &&
+ this.selected_.autofillFormData);
},
/**
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_screen.html b/chromium/chrome/browser/resources/settings/people_page/lock_screen.html
index 6064de35743..db34d13e12b 100644
--- a/chromium/chrome/browser/resources/settings/people_page/lock_screen.html
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -1,10 +1,11 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/html/action_link.html">
-<link rel="import" href="chrome://resources/html/action_link_css.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html">
<link rel="import" href="../controls/settings_toggle_button.html">
+<link rel="import" href="easy_unlock_browser_proxy.html">
+<link rel="import" href="easy_unlock_turn_off_dialog.html">
<link rel="import" href="fingerprint_browser_proxy.html">
<link rel="import" href="lock_screen_constants.html">
<link rel="import" href="lock_state_behavior.html">
@@ -19,28 +20,49 @@
<dom-module id="settings-lock-screen">
<template>
<style include="settings-shared action-link">
- .radio-indent {
- -webkit-margin-start: 36px;
+ #easyUnlock .start {
+ /* When the easy unlock toggle is shown, the easy unlock section's
+ * content becomes squashed to the top and bottom edges. Use padding to
+ * ensure the easy unlock content looks correct. */
+ padding: 11px 0;
+ }
+
+ paper-radio-button {
+ --paper-radio-button-label: {
+ display: flex;
+ width: 100%;
+ };
+ }
+
+ paper-radio-button > .start {
+ flex: 1;
}
</style>
<div>
- <div class="list-frame">
- <paper-radio-group selected="{{selectedUnlockType}}">
- <paper-radio-button name="password">
- $i18n{lockScreenPasswordOnly}
- </paper-radio-button>
- <paper-radio-button name="pin+password">
- $i18n{lockScreenPinOrPassword}
- </paper-radio-button>
- </paper-radio-group>
- <div class="list-item radio-indent"
- hidden$="[[!showConfigurePinButton_(selectedUnlockType)]]">
- <a is="action-link" class="list-button" on-tap="onConfigurePin_">
- [[getSetupPinText_(hasPin)]]
- </a>
+ <template is="dom-if" if="[[quickUnlockEnabled_]]">
+ <div class="list-frame">
+ <paper-radio-group id="unlockType" selected="{{selectedUnlockType}}">
+ <paper-radio-button name="password">
+ <div class="start">
+ $i18n{lockScreenPasswordOnly}
+ </div>
+ </paper-radio-button>
+ <paper-radio-button name="pin+password">
+ <div class="start">
+ $i18n{lockScreenPinOrPassword}
+ </div>
+ <template is="dom-if"
+ if="[[showConfigurePinButton_(selectedUnlockType)]]">
+ <paper-button id="setupPinButton" class="secondary-button"
+ on-tap="onConfigurePin_">
+ [[getSetupPinText_(hasPin)]]
+ </paper-button>
+ </template>
+ </paper-radio-button>
+ </paper-radio-group>
</div>
- </div>
+ </template>
<div id="screenLockDiv" class="settings-box">
<settings-toggle-button class="start"
@@ -75,12 +97,56 @@
</div>
</template>
+ <template is="dom-if" if="[[easyUnlockAllowed_]]">
+ <div id="easyUnlock" class="settings-box two-line">
+ <div class="start">
+ <div>$i18n{easyUnlockSectionTitle}</div>
+ <div class="secondary">
+ [[getEasyUnlockDescription_(easyUnlockEnabled_,
+ '$i18nPolymer{easyUnlockDescription}',
+ '$i18nPolymer{easyUnlockSetupIntro}')]]
+ <a target="_blank" href="$i18n{easyUnlockLearnMoreURL}">
+ $i18n{learnMore}
+ </a>
+ <template is="dom-if" if="[[getShowEasyUnlockToggle_(
+ easyUnlockEnabled_, easyUnlockProximityDetectionAllowed_)]]">
+ <settings-toggle-button
+ pref="{{prefs.easy_unlock.proximity_required}}"
+ label="$i18n{easyUnlockRequireProximityLabel}">
+ </settings-toggle-button>
+ </template>
+ </div>
+ </div>
+ <div class="secondary-action">
+ <template is="dom-if" if="[[!easyUnlockEnabled_]]">
+ <paper-button id="easyUnlockSetup" class="secondary-button"
+ on-tap="onEasyUnlockSetupTap_">
+ $i18n{easyUnlockSetupButton}
+ </paper-button>
+ </template>
+ <template is="dom-if" if="[[easyUnlockEnabled_]]">
+ <paper-button id="easyUnlockTurnOff" class="secondary-button"
+ on-tap="onEasyUnlockTurnOffTap_">
+ $i18n{easyUnlockTurnOffButton}
+ </paper-button>
+ </template>
+ </div>
+ </div>
+ </template>
+
<settings-password-prompt-dialog id="passwordPrompt"
on-close="onPasswordClosed_" set-modes="{{setModes_}}">
</settings-password-prompt-dialog>
+
<settings-setup-pin-dialog id="setupPin" on-done="onPinSetupDone_"
- set-modes="[[setModes_]]">
+ on-close="onSetupPinClosed_" set-modes="[[setModes_]]">
</settings-setup-pin-dialog>
+
+ <template is="dom-if" if="[[showEasyUnlockTurnOffDialog_]]">
+ <easy-unlock-turn-off-dialog id="easyUnlockTurnOffDialog"
+ on-close="onEasyUnlockTurnOffDialogClose_">
+ </easy-unlock-turn-off-dialog>
+ </template>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_screen.js b/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
index 70365d15396..e1f2c929347 100644
--- a/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
@@ -17,13 +17,16 @@
Polymer({
is: 'settings-lock-screen',
- behaviors: [I18nBehavior, LockStateBehavior, settings.RouteObserverBehavior],
+ behaviors: [
+ I18nBehavior,
+ LockStateBehavior,
+ WebUIListenerBehavior,
+ settings.RouteObserverBehavior,
+ ],
properties: {
/** Preferences state. */
- prefs: {
- type: Object
- },
+ prefs: {type: Object},
/**
* setModes_ is a partially applied function that stores the previously
@@ -35,7 +38,7 @@ Polymer({
*/
setModes_: {
type: Object,
- observer: 'onSetModesChanged_'
+ observer: 'onSetModesChanged_',
},
/**
@@ -47,17 +50,19 @@ Polymer({
*/
writeUma_: {
type: Object,
- value: function() { return settings.recordLockScreenProgress; }
+ value: function() {
+ return settings.recordLockScreenProgress;
+ },
},
/**
- * True if pin unlock settings should be displayed on this machine.
+ * True if quick unlock settings should be displayed on this machine.
* @private
*/
- pinUnlockEnabled_: {
+ quickUnlockEnabled_: {
type: Boolean,
value: function() {
- return loadTimeData.getBoolean('pinUnlockEnabled');
+ return loadTimeData.getBoolean('quickUnlockEnabled');
},
readOnly: true,
},
@@ -79,22 +84,73 @@ Polymer({
type: Number,
value: 0,
},
+
+ /**
+ * True if Easy Unlock is allowed on this machine.
+ */
+ easyUnlockAllowed_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('easyUnlockAllowed');
+ },
+ readOnly: true,
+ },
+
+ /**
+ * True if Easy Unlock is enabled.
+ */
+ easyUnlockEnabled_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('easyUnlockEnabled');
+ },
+ },
+
+ /**
+ * True if Easy Unlock's proximity detection feature is allowed.
+ */
+ easyUnlockProximityDetectionAllowed_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('easyUnlockAllowed') &&
+ loadTimeData.getBoolean('easyUnlockProximityDetectionAllowed');
+ },
+ readOnly: true,
+ },
+
+ /** @private */
+ showEasyUnlockTurnOffDialog_: {
+ type: Boolean,
+ value: false,
+ },
},
+ /** @private {?settings.EasyUnlockBrowserProxy} */
+ easyUnlockBrowserProxy_: null,
+
/** @private {?settings.FingerprintBrowserProxy} */
- browserProxy_: null,
+ fingerprintBrowserProxy_: null,
/** selectedUnlockType is defined in LockStateBehavior. */
observers: ['selectedUnlockTypeChanged_(selectedUnlockType)'],
/** @override */
attached: function() {
- // currentRouteChanged is not called during the initial navigation. If the
- // user navigates directly to the lockScreen page, we still want to show the
- // password prompt page.
- this.currentRouteChanged(settings.Route.LOCK_SCREEN,
- settings.Route.LOCK_SCREEN);
- this.browserProxy_ = settings.FingerprintBrowserProxyImpl.getInstance();
+ if (this.shouldAskForPassword_(settings.getCurrentRoute()))
+ this.$.passwordPrompt.open();
+
+ this.easyUnlockBrowserProxy_ =
+ settings.EasyUnlockBrowserProxyImpl.getInstance();
+ this.fingerprintBrowserProxy_ =
+ settings.FingerprintBrowserProxyImpl.getInstance();
+
+ if (this.easyUnlockAllowed_) {
+ this.addWebUIListener(
+ 'easy-unlock-enabled-status',
+ this.handleEasyUnlockEnabledStatusChanged_.bind(this));
+ this.easyUnlockBrowserProxy_.getEnabledStatus().then(
+ this.handleEasyUnlockEnabledStatusChanged_.bind(this));
+ }
},
/**
@@ -105,15 +161,14 @@ Polymer({
*/
currentRouteChanged: function(newRoute, oldRoute) {
if (newRoute == settings.Route.LOCK_SCREEN &&
- this.fingerprintUnlockEnabled_ &&
- this.browserProxy_) {
- this.browserProxy_.getNumFingerprints().then(
+ this.fingerprintUnlockEnabled_ && this.fingerprintBrowserProxy_) {
+ this.fingerprintBrowserProxy_.getNumFingerprints().then(
function(numFingerprints) {
this.numFingerprints_ = numFingerprints;
}.bind(this));
}
- if (newRoute == settings.Route.LOCK_SCREEN && !this.setModes_) {
+ if (this.shouldAskForPassword_(newRoute)) {
this.$.passwordPrompt.open();
} else if (newRoute != settings.Route.FINGERPRINT &&
oldRoute != settings.Route.FINGERPRINT) {
@@ -142,8 +197,7 @@ Polymer({
/** @private */
onSetModesChanged_: function() {
- if (settings.getCurrentRoute() == settings.Route.LOCK_SCREEN &&
- !this.setModes_) {
+ if (this.shouldAskForPassword_(settings.getCurrentRoute())) {
this.$.setupPin.close();
this.$.passwordPrompt.open();
}
@@ -153,6 +207,8 @@ Polymer({
onPasswordClosed_: function() {
if (!this.setModes_)
settings.navigateTo(settings.Route.PEOPLE);
+ else
+ this.$$('#unlockType').focus();
},
/** @private */
@@ -160,6 +216,11 @@ Polymer({
this.$.setupPin.close();
},
+ /** @private */
+ onSetupPinClosed_: function() {
+ this.$$('#setupPinButton').focus();
+ },
+
/**
* Returns true if the setup pin section should be shown.
* @param {!string} selectedUnlockType The current unlock type. Used to let
@@ -170,9 +231,12 @@ Polymer({
return selectedUnlockType === LockScreenUnlockType.PIN_PASSWORD;
},
- /** @private */
- getSetupPinText_: function() {
- if (this.hasPin)
+ /**
+ * @param {boolean} hasPin
+ * @private
+ */
+ getSetupPinText_: function(hasPin) {
+ if (hasPin)
return this.i18n('lockScreenChangePinButton');
return this.i18n('lockScreenSetupPinButton');
},
@@ -201,4 +265,68 @@ Polymer({
onEditFingerprints_: function() {
settings.navigateTo(settings.Route.FINGERPRINT);
},
+
+ /**
+ * @param {!settings.Route} route
+ * @return {boolean} Whether the password dialog should be shown.
+ * @private
+ */
+ shouldAskForPassword_: function(route) {
+ return route == settings.Route.LOCK_SCREEN && !this.setModes_;
+ },
+
+ /**
+ * Handler for when the Easy Unlock enabled status has changed.
+ * @private
+ */
+ handleEasyUnlockEnabledStatusChanged_: function(easyUnlockEnabled) {
+ this.easyUnlockEnabled_ = easyUnlockEnabled;
+ this.showEasyUnlockTurnOffDialog_ =
+ easyUnlockEnabled && this.showEasyUnlockTurnOffDialog_;
+ },
+
+ /** @private */
+ onEasyUnlockSetupTap_: function() {
+ this.easyUnlockBrowserProxy_.startTurnOnFlow();
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onEasyUnlockTurnOffTap_: function(e) {
+ // Prevent the end of the tap event from focusing what is underneath the
+ // button.
+ e.preventDefault();
+ this.showEasyUnlockTurnOffDialog_ = true;
+ },
+
+ /** @private */
+ onEasyUnlockTurnOffDialogClose_: function() {
+ this.showEasyUnlockTurnOffDialog_ = false;
+
+ // Restores focus on close to either the turn-off or set-up button,
+ // whichever is being displayed.
+ this.$$('.secondary-button').focus();
+ },
+
+ /**
+ * @param {boolean} enabled
+ * @param {!string} enabledStr
+ * @param {!string} disabledStr
+ * @private
+ */
+ getEasyUnlockDescription_: function(enabled, enabledStr, disabledStr) {
+ return enabled ? enabledStr : disabledStr;
+ },
+
+ /**
+ * @param {boolean} easyUnlockEnabled
+ * @param {boolean} proximityDetectionAllowed
+ * @private
+ */
+ getShowEasyUnlockToggle_: function(
+ easyUnlockEnabled, proximityDetectionAllowed) {
+ return easyUnlockEnabled && proximityDetectionAllowed;
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/people_page/manage_profile.html b/chromium/chrome/browser/resources/settings/people_page/manage_profile.html
index 0bc61813b4c..bce7a673d55 100644
--- a/chromium/chrome/browser/resources/settings/people_page/manage_profile.html
+++ b/chromium/chrome/browser/resources/settings/people_page/manage_profile.html
@@ -19,6 +19,7 @@
<div class="settings-box first">
<paper-input id="name" value="[[profileName]]" pattern=".*\S.*"
auto-validate required on-change="onProfileNameChanged_"
+ on-keydown="onProfileNameKeydown_"
disabled="[[isProfileNameDisabled_(syncStatus)]]">
</paper-input>
</div>
diff --git a/chromium/chrome/browser/resources/settings/people_page/manage_profile.js b/chromium/chrome/browser/resources/settings/people_page/manage_profile.js
index 6b757451dc6..c0cfb2d9906 100644
--- a/chromium/chrome/browser/resources/settings/people_page/manage_profile.js
+++ b/chromium/chrome/browser/resources/settings/people_page/manage_profile.js
@@ -34,7 +34,9 @@ Polymer({
*/
availableIcons: {
type: Array,
- value: function() { return []; },
+ value: function() {
+ return [];
+ },
},
/**
@@ -91,15 +93,26 @@ Polymer({
/**
* Handler for when the profile name field is changed, then blurred.
- * @private
* @param {!Event} event
+ * @private
*/
onProfileNameChanged_: function(event) {
if (event.target.invalid)
return;
- this.browserProxy_.setProfileIconAndName(this.profileIconUrl,
- event.target.value);
+ this.browserProxy_.setProfileName(event.target.value);
+ },
+
+ /**
+ * Handler for profile name keydowns.
+ * @param {!Event} event
+ * @private
+ */
+ onProfileNameKeydown_: function(event) {
+ if (event.key == 'Escape') {
+ event.target.value = this.profileName;
+ event.target.blur();
+ }
},
/**
@@ -108,8 +121,15 @@ Polymer({
* @private
*/
onIconActivate_: function(event) {
- this.browserProxy_.setProfileIconAndName(event.detail.selected,
- this.profileName);
+ // Explicitly test against undefined, because even when an element has the
+ // data-is-gaia-avatar attribute, dataset.isGaiaAvatar returns an empty
+ // string, which is falsy.
+ var isGaiaAvatar = event.detail.item.dataset.isGaiaAvatar !== undefined;
+
+ if (isGaiaAvatar)
+ this.browserProxy_.setProfileIconToGaiaAvatar();
+ else
+ this.browserProxy_.setProfileIconToDefaultAvatar(event.detail.selected);
},
/**
diff --git a/chromium/chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.js b/chromium/chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.js
index 78bcb39586b..34e2d34108b 100644
--- a/chromium/chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.js
@@ -25,16 +25,26 @@ cr.define('settings', function() {
ManageProfileBrowserProxy.prototype = {
/**
* Gets the available profile icons to choose from.
- * @return {!Promise<!Array<string>>}
+ * @return {!Promise<!Array<!AvatarIcon>>}
*/
getAvailableIcons: function() {},
/**
- * Sets the profile's icon and name. There is no response.
- * @param {!string} iconUrl The new profile URL.
- * @param {!string} name The new profile name.
+ * Sets the profile's icon to the GAIA avatar.
*/
- setProfileIconAndName: function(iconUrl, name) {},
+ setProfileIconToGaiaAvatar: function() {},
+
+ /**
+ * Sets the profile's icon to one of the default avatars.
+ * @param {string} iconUrl The new profile URL.
+ */
+ setProfileIconToDefaultAvatar: function(iconUrl) {},
+
+ /**
+ * Sets the profile's name.
+ * @param {string} name The new profile name.
+ */
+ setProfileName: function(name) {},
/**
* Returns whether the current profile has a shortcut.
@@ -69,8 +79,18 @@ cr.define('settings', function() {
},
/** @override */
- setProfileIconAndName: function(iconUrl, name) {
- chrome.send('setProfileIconAndName', [iconUrl, name]);
+ setProfileIconToGaiaAvatar: function() {
+ chrome.send('setProfileIconToGaiaAvatar');
+ },
+
+ /** @override */
+ setProfileIconToDefaultAvatar: function(iconUrl) {
+ chrome.send('setProfileIconToDefaultAvatar', [iconUrl]);
+ },
+
+ /** @override */
+ setProfileName: function(name) {
+ chrome.send('setProfileName', [name]);
},
/** @override */
diff --git a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html b/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html
index ac270adb6e6..2f0216581bd 100644
--- a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html
+++ b/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html
@@ -29,23 +29,20 @@
label="$i18n{passwordPromptPasswordLabel}"
no-label-float
value="{{password_}}"
- on-keydown="onKeydown_"
invalid$="[[passwordInvalid_]]"
error-message="$i18n{passwordPromptInvalidPassword}"
aria-disabled="false">
</paper-input>
+ </div>
+ <div class="button-container">
+ <paper-button class="cancel-button" on-tap="onCancelTap_">
+ $i18n{cancel}
+ </paper-button>
- <div class="button-strip">
- <paper-button class="cancel-button" on-tap="onCancelTap_">
- $i18n{cancel}
- </paper-button>
-
- <paper-button class="action-button" on-tap="submitPassword_"
- disabled$="[[!enableConfirm_(password_,
- passwordInvalid_)]]">
- $i18n{confirm}
- </paper-button>
- </div>
+ <paper-button class="action-button" on-tap="submitPassword_"
+ disabled$="[[!enableConfirm_(password_, passwordInvalid_)]]">
+ $i18n{confirm}
+ </paper-button>
</div>
</dialog>
</template>
diff --git a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js b/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
index 0ff12bbb62b..96be633de90 100644
--- a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
+++ b/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
@@ -126,12 +126,6 @@ Polymer({
this.password_ = '';
},
- /** @private */
- onKeydown_: function(e) {
- if (e.key == 'Enter')
- this.submitPassword_();
- },
-
/**
* Run the account password check.
* @private
diff --git a/chromium/chrome/browser/resources/settings/people_page/people_page.html b/chromium/chrome/browser/resources/settings/people_page/people_page.html
index a4bc33b71b8..8684b302695 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.html
@@ -4,6 +4,7 @@
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
@@ -21,8 +22,6 @@
<if expr="chromeos">
<link rel="import" href="change_picture.html">
-<link rel="import" href="easy_unlock_browser_proxy.html">
-<link rel="import" href="easy_unlock_turn_off_dialog.html">
<link rel="import" href="fingerprint_list.html">
<link rel="import" href="lock_screen.html">
<link rel="import" href="lock_state_behavior.html">
@@ -71,11 +70,6 @@
color: var(--settings-error-color);
}
- #easy-unlock .start {
- /* Use padding to ensure taller content looks correct. */
- padding: 11px 0;
- }
-
.icon-container {
display: flex;
flex-shrink: 0;
@@ -83,18 +77,6 @@
width: 40px;
}
- /* Avoid orphaned english text (as requested by bettes@) */
- #activity-controls .secondary {
- max-width: 90%;
- }
-
- #googleg-logo {
- background-image: url(../../../../../ui/webui/resources/images/200-logo_googleg.png);
- background-size: cover;
- height: var(--iron-icon-height);
- width: var(--iron-icon-width);
- }
-
#disconnectDialog .footer .settings-box {
--settings-box-row-padding: 0;
}
@@ -106,7 +88,8 @@
padding-top: 10px;
}
</style>
- <settings-animated-pages id="pages" section="people">
+ <settings-animated-pages id="pages" section="people"
+ focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<div id="picture-subpage-trigger" class="settings-box first two-line">
<template is="dom-if" if="[[syncStatus]]">
@@ -123,14 +106,20 @@
</if>
<div class="flex text-elide">
<span id="profile-name">[[profileName_]]</span>
- <div class="secondary" hidden="[[!syncStatus.signedIn]]"
- id="profileNameSecondary">
+ <div class="secondary" hidden="[[!syncStatus.signedIn]]">
[[syncStatus.signedInUsername]]
</div>
</div>
+<if expr="not chromeos">
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{editPerson}"
+ aria-describedby="profile-name"></button>
+</if>
+<if expr="chromeos">
<button class="subpage-arrow" is="paper-icon-button-light"
- aria-labelledby="profile-name"
- aria-describedby="profileNameSecondary"></button>
+ aria-label="$i18n{changePictureTitle}"
+ aria-describedby="profile-name"></button>
+</if>
</div>
<if expr="not chromeos">
<template is="dom-if" if="[[showSignin_(syncStatus)]]">
@@ -198,92 +187,20 @@
</div>
</template>
- <div class="settings-box three-line" id="activity-controls"
- on-tap="onActivityControlsTap_" actionable
- hidden="[[!syncStatus.signedIn]]">
- <div class="icon-container">
- <div id="googleg-logo"></div>
- </div>
- <div class="middle">
- $i18n{personalizeGoogleServicesTitle}
- <div class="secondary" id="personalizeGoogleServicesSecondary">
- $i18n{personalizeGoogleServicesText}
- </div>
- </div>
- <button class="icon-external" is="paper-icon-button-light"
- aria-label="$i18n{personalizeGoogleServicesTitle}"
- aria-describedby="personalizeGoogleServicesSecondary"></button>
- </div>
-
<if expr="chromeos">
- <template is="dom-if" if="[[!quickUnlockEnabled_]]">
- <div class="settings-box">
- <settings-toggle-button class="start"
- pref="{{prefs.settings.enable_screen_lock}}"
- label="$i18n{enableScreenlock}">
- </settings-toggle-button>
- </div>
- </template>
-
- <template is="dom-if" if="[[quickUnlockEnabled_]]">
- <div class="settings-box two-line" actionable
- on-tap="onConfigureLockTap_">
- <div class="start">
- $i18n{lockScreenTitle}
- <div class="secondary" id="lockScreenSecondary">
- [[getPasswordState_(hasPin,
- prefs.settings.enable_screen_lock.value)]]
- </div>
+ <div class="settings-box two-line" actionable
+ on-tap="onConfigureLockTap_">
+ <div class="start">
+ $i18n{lockScreenTitle}
+ <div class="secondary" id="lockScreenSecondary">
+ [[getPasswordState_(hasPin,
+ prefs.settings.enable_screen_lock.value)]]
</div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{lockScreenTitle}"
- aria-describedby="lockScrenSecondary"></button>
</div>
- </template>
-
- <template is="dom-if" if="[[easyUnlockAllowed_]]">
- <div id="easy-unlock" class="settings-box two-line">
- <div class="start">
- <div>$i18n{easyUnlockSectionTitle}</div>
- <div class="secondary">
- <template is="dom-if" if="[[!easyUnlockEnabled_]]">
- $i18n{easyUnlockSetupIntro}
- </template>
- <template is="dom-if" if="[[easyUnlockEnabled_]]">
- $i18n{easyUnlockDescription}
- </template>
- <a target="_blank" href="$i18n{easyUnlockLearnMoreURL}">
- $i18n{learnMore}
- </a>
- <!-- TODO(dbeam): this should be 1 dom-if with a method instead
- of 2 nested dom-ifs. -->
- <template is="dom-if" if="[[easyUnlockEnabled_]]">
- <template is="dom-if"
- if="[[easyUnlockProximityDetectionAllowed_]]">
- <settings-toggle-button
- pref="{{prefs.easy_unlock.proximity_required}}"
- label="$i18n{easyUnlockRequireProximityLabel}">
- </settings-toggle-button>
- </template>
- </template>
- </div>
- </div>
- <div class="secondary-action">
- <template is="dom-if" if="[[!easyUnlockEnabled_]]">
- <paper-button id="easyUnlockSetup" class="secondary-button"
- on-tap="onEasyUnlockSetupTap_">
- $i18n{easyUnlockSetupButton}
- </paper-button>
- </template>
- <template is="dom-if" if="[[easyUnlockEnabled_]]">
- <paper-button id="easyUnlockTurnOff" class="secondary-button"
- on-tap="onEasyUnlockTurnOffTap_">
- $i18n{easyUnlockTurnOffButton}
- </paper-button>
- </template>
- </div>
- </div>
- </template>
+ <button id="lockScreenSubpageTrigger" class="subpage-arrow"
+ is="paper-icon-button-light" aria-label="$i18n{lockScreenTitle}"
+ aria-describedby="lockScrenSecondary"></button>
+ </div>
</if>
<div id="manage-other-people-subpage-trigger"
@@ -296,23 +213,18 @@
<if expr="not chromeos">
<div class="settings-box" on-tap="onImportDataTap_" actionable>
<div class="start">$i18n{importTitle}</div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{importTitle}"></button>
+ <button id="importDataDialogTrigger" class="subpage-arrow"
+ is="paper-icon-button-light" aria-label="$i18n{importTitle}">
+ </button>
</div>
</if>
<template is="dom-if" if="[[profileManagesSupervisedUsers_]]">
- <div id="manageSupervisedUsersContainer" class="settings-box two-line"
+ <div id="manageSupervisedUsersContainer" class="settings-box"
on-tap="onManageSupervisedUsers_" actionable>
- <div class="start">
- $i18n{manageSupervisedUsers}
- <div class="secondary" id="manageSupervisedUsersSecondary">
- $i18n{manageSupervisedUsersDescription}
- </div>
- </div>
+ <div class="start">$i18n{manageSupervisedUsers}</div>
<button class="icon-external" is="paper-icon-button-light"
- aria-label="$i18n{manageSupervisedUsers}"
- aria-describedby="manageSupervisedUsersSecondary"></button>
+ aria-label="$i18n{manageSupervisedUsers}"></button>
</div>
</template>
</neon-animatable>
@@ -326,14 +238,14 @@
</settings-subpage>
</template>
<if expr="chromeos">
- <template is="dom-if" if="[[quickUnlockEnabled_]]">
- <template is="dom-if" route-path="/lockScreen" no-search>
- <settings-subpage page-title="$i18n{lockScreenTitle}">
- <settings-lock-screen
- prefs="{{prefs}}">
- </settings-lock-screen>
- </settings-subpage>
- </template>
+ <template is="dom-if" route-path="/lockScreen" no-search>
+ <settings-subpage page-title="$i18n{lockScreenTitle}">
+ <settings-lock-screen
+ prefs="{{prefs}}">
+ </settings-lock-screen>
+ </settings-subpage>
+ </template>
+ <template is="dom-if" if="[[fingerprintUnlockEnabled_]]">
<template is="dom-if" route-path="/lockScreen/fingerprint" no-search>
<settings-subpage page-title="$i18n{lockScreenFingerprintTitle}">
<settings-fingerprint-list></settings-fingerprint-list>
@@ -368,45 +280,52 @@
</if>
</settings-animated-pages>
- <dialog is="cr-dialog" id="disconnectDialog" on-close="onDisconnectClosed_"
- close-text="$i18n{close}" ignore-popstate>
- <div class="title">$i18n{syncDisconnectTitle}</div>
- <div class="body">
- <div inner-h-t-m-l="[[getDisconnectExplanationHtml_(syncStatus.domain)]]">
+ <template is="dom-if" if="[[showDisconnectDialog_]]" restamp>
+ <dialog is="cr-dialog" id="disconnectDialog"
+ ignore-popstate ignore-enter-key
+ on-close="onDisconnectClosed_" close-text="$i18n{close}">
+ <div class="title">$i18n{syncDisconnectTitle}</div>
+ <div class="body">
+ <div inner-h-t-m-l="[[
+ getDisconnectExplanationHtml_(syncStatus.domain)]]">
+ </div>
+ </div>
+ <div class="button-container">
+ <paper-button on-tap="onDisconnectCancel_" class="cancel-button">
+ $i18n{cancel}
+ </paper-button>
+ <paper-button id="disconnectConfirm" class="action-button"
+ hidden="[[syncStatus.domain]]" on-tap="onDisconnectConfirm_">
+ $i18n{syncDisconnect}
+ </paper-button>
+ <paper-button id="disconnectManagedProfileConfirm"
+ class="action-button" hidden="[[!syncStatus.domain]]"
+ on-tap="onDisconnectConfirm_">
+ $i18n{syncDisconnectConfirm}
+ </paper-button>
</div>
- </div>
- <div class="button-container">
- <paper-button on-tap="onDisconnectCancel_" class="cancel-button">
- $i18n{cancel}
- </paper-button>
- <paper-button id="disconnectConfirm" class="action-button"
- hidden="[[syncStatus.domain]]" on-tap="onDisconnectConfirm_">
- $i18n{syncDisconnect}
- </paper-button>
- <paper-button id="disconnectManagedProfileConfirm" class="action-button"
- hidden="[[!syncStatus.domain]]" on-tap="onDisconnectConfirm_">
- $i18n{syncDisconnectConfirm}
- </paper-button>
- </div>
<if expr="(not chromeos and is_posix) or is_win or is_macosx">
- <template is="dom-if" if="[[!syncStatus.domain]]">
- <div class="footer border-top-divider">
- <div class="settings-box first">
- <paper-checkbox id="deleteProfile" class="start"
- checked="{{deleteProfile_}}">
- $i18n{syncDisconnectDeleteProfile}
- </paper-checkbox>
- <cr-expand-button expanded="{{deleteProfileWarningVisible_}}"
- alt="$i18n{deleteProfileWarningExpandA11yLabel}">
- </cr-expand-button>
+ <template is="dom-if" if="[[!syncStatus.domain]]">
+ <div class="footer border-top-divider">
+ <div class="settings-box first">
+ <paper-checkbox id="deleteProfile" class="start"
+ checked="{{deleteProfile_}}">
+ $i18n{syncDisconnectDeleteProfile}
+ </paper-checkbox>
+ <cr-expand-button expanded="{{deleteProfileWarningVisible_}}"
+ alt="$i18n{deleteProfileWarningExpandA11yLabel}">
+ </cr-expand-button>
+ </div>
+ <iron-collapse opened="[[deleteProfileWarningVisible_]]">
+ <div class="delete-profile-warning">
+ [[deleteProfileWarning_]]
+ </div>
+ </iron-collapse>
</div>
- <iron-collapse opened="[[deleteProfileWarningVisible_]]">
- <div class="delete-profile-warning">[[deleteProfileWarning_]]</div>
- </iron-collapse>
- </div>
- </template>
+ </template>
</if>
- </dialog>
+ </dialog>
+ </template>
<template is="dom-if" if="[[showImportDataDialog_]]" restamp>
<settings-import-data-dialog prefs="{{prefs}}"
@@ -414,13 +333,6 @@
</settings-import-data-dialog>
</template>
-<if expr="chromeos">
- <template is="dom-if" if="[[showEasyUnlockTurnOffDialog_]]">
- <easy-unlock-turn-off-dialog id="easyUnlockTurnOffDialog"
- on-close="onEasyUnlockTurnOffDialogClose_">
- </easy-unlock-turn-off-dialog>
- </template>
-</if>
</template>
<script src="people_page.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/people_page/people_page.js b/chromium/chrome/browser/resources/settings/people_page/people_page.js
index 76115fddd45..a10ea40fe0a 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.js
@@ -81,67 +81,48 @@ Polymer({
},
},
+ /** @private */
+ showDisconnectDialog_: Boolean,
+
// <if expr="chromeos">
/**
- * True if quick unlock settings should be displayed on this machine.
+ * True if fingerprint settings should be displayed on this machine.
* @private
*/
- quickUnlockEnabled_: {
+ fingerprintUnlockEnabled_: {
type: Boolean,
value: function() {
- return loadTimeData.getBoolean('pinUnlockEnabled') ||
- loadTimeData.getBoolean('fingerprintUnlockEnabled');
+ return loadTimeData.getBoolean('fingerprintUnlockEnabled');
},
readOnly: true,
},
+// </if>
- /** @private {!settings.EasyUnlockBrowserProxy} */
- easyUnlockBrowserProxy_: {
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
type: Object,
value: function() {
- return settings.EasyUnlockBrowserProxyImpl.getInstance();
- },
- },
-
- /**
- * True if Easy Unlock is allowed on this machine.
- */
- easyUnlockAllowed_: {
- type: Boolean,
- value: function() {
- return loadTimeData.getBoolean('easyUnlockAllowed');
- },
- readOnly: true,
- },
-
- /**
- * True if Easy Unlock is enabled.
- */
- easyUnlockEnabled_: {
- type: Boolean,
- value: function() {
- return loadTimeData.getBoolean('easyUnlockEnabled');
- },
- },
-
- /**
- * True if Easy Unlock's proximity detection feature is allowed.
- */
- easyUnlockProximityDetectionAllowed_: {
- type: Boolean,
- value: function() {
- return loadTimeData.getBoolean('easyUnlockAllowed') &&
- loadTimeData.getBoolean('easyUnlockProximityDetectionAllowed');
+ var map = new Map();
+ map.set(
+ settings.Route.SYNC.path, '#sync-status .subpage-arrow');
+// <if expr="not chromeos">
+ map.set(
+ settings.Route.MANAGE_PROFILE.path,
+ '#picture-subpage-trigger .subpage-arrow');
+// </if>
+// <if expr="chromeos">
+ map.set(
+ settings.Route.CHANGE_PICTURE.path,
+ '#picture-subpage-trigger .subpage-arrow');
+ map.set(
+ settings.Route.LOCK_SCREEN.path, '#lockScreenSubpageTrigger');
+ map.set(
+ settings.Route.ACCOUNTS.path,
+ '#manage-other-people-subpage-trigger .subpage-arrow');
+// </if>
+ return map;
},
- readOnly: true,
- },
-
- /** @private */
- showEasyUnlockTurnOffDialog_: {
- type: Boolean,
- value: false,
},
-// </if>
},
/** @override */
@@ -163,16 +144,6 @@ Polymer({
this.handleSyncStatus_.bind(this));
this.addWebUIListener('sync-status-changed',
this.handleSyncStatus_.bind(this));
-
-// <if expr="chromeos">
- if (this.easyUnlockAllowed_) {
- this.addWebUIListener(
- 'easy-unlock-enabled-status',
- this.handleEasyUnlockEnabledStatusChanged_.bind(this));
- this.easyUnlockBrowserProxy_.getEnabledStatus().then(
- this.handleEasyUnlockEnabledStatusChanged_.bind(this));
- }
-// </if>
},
/** @protected */
@@ -184,12 +155,16 @@ Polymer({
// If the sync status has not been fetched yet, optimistically display
// the disconnect dialog. There is another check when the sync status is
// fetched. The dialog will be closed then the user is not signed in.
- if (this.syncStatus && !this.syncStatus.signedIn)
+ if (this.syncStatus && !this.syncStatus.signedIn) {
settings.navigateToPreviousRoute();
- else
- this.$.disconnectDialog.showModal();
- } else if (this.$.disconnectDialog.open) {
- this.$.disconnectDialog.close();
+ } else {
+ this.showDisconnectDialog_ = true;
+ this.async(function() {
+ this.$$('#disconnectDialog').showModal();
+ }.bind(this));
+ }
+ } else if (this.showDisconnectDialog_) {
+ this.$$('#disconnectDialog').close();
}
},
@@ -253,24 +228,12 @@ Polymer({
settings.ProfileInfoBrowserProxyImpl.getInstance().getProfileStatsCount();
// </if>
- if (!syncStatus.signedIn && this.$.disconnectDialog.open)
- this.$.disconnectDialog.close();
+ if (!syncStatus.signedIn && this.showDisconnectDialog_)
+ this.$$('#disconnectDialog').close();
this.syncStatus = syncStatus;
},
-// <if expr="chromeos">
- /**
- * Handler for when the Easy Unlock enabled status has changed.
- * @private
- */
- handleEasyUnlockEnabledStatusChanged_: function(easyUnlockEnabled) {
- this.easyUnlockEnabled_ = easyUnlockEnabled;
- this.showEasyUnlockTurnOffDialog_ =
- easyUnlockEnabled && this.showEasyUnlockTurnOffDialog_;
- },
-// </if>
-
/** @private */
onPictureTap_: function() {
// <if expr="chromeos">
@@ -289,17 +252,15 @@ Polymer({
// </if>
/** @private */
- onActivityControlsTap_: function() {
- this.syncBrowserProxy_.openActivityControlsUrl();
- },
-
- /** @private */
onSigninTap_: function() {
this.syncBrowserProxy_.startSignIn();
},
/** @private */
onDisconnectClosed_: function() {
+ this.showDisconnectDialog_ = false;
+ this.$$('#disconnectButton').focus();
+
if (settings.getCurrentRoute() == settings.Route.SIGN_OUT)
settings.navigateToPreviousRoute();
this.fire('signout-dialog-closed');
@@ -312,7 +273,7 @@ Polymer({
/** @private */
onDisconnectCancel_: function() {
- this.$.disconnectDialog.close();
+ this.$$('#disconnectDialog').close();
},
/** @private */
@@ -328,7 +289,7 @@ Polymer({
this.syncBrowserProxy_.signOut(deleteProfile);
}.bind(this));
- this.$.disconnectDialog.close();
+ this.$$('#disconnectDialog').close();
},
/** @private */
@@ -373,25 +334,6 @@ Polymer({
onConfigureLockTap_: function() {
settings.navigateTo(settings.Route.LOCK_SCREEN);
},
-
- /** @private */
- onEasyUnlockSetupTap_: function() {
- this.easyUnlockBrowserProxy_.startTurnOnFlow();
- },
-
- /**
- * @param {!Event} e
- * @private
- */
- onEasyUnlockTurnOffTap_: function(e) {
- e.preventDefault();
- this.showEasyUnlockTurnOffDialog_ = true;
- },
-
- /** @private */
- onEasyUnlockTurnOffDialogClose_: function() {
- this.showEasyUnlockTurnOffDialog_ = false;
- },
// </if>
/** @private */
@@ -429,6 +371,7 @@ Polymer({
/** @private */
onImportDataDialogClosed_: function() {
settings.navigateToPreviousRoute();
+ this.$.importDataDialogTrigger.focus();
},
// </if>
diff --git a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
index da9925a4b2a..6a83915012d 100644
--- a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
+++ b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
@@ -72,18 +72,17 @@
<iron-icon icon="settings:warning"></iron-icon>
<span class="middle">[[problemMessage_]]</span>
</div>
+ </div>
+ <div class="button-container">
+ <paper-button id="addAnotherButton" on-tap="onAddAnotherFingerprint_"
+ hidden$="[[hideAddAnother_(step_)]]">
+ $i18n{configureFingerprintAddAnotherButton}
+ </paper-button>
- <div class="button-strip">
- <paper-button id="addAnotherButton" on-tap="onAddAnotherFingerprint_"
- hidden$="[[hideAddAnother_(step_)]]">
- $i18n{configureFingerprintAddAnotherButton}
- </paper-button>
-
- <paper-button id="closeButton"
- class$="[[getCloseButtonClass_(step_)]]" on-tap="onClose_">
- [[getCloseButtonText_(step_)]]
- </paper-button>
- </div>
+ <paper-button id="closeButton"
+ class$="[[getCloseButtonClass_(step_)]]" on-tap="onClose_">
+ [[getCloseButtonText_(step_)]]
+ </paper-button>
</div>
</dialog>
</template>
diff --git a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js
index 74efc3ebe02..ba09526256b 100644
--- a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js
+++ b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js
@@ -50,10 +50,7 @@ Polymer({
* @type {!settings.FingerprintSetupStep}
* @private
*/
- step_: {
- type: Number,
- value: settings.FingerprintSetupStep.LOCATE_SCANNER
- },
+ step_: {type: Number, value: settings.FingerprintSetupStep.LOCATE_SCANNER},
},
/**
@@ -77,8 +74,8 @@ Polymer({
/** @override */
attached: function() {
- this.addWebUIListener('on-scan-received',
- this.onScanReceived_.bind(this));
+ this.addWebUIListener(
+ 'on-fingerprint-scan-received', this.onScanReceived_.bind(this));
this.browserProxy_ = settings.FingerprintBrowserProxyImpl.getInstance();
},
diff --git a/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.html b/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
index 6ff721fc3a4..4ddfb46c43f 100644
--- a/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
+++ b/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
@@ -10,8 +10,7 @@
<dom-module id="settings-setup-pin-dialog">
<template>
- <style include="settings-shared"></style>
- <style>
+ <style include="settings-shared">
.warning {
color: var(--paper-grey-700);
}
@@ -28,7 +27,7 @@
--iron-icon-fill-color: var(--paper-red-500);
}
- .align-center {
+ #pinKeyboardDiv {
justify-content: center;
}
</style>
@@ -46,22 +45,21 @@
</div>
<!-- Pin keyboard -->
- <div class="align-center settings-box continuation">
+ <div id="pinKeyboardDiv" class="settings-box continuation">
<pin-keyboard id="pinKeyboard" on-pin-change="onPinChange_"
- on-submit="onPinSubmit_" value="{{pinKeyboardValue_}}">
+ on-submit="onPinSubmit_" value="{{pinKeyboardValue_}}">
</pin-keyboard>
</div>
+ </div>
+ <div class="button-container">
+ <paper-button class="cancel-button" on-tap="onCancelTap_">
+ $i18n{cancel}
+ </paper-button>
- <div class="button-strip">
- <paper-button class="cancel-button" on-tap="onCancelTap_">
- $i18n{cancel}
- </paper-button>
-
- <paper-button class="action-button" on-tap="onPinSubmit_"
- disabled$="[[!enableSubmit_]]">
- <span>[[getContinueMessage_(isConfirmStep_)]]</span>
- </paper-button>
- </div>
+ <paper-button class="action-button" on-tap="onPinSubmit_"
+ disabled$="[[!enableSubmit_]]">
+ <span>[[getContinueMessage_(isConfirmStep_)]]</span>
+ </paper-button>
</div>
</dialog>
</template>
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_page.html b/chromium/chrome/browser/resources/settings/people_page/sync_page.html
index b7bd67fb887..3761fa52596 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.html
@@ -32,6 +32,12 @@
margin-top: 20px;
}
+ #existingPassphrase {
+ /* This particular list frame is not indented. */
+ -webkit-padding-start: var(--settings-box-row-padding);
+ border-bottom: var(--settings-separator-line);
+ }
+
#existingPassphraseContainer,
#passphraseRecoverHint {
align-items: center;
@@ -52,16 +58,47 @@
border-top: var(--settings-separator-line);
}
</style>
- <div id="[[pages.SPINNER]]" class="settings-box first"
- hidden$="[[!isStatus_(pages.SPINNER, pageStatus_)]]">
+ <div id="[[pages_.SPINNER]]" class="settings-box first"
+ hidden$="[[!isStatus_(pages_.SPINNER, pageStatus_)]]">
$i18n{syncLoading}
</div>
- <div id="[[pages.TIMEOUT]]" class="settings-box first"
- hidden$="[[!isStatus_(pages.TIMEOUT, pageStatus_)]]">
+ <div id="[[pages_.TIMEOUT]]" class="settings-box first"
+ hidden$="[[!isStatus_(pages_.TIMEOUT, pageStatus_)]]">
$i18n{syncTimeout}
</div>
- <div id="[[pages.CONFIGURE]]"
- hidden$="[[!isStatus_(pages.CONFIGURE, pageStatus_)]]">
+ <div id="[[pages_.CONFIGURE]]"
+ hidden$="[[!isStatus_(pages_.CONFIGURE, pageStatus_)]]">
+ <template is="dom-if" if="[[syncPrefs.passphraseRequired]]">
+ <div id="existingPassphrase" class="list-frame">
+ <div class="list-item">
+ <span>
+ [[enterPassphrasePrompt_(syncPrefs.passphraseTypeIsCustom)]]
+ <a href="$i18nRaw{syncErrorHelpUrl}" target="_blank">
+ $i18n{learnMore}
+ </a>
+ </span>
+ </div>
+ <div id="existingPassphraseContainer" class="list-item">
+ <paper-input id="existingPassphraseInput" type="password"
+ value="{{existingPassphrase_}}"
+ placeholder="$i18n{passphrasePlaceholder}"
+ error-message="$i18n{incorrectPassphraseError}">
+ <iron-a11y-keys id="keys" keys="enter"
+ on-keys-pressed="onSubmitExistingPassphraseTap_">
+ </iron-a11y-keys>
+ </paper-input>
+ <paper-button id="submitExistingPassphrase"
+ on-tap="onSubmitExistingPassphraseTap_" class="action-button"
+ disabled="[[!existingPassphrase_]]">
+ $i18n{submitPassphraseButton}
+ </paper-button>
+ </div>
+ <div id="passphraseRecoverHint" class="list-item">
+ <span>$i18nRaw{passphraseRecover}</span>
+ </div>
+ </div>
+ </template>
+
<div class="settings-box first">
<div id="syncEverythingCheckboxLabel" class="start">
$i18n{syncEverythingCheckboxLabel}
@@ -213,26 +250,35 @@
</div>
<div class="settings-box two-line" actionable
- on-tap="onManageSyncedDataTap_">
+ on-tap="onActivityControlsTap_">
<div class="start">
- $i18n{manageSyncedDataTitle}
- <div class="secondary" id="manageSyncedDataSecondary">
- $i18n{manageSyncedDataDescription}
+ $i18n{personalizeGoogleServicesTitle}
+ <div class="secondary" id="activityControlsSecondary">
+ $i18n{personalizeGoogleServicesText}
</div>
</div>
<button class="icon-external" is="paper-icon-button-light"
- aria-label="$i18n{manageSyncedDataTitle}"
- aria-describedby="manageSyncedDataSecondary"></button>
+ aria-label="$i18n{personalizeGoogleServicesTitle}"
+ aria-describedby="activityControlsSecondary"></button>
+ </div>
+
+ <div class="settings-box" actionable on-tap="onManageSyncedDataTap_">
+ <div class="start">
+ $i18n{manageSyncedDataTitle}
+ </div>
+ <button class="icon-external" is="paper-icon-button-light"
+ aria-label="$i18n{manageSyncedDataTitle}"></button>
</div>
- <div class="settings-box two-line single-column">
+ <div id="encryptionDescription" hidden="[[syncPrefs.passphraseRequired]]"
+ class="settings-box two-line single-column">
<div>$i18n{encryptionOptionsTitle}</div>
<div class="secondary">$i18n{syncDataEncryptedText}</div>
</div>
<div id="encryptionRadioGroupContainer" class="list-frame"
hidden="[[syncPrefs.passphraseRequired]]">
- <paper-radio-group
+ <paper-radio-group disabled$="[[syncPrefs.encryptAllData]]"
selected="[[selectedEncryptionRadio_(
syncPrefs.passphraseTypeIsCustom)]]"
on-paper-radio-group-changed="onEncryptionRadioSelectionChanged_">
@@ -286,37 +332,6 @@
</div>
</div>
</template>
-
- <template is="dom-if" if="[[syncPrefs.passphraseRequired]]">
- <div class="list-frame">
- <div class="list-item">
- <span>
- [[enterPassphrasePrompt_(syncPrefs.passphraseTypeIsCustom)]]
- <a href="$i18nRaw{syncErrorHelpUrl}" target="_blank">
- $i18n{learnMore}
- </a>
- </span>
- </div>
- <div id="existingPassphraseContainer" class="list-item">
- <paper-input id="existingPassphraseInput" type="password"
- value="{{existingPassphrase_}}"
- placeholder="$i18n{passphrasePlaceholder}"
- error-message="$i18n{incorrectPassphraseError}">
- <iron-a11y-keys id="keys" keys="enter"
- on-keys-pressed="onSubmitExistingPassphraseTap_">
- </iron-a11y-keys>
- </paper-input>
- <paper-button id="submitExistingPassphrase"
- on-tap="onSubmitExistingPassphraseTap_" class="action-button"
- disabled="[[!existingPassphrase_]]">
- $i18n{submitPassphraseButton}
- </paper-button>
- </div>
- <div id="passphraseRecoverHint" class="list-item">
- <span>$i18nRaw{passphraseRecover}</span>
- </div>
- </div>
- </template>
</div>
</template>
<script src="sync_page.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_page.js b/chromium/chrome/browser/resources/settings/people_page/sync_page.js
index b22155deedc..3473acdc58f 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.js
@@ -35,13 +35,6 @@ var SyncPrefsIndividualDataTypes = [
/**
* @fileoverview
* 'settings-sync-page' is the settings page containing sync settings.
- *
- * Example:
- *
- * <iron-animated-pages>
- * <settings-sync-page></settings-sync-page>
- * ... other pages ...
- * </iron-animated-pages>
*/
Polymer({
is: 'settings-sync-page',
@@ -53,7 +46,7 @@ Polymer({
properties: {
/** @private */
- pages: {
+ pages_: {
type: Object,
value: settings.PageStatus,
readOnly: true,
@@ -225,6 +218,16 @@ Polymer({
// Hide the new passphrase box if the sync data has been encrypted.
if (this.syncPrefs.encryptAllData)
this.creatingNewPassphrase_ = false;
+
+ // Focus the password input box if password is needed to start sync.
+ if (this.syncPrefs.passphraseRequired) {
+ // Async to allow the dom-if templates to render first.
+ this.async(function() {
+ var input = /** @type {!PaperInputElement} */ (
+ this.$$('#existingPassphraseInput'));
+ input.inputElement.focus();
+ }.bind(this));
+ }
},
/**
@@ -267,6 +270,11 @@ Polymer({
},
/** @private */
+ onActivityControlsTap_: function() {
+ this.browserProxy_.openActivityControlsUrl();
+ },
+
+ /** @private */
onManageSyncedDataTap_: function() {
window.open(loadTimeData.getString('syncDashboardUrl'));
},
@@ -345,7 +353,7 @@ Polymer({
settings.navigateTo(settings.Route.PEOPLE);
return;
case settings.PageStatus.PASSPHRASE_FAILED:
- if (this.pageStatus_ == this.pages.CONFIGURE &&
+ if (this.pageStatus_ == this.pages_.CONFIGURE &&
this.syncPrefs && this.syncPrefs.passphraseRequired) {
this.$$('#existingPassphraseInput').invalid = true;
}
diff --git a/chromium/chrome/browser/resources/settings/people_page/user_list.html b/chromium/chrome/browser/resources/settings/people_page/user_list.html
index 560410b21eb..3303a46501c 100644
--- a/chromium/chrome/browser/resources/settings/people_page/user_list.html
+++ b/chromium/chrome/browser/resources/settings/people_page/user_list.html
@@ -1,4 +1,5 @@
<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
@@ -29,18 +30,15 @@
}
.user-info {
- -webkit-padding-start: 16px;
+ -webkit-padding-start: 20px;
}
</style>
<div class="user-list">
<template is="dom-repeat" items="[[users_]]">
<div class="user layout horizontal center two-line">
- <img class="user-icon" src="[[getProfilePictureUrl_(item.name)]]">
+ <img class="user-icon" src="[[getProfilePictureUrl_(item)]]">
<div class="flex user-info">
- <div>
- [[item.name]]
- <span hidden="[[!item.isOwner]]">$i18n{deviceOwnerLabel}</span>
- </div>
+ <div>[[getUserName_(item)]]</div>
<div class="secondary">[[item.email]]</div>
</div>
<paper-icon-button icon="cr:clear" class="clear-icon"
diff --git a/chromium/chrome/browser/resources/settings/people_page/user_list.js b/chromium/chrome/browser/resources/settings/people_page/user_list.js
index 21f3b530596..10a3e356e80 100644
--- a/chromium/chrome/browser/resources/settings/people_page/user_list.js
+++ b/chromium/chrome/browser/resources/settings/people_page/user_list.js
@@ -15,9 +15,7 @@
Polymer({
is: 'settings-user-list',
- behaviors: [
- settings.RouteObserverBehavior,
- ],
+ behaviors: [I18nBehavior, settings.RouteObserverBehavior],
properties: {
/**
@@ -26,7 +24,9 @@ Polymer({
*/
users_: {
type: Array,
- value: function() { return []; },
+ value: function() {
+ return [];
+ },
notify: true
},
@@ -37,7 +37,7 @@ Polymer({
*/
disabled: {
type: Boolean,
- value: false
+ value: false,
}
},
@@ -64,6 +64,15 @@ Polymer({
},
/**
+ * @param {!chrome.usersPrivate.User} user
+ * @return {string}
+ * @private
+ */
+ getUserName_: function(user) {
+ return user.isOwner ? this.i18n('deviceOwnerLabel', user.name) : user.name;
+ },
+
+ /**
* Helper function that sorts and sets the given list of whitelisted users.
* @param {!Array<!chrome.usersPrivate.User>} users List of whitelisted users.
*/
@@ -91,8 +100,11 @@ Polymer({
return disabled || isUserOwner;
},
- /** @private */
- getProfilePictureUrl_: function(username) {
- return 'chrome://userimage/' + username + '?id=' + Date.now();
+ /**
+ * @param {chrome.usersPrivate.User} user
+ * @private
+ */
+ getProfilePictureUrl_: function(user) {
+ return 'chrome://userimage/' + user.email + '?id=' + Date.now();
}
});
diff --git a/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.html b/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.html
index 0082fecaa47..69cd20b555f 100644
--- a/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.html
+++ b/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.html
@@ -1,7 +1,6 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="../settings_shared_css.html">
@@ -21,15 +20,15 @@
<div class="title">$i18n{addUsers}</div>
<div class="body">
<paper-input id="addUserInput" label="$i18n{addUsersEmail}" autofocus
- on-input="validate_">
- <iron-a11y-keys id="keys" keys="enter" on-keys-pressed="addUser_">
- </iron-a11y-keys>
+ on-input="validate_" invalid="[[!isValid_]]">
</paper-input>
</div>
<div class="button-container">
- <paper-button class="cancel-button" on-tap="onCancelTap_"
- id="cancel">$i18n{cancel}</paper-button>
- <paper-button id="add" on-tap="addUser_" class="action-button" disabled>
+ <paper-button class="cancel-button" on-tap="onCancelTap_">
+ $i18n{cancel}
+ </paper-button>
+ <paper-button on-tap="addUser_" class="action-button"
+ disabled$="[[!isValid_]]">
$i18n{add}
</paper-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.js b/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.js
index b1383ee9516..99b27488184 100644
--- a/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.js
+++ b/chromium/chrome/browser/resources/settings/people_page/users_add_user_dialog.js
@@ -32,7 +32,16 @@ var EMAIL_REGEX = new RegExp(
Polymer({
is: 'settings-users-add-user-dialog',
+ properties: {
+ /** @private */
+ isValid_: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
open: function() {
+ this.isValid_ = false;
this.$.dialog.showModal();
},
@@ -48,11 +57,8 @@ Polymer({
*/
validate_: function() {
var input = this.$.addUserInput.value;
- var valid = NAME_ONLY_REGEX.test(input) || EMAIL_REGEX.test(input);
-
- this.$.add.disabled = !valid;
- this.$.addUserInput.invalid = !valid;
- return valid;
+ this.isValid_ = NAME_ONLY_REGEX.test(input) || EMAIL_REGEX.test(input);
+ return this.isValid_;
},
/** @private */
diff --git a/chromium/chrome/browser/resources/settings/people_page/users_page.html b/chromium/chrome/browser/resources/settings/people_page/users_page.html
index 6a542f2996f..318d936e1f2 100644
--- a/chromium/chrome/browser/resources/settings/people_page/users_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/users_page.html
@@ -11,18 +11,13 @@
<dom-module id="settings-users-page">
<template>
<style include="settings-shared action-link">
- .users {
- /* The users box must line up with the checkbox text. */
- -webkit-margin-start: var(--settings-indent-width);
- }
-
.settings-box:first-of-type {
border-top: none;
}
#add-user-button {
/* Add user button must be lined up with the start of users' names. */
- -webkit-margin-start: 56px;
+ -webkit-margin-start: var(--settings-box-row-indent);
}
</style>
<template is="dom-if" if="[[isWhitelistManaged_]]">
@@ -56,21 +51,22 @@
disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]"
inverted>
</settings-toggle-button>
- <div class="users">
- <settings-user-list prefs="[[prefs]]"
- disabled="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_,
- prefs.cros.accounts.allowGuest.value)]]">
- </settings-user-list>
- <div id="add-user-button" class="list-item"
- hidden="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_,
- prefs.cros.accounts.allowGuest.value)]]">
- <a is="action-link" class="list-button" on-tap="openAddUserDialog_">
- $i18n{addUsers}
- </a>
- </div>
+ </div>
+ <div class="list-frame">
+ <settings-user-list prefs="[[prefs]]"
+ disabled="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_,
+ prefs.cros.accounts.allowGuest.value)]]">
+ </settings-user-list>
+ <div id="add-user-button" class="list-item"
+ hidden="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_,
+ prefs.cros.accounts.allowGuest.value)]]">
+ <a is="action-link" class="list-button" on-tap="openAddUserDialog_">
+ $i18n{addUsers}
+ </a>
</div>
</div>
- <settings-users-add-user-dialog id="addUserDialog">
+ <settings-users-add-user-dialog id="addUserDialog"
+ on-close="onAddUserDialogClose_">
</settings-users-add-user-dialog>
</template>
<script src="users_page.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/people_page/users_page.js b/chromium/chrome/browser/resources/settings/people_page/users_page.js
index 4114350745f..c02c26a7e4d 100644
--- a/chromium/chrome/browser/resources/settings/people_page/users_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/users_page.js
@@ -52,6 +52,11 @@ Polymer({
this.$.addUserDialog.open();
},
+ /** @private */
+ onAddUserDialogClose_: function() {
+ this.$$('#add-user-button a').focus();
+ },
+
/**
* @param {boolean} isOwner
* @param {boolean} isWhitelistManaged
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cloud_printers.html b/chromium/chrome/browser/resources/settings/printing_page/cloud_printers.html
index 2321a7bfbda..d47403fc297 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cloud_printers.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cloud_printers.html
@@ -20,16 +20,12 @@
label="$i18n{printingNotificationsLabel}">
</settings-toggle-button>
</div>
- <div class="settings-box two-line" on-tap="onManageTap_" actionable>
+ <div class="settings-box" on-tap="onManageTap_" actionable>
<div class="start">
$i18n{printingManageCloudPrintDevices}
- <div class="secondary" id="manageCloudPrintSecondary">
- $i18n{printingManageCloudPrintDevicesDescription}
- </div>
</div>
<button class="icon-external" is="paper-icon-button-light"
- aria-label="$i18n{printingManageCloudPrintDevices}"
- aria-describedby="manageCloudPrintSecondary"></button>
+ aria-label="$i18n{printingManageCloudPrintDevices}"></button>
</div>
</template>
<script src="cloud_printers.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
index f80c347472e..e802ed11e33 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -41,8 +41,10 @@
width: 15px;
}
- #manuallyAddPrinterButton {
- -webkit-margin-end: 210px;
+ .dialog-buttons {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
}
</style>
<add-printer-dialog>
@@ -60,17 +62,23 @@
</div>
</div>
<div class="dialog-buttons">
- <paper-button id="manuallyAddPrinterButton"
- on-tap="switchToManualAddDialog_">
- $i18n{manuallyAddPrinterButtonText}
- </paper-button>
- <paper-button class="cancel-button" on-tap="onCancelTap_">
- $i18n{cancelButtonText}
- </paper-button>
- <paper-button class="action-button" id="addPrinterButton"
- disabled="[[!selectedPrinter]]" on-tap="switchToConfiguringDialog_">
- $i18n{addPrinterButtonText}
- </paper-button>
+ <div> <!-- Left group -->
+ <paper-button id="manuallyAddPrinterButton" class="secondary-button"
+ on-tap="switchToManualAddDialog_">
+ $i18n{manuallyAddPrinterButtonText}
+ </paper-button>
+ </div>
+ <div> <!-- Right group -->
+ <paper-button class="cancel-button secondary-button"
+ on-tap="onCancelTap_">
+ $i18n{cancelButtonText}
+ </paper-button>
+ <paper-button class="action-button" id="addPrinterButton"
+ disabled="[[!selectedPrinter]]"
+ on-tap="switchToConfiguringDialog_">
+ $i18n{addPrinterButtonText}
+ </paper-button>
+ </div>
</div>
</add-printer-dialog>
</template>
@@ -97,7 +105,7 @@
.md-select,
paper-input {
- --paper-input-container-color: var(--google-grey-500);
+ --paper-input-container-color: var(--paper-grey-600);
--paper-input-container-input: {
font-size: inherit;
};
@@ -160,10 +168,10 @@
</div>
<div class="settings-box two-line">
<div class="start">
- <div class="label">$i18n{printerProtocol}</div>
+ <div id="printerProtocol" class="label">$i18n{printerProtocol}</div>
<div class="secondary">
<div class="md-select-wrapper">
- <select class="md-select"
+ <select class="md-select" aria-labelledby="printerProtocol"
value="[[newPrinter.printerProtocol]]"
on-change="onProtocolChange_">
<option value="ipp">$i18n{printerProtocolIpp}</option>
@@ -173,7 +181,6 @@
<option value="socket">$i18n{printerProtocolAppSocket}
</option>
<option value="lpd">$i18n{printerProtocolLpd}</option>
- <option value="usb">$i18n{printerProtocolUsb}</option>
</select>
<span class="md-select-underline"></span>
</div>
@@ -202,7 +209,8 @@
</div>
</div>
<div class="dialog-buttons">
- <paper-button class="cancel-button" on-tap="onCancelTap_">
+ <paper-button class="cancel-button secondary-button"
+ on-tap="onCancelTap_">
$i18n{cancelButtonText}
</paper-button>
<paper-button class="action-button" on-tap="switchToManufacturerDialog_"
@@ -231,7 +239,7 @@
}
paper-input {
- --paper-input-container-color: var(--google-grey-500);
+ --paper-input-container-color: var(--paper-grey-600);
--paper-input-container-input: {
font-size: inherit;
border: 1px solid lightgray;
@@ -252,8 +260,10 @@
padding: 10px 20px;
}
- #manuallyAddPrinterButton {
- -webkit-margin-end: 210px;
+ .dialog-buttons {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
}
#browseButton {
@@ -304,17 +314,22 @@
</div>
</div>
<div class="dialog-buttons">
- <paper-button id="manuallyAddPrinterButton"
- on-tap="switchToManualAddDialog_">
- $i18n{manuallyAddPrinterButtonText}
- </paper-button>
- <paper-button class="cancel-button" on-tap="onCancelTap_">
- $i18n{cancelButtonText}
- </paper-button>
- <paper-button class="action-button" id="addPrinterButton"
- on-tap="switchToConfiguringDialog_">
- $i18n{addPrinterButtonText}
- </paper-button>
+ <div> <!-- Left group -->
+ <paper-button id="manuallyAddPrinterButton" class="secondary-button"
+ on-tap="switchToManualAddDialog_">
+ $i18n{manuallyAddPrinterButtonText}
+ </paper-button>
+ </div>
+ <div> <!-- Right group -->
+ <paper-button class="cancel-button secondary-button"
+ on-tap="onCancelTap_">
+ $i18n{cancelButtonText}
+ </paper-button>
+ <paper-button class="action-button" id="addPrinterButton"
+ on-tap="switchToConfiguringDialog_">
+ $i18n{addPrinterButtonText}
+ </paper-button>
+ </div>
</div>
</add-printer-dialog>
</template>
@@ -335,7 +350,8 @@
<div id="configuringMessage">$i18n{printerConfiguringMessage}</div>
</div>
<div class="dialog-buttons">
- <paper-button class="cancel-button" on-tap="onCancelConfiguringTap_">
+ <paper-button class="cancel-button secondary-button"
+ on-tap="onCancelConfiguringTap_">
$i18n{cancelButtonText}
</paper-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
index 6d20849152c..d97e93bd526 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -135,7 +135,7 @@ Polymer({
printerName: '',
printerPPDPath: '',
printerProtocol: 'ipp',
- printerQueue: '',
+ printerQueue: 'ipp/print',
printerStatus: '',
};
},
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
index 4afc3444aa6..2b279137dca 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
@@ -63,7 +63,7 @@
}
paper-input-container {
- --paper-input-container-color: var(--google-grey-500);
+ --paper-input-container-color: var(--paper-grey-600);
--paper-input-container-input: {
font-size: inherit;
};
@@ -76,8 +76,8 @@
padding: 8px 0;
}
</style>
- <paper-input-container no-label-float>
- <input is="iron-input" type="search" on-tap="onTap_"
+ <paper-input-container no-label-float on-tap="onTap_">
+ <input is="iron-input" type="search"
on-search="onInputValueChanged_" on-change="onChange_" incremental>
<paper-icon-button suffix id="searchIcon" icon="cr:search" hidden>
</paper-icon-button>
@@ -106,14 +106,7 @@
}
#dialog .button-container {
- border-top: 1px solid rgba(0, 0, 0, 0.14);
- margin-top: 0;
- padding-top: 10px;
- }
-
- #dialog .button-container ::content paper-button {
- font-size: 107.69%; /* 14px / 13px */
- font-weight: bold;
+ border-top: 1px solid var(--paper-grey-300);
}
</style>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html
index 24ea9b13171..19c8b0e7560 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html
@@ -9,7 +9,7 @@
<template>
<style include="settings-shared action-link">
.settings-box .start {
- color: var(--paper-grey-500);
+ color: var(--paper-grey-600);
}
.settings-box .start .secondary {
@@ -46,7 +46,7 @@
</style>
<div class="settings-box first">
- <a is="action-link" on-tap="onAddPrinterTap_"
+ <a id="addPrinter" is="action-link" on-tap="onAddPrinterTap_"
hidden="[[!canAddPrinter_]]">
$i18n{addCupsPrinter}
</a>
@@ -58,7 +58,8 @@
</div>
</div>
- <settings-cups-add-printer-dialog id="addPrinterDialog">
+ <settings-cups-add-printer-dialog id="addPrinterDialog"
+ on-close="onAddPrinterDialogClose_">
</settings-cups-add-printer-dialog>
<settings-cups-printers-list printers="{{printers}}"
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js
index 94f9bc8fd79..b9c0e00b28e 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js
@@ -118,4 +118,9 @@ Polymer({
this.$.addPrinterDialog.open();
this.$.addPrinterErrorMessage.hidden = true;
},
+
+ /** @private */
+ onAddPrinterDialogClose_: function() {
+ this.$$('#addPrinter').focus();
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/printing_page/printing_page.html b/chromium/chrome/browser/resources/settings/printing_page/printing_page.html
index dbfa5cf78c4..29ebbe9f110 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/printing_page.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/printing_page.html
@@ -14,7 +14,8 @@
<dom-module id="settings-printing-page">
<template>
<style include="settings-shared"></style>
- <settings-animated-pages id="pages" section="printing">
+ <settings-animated-pages id="pages" section="printing"
+ focus-config="[[focusConfig_]]">
<array-selector id="arraySelector" items="{{cupsPrinters}}"
selected="{{detailPrinter_}}">
</array-selector>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/printing_page.js b/chromium/chrome/browser/resources/settings/printing_page/printing_page.js
index a58001fbe48..eb1bb21280b 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/printing_page.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/printing_page.js
@@ -34,6 +34,22 @@ Polymer({
searchTerm: {
type: String,
},
+
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+ map.set(
+ settings.Route.CLOUD_PRINTERS.path,
+ '#cloudPrinters .subpage-arrow');
+// <if expr="chromeos">
+ map.set(
+ settings.Route.CUPS_PRINTERS.path, '#cupsPrinters .subpage-arrow');
+// </if>
+ return map;
+ },
+ },
},
listeners: {
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/privacy_page/compiled_resources2.gyp
index c842549db91..50ac0e5c39d 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/privacy_page/compiled_resources2.gyp
@@ -18,6 +18,7 @@
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'../compiled_resources2.gyp:route',
+ '../controls/compiled_resources2.gyp:settings_toggle_button',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
'../settings_ui/compiled_resources2.gyp:settings_ui_types',
'../site_settings/compiled_resources2.gyp:constants',
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
index 3e2e0de7d61..b6e0dce6d89 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -1,4 +1,5 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_vars_css.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
@@ -41,7 +42,8 @@
on-close="onDialogClosed_">
</settings-clear-browsing-data-dialog>
</template>
- <settings-animated-pages id="pages" section="privacy">
+ <settings-animated-pages id="pages" section="privacy"
+ focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<div class="settings-box first">
<p class="privacy-explanation">$i18nRaw{improveBrowsingExperience}</p>
@@ -109,9 +111,28 @@
</if><!-- not chromeos -->
</if><!-- _google_chrome -->
<div class="settings-box">
- <settings-toggle-button class="start"
- pref="{{prefs.enable_do_not_track}}"
- label="$i18n{doNotTrack}">
+ <template id="doNotTrackDialogIf" is="dom-if"
+ if="[[showDoNotTrackDialog_]]" notify-dom-change>
+ <dialog is="cr-dialog" id="confirmDoNotTrackDialog"
+ close-text="$i18n{close}" on-cancel="onDoNotTrackDialogCancel_">
+ <div class="title">$i18n{doNotTrackDialogTitle}</div>
+ <div class="body">$i18nRaw{doNotTrackDialogMessage}</div>
+ <div class="button-container">
+ <paper-button class="cancel-button"
+ on-tap="onDoNotTrackDialogCancel_">
+ $i18n{cancel}
+ </paper-button>
+ <paper-button class="action-button"
+ on-tap="onDoNotTrackDialogConfirm_">
+ $i18n{confirm}
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <settings-toggle-button id="doNotTrack" class="start"
+ pref="{{prefs.enable_do_not_track}}" label="$i18n{doNotTrack}"
+ on-settings-boolean-control-change="onDoNotTrackChange_"
+ no-set-pref>
</settings-toggle-button>
</div>
<if expr="chromeos">
@@ -179,8 +200,8 @@
$i18n{clearBrowsingDataDescription}
</div>
</div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{clearBrowsingData}"
+ <button is="paper-icon-button-light" id="clearBrowsingDataTrigger"
+ class="subpage-arrow" aria-label="$i18n{clearBrowsingData}"
aria-describedby="clearBrowsingDataSecondary"></button>
</div>
</neon-animatable>
@@ -200,7 +221,8 @@
id="site-settings"
page-title="[[siteSettingsPageTitle_()]]"
learn-more-url="$i18n{exceptionsLearnMoreURL}">
- <settings-site-settings-page></settings-site-settings-page>
+ <settings-site-settings-page focus-config="[[focusConfig_]]">
+ </settings-site-settings-page>
</settings-subpage>
</template>
@@ -236,14 +258,15 @@
</template>
<template is="dom-if" route-path="/content/camera" no-search>
<settings-subpage page-title="$i18n{siteSettingsCategoryCamera}">
- <media-picker type="camera"></media-picker>
+ <media-picker label="$i18n{siteSettingsCameraLabel}" type="camera">
+ </media-picker>
<category-default-setting category="{{ContentSettingsTypes.CAMERA}}"
toggle-off-label="$i18n{siteSettingsBlocked}"
toggle-on-label=
"$i18n{siteSettingsAskBeforeAccessingRecommended}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.CAMERA}}">
+ category="{{ContentSettingsTypes.CAMERA}}" read-only-list>
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -252,10 +275,9 @@
<category-default-setting category="{{ContentSettingsTypes.COOKIES}}"
toggle-off-label="$i18n{siteSettingsBlocked}"
toggle-on-label="$i18n{siteSettingsCookiesAllowedRecommended}"
- sub-option-label="$i18n{deleteDataPostSession}"
- sub-option-secondary=""><!-- To work with :empty. -->
+ sub-option-label="$i18n{deleteDataPostSession}">
</category-default-setting>
- <div class="settings-box">
+ <div class="settings-box two-line">
<settings-toggle-button class="start"
pref="{{prefs.profile.block_third_party_cookies}}"
label="$i18n{thirdPartyCookie}"
@@ -265,7 +287,7 @@
<category-setting-exceptions
category="{{ContentSettingsTypes.COOKIES}}">
</category-setting-exceptions>
- <site-data></site-data>
+ <site-data focus-config="[[focusConfig_]]"></site-data>
</settings-subpage>
</template>
<template is="dom-if" route-path="/content/images" no-search>
@@ -287,7 +309,7 @@
category="{{ContentSettingsTypes.GEOLOCATION}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.GEOLOCATION}}">
+ category="{{ContentSettingsTypes.GEOLOCATION}}" read-only-list>
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -323,13 +345,15 @@
</template>
<template is="dom-if" route-path="/content/microphone" no-search>
<settings-subpage page-title="$i18n{siteSettingsCategoryMicrophone}">
- <media-picker type="mic"></media-picker>
+ <media-picker label="$i18n{siteSettingsMicrophoneLabel}" type="mic">
+ </media-picker>
<category-default-setting category="{{ContentSettingsTypes.MIC}}"
toggle-off-label="$i18n{siteSettingsBlocked}"
toggle-on-label=
"$i18n{siteSettingsAskBeforeAccessingRecommended}">
</category-default-setting>
- <category-setting-exceptions category="{{ContentSettingsTypes.MIC}}">
+ <category-setting-exceptions
+ category="{{ContentSettingsTypes.MIC}}" read-only-list>
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -377,7 +401,20 @@
</category-setting-exceptions>
</settings-subpage>
</template>
- <template is="dom-if" route-path="/content/unsandboxedPlugins" no-search>
+ <template is="dom-if" if="[[enableSafeBrowsingSubresourceFilter_]]"
+ route-path="/content/subresourceFilter" no-search>
+ <settings-subpage page-title="$i18n{siteSettingsSubresourceFilter}">
+ <category-default-setting
+ category="{{ContentSettingsTypes.SUBRESOURCE_FILTER}}"
+ toggle-off-label="$i18n{siteSettingsSubresourceFilterAllow}"
+ toggle-on-label="$i18n{siteSettingsSubresourceFilterBlock}">
+ </category-default-setting>
+ <category-setting-exceptions
+ category="{{ContentSettingsTypes.SUBRESOURCE_FITER}}">
+ </category-setting-exceptions>
+ </settings-subpage>
+ </template>
+ <template is="dom-if" route-path="/content/unsandboxedPlugins" no-search>
<settings-subpage page-title="$i18n{siteSettingsUnsandboxedPlugins}">
<category-default-setting
toggle-off-label="$i18n{siteSettingsUnsandboxedPluginsBlock}"
@@ -399,7 +436,7 @@
category="{{ContentSettingsTypes.MIDI_DEVICES}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.MIDI_DEVICES}}">
+ category="{{ContentSettingsTypes.MIDI_DEVICES}}" read-only-list>
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -415,7 +452,7 @@
</template>
<template is="dom-if" route-path="/cookies/detail" no-search>
<settings-subpage page-title="[[pageTitle]]">
- <paper-button class="subpage-title-extra"
+ <paper-button class="subpage-title-extra secondary-button"
on-tap="onRemoveAllCookiesFromSite_">
$i18n{siteSettingsCookieRemoveAll}
</paper-button>
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
index 825633f929f..a8ac9506de2 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
+++ b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -77,6 +77,12 @@ Polymer({
/** @private */
showClearBrowsingDataDialog_: Boolean,
+ /** @private */
+ showDoNotTrackDialog_: {
+ type: Boolean,
+ value: false,
+ },
+
/**
* Used for HTML bindings. This is defined as a property rather than within
* the ready callback, because the value needs to be available before
@@ -87,6 +93,35 @@ Polymer({
type: Object,
value: NetworkPredictionOptions,
},
+
+ /** @private */
+ enableSafeBrowsingSubresourceFilter_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('enableSafeBrowsingSubresourceFilter');
+ }
+ },
+
+ /** @private {!Map<string, string>} */
+ focusConfig_: {
+ type: Object,
+ value: function() {
+ var map = new Map();
+// <if expr="use_nss_certs">
+ map.set(
+ settings.Route.CERTIFICATES.path,
+ '#manageCertificates .subpage-arrow');
+// </if>
+ map.set(
+ settings.Route.SITE_SETTINGS.path,
+ '#site-settings-subpage-trigger .subpage-arrow');
+ return map;
+ },
+ },
+ },
+
+ listeners: {
+ 'doNotTrackDialogIf.dom-change': 'onDoNotTrackDomChange_',
},
ready: function() {
@@ -111,6 +146,68 @@ Polymer({
settings.getCurrentRoute() == settings.Route.CLEAR_BROWSER_DATA;
},
+ /**
+ * @param {Event} event
+ * @private
+ */
+ onDoNotTrackDomChange_: function(event) {
+ if (this.showDoNotTrackDialog_)
+ this.maybeShowDoNotTrackDialog_();
+ },
+
+ /**
+ * Handles the change event for the do-not-track toggle. Shows a
+ * confirmation dialog when enabling the setting.
+ * @param {Event} event
+ * @private
+ */
+ onDoNotTrackChange_: function(event) {
+ var target = /** @type {!SettingsToggleButtonElement} */(event.target);
+ if (!target.checked) {
+ // Always allow disabling the pref.
+ target.sendPrefChange();
+ return;
+ }
+ this.showDoNotTrackDialog_ = true;
+ // If the dialog has already been stamped, show it. Otherwise it will be
+ // shown in onDomChange_.
+ this.maybeShowDoNotTrackDialog_();
+ },
+
+ /** @private */
+ maybeShowDoNotTrackDialog_: function() {
+ var dialog = this.$$('#confirmDoNotTrackDialog');
+ if (dialog && !dialog.open)
+ dialog.showModal();
+ },
+
+ /** @private */
+ closeDoNotTrackDialog_: function() {
+ this.$$('#confirmDoNotTrackDialog').close();
+ this.showDoNotTrackDialog_ = false;
+ },
+
+ /**
+ * Handles the shared proxy confirmation dialog 'Confirm' button.
+ * @private
+ */
+ onDoNotTrackDialogConfirm_: function() {
+ /** @type {!SettingsToggleButtonElement} */ (this.$.doNotTrack)
+ .sendPrefChange();
+ this.closeDoNotTrackDialog_();
+ },
+
+ /**
+ * Handles the shared proxy confirmation dialog 'Cancel' button or a cancel
+ * event.
+ * @private
+ */
+ onDoNotTrackDialogCancel_: function() {
+ /** @type {!SettingsToggleButtonElement} */ (this.$.doNotTrack)
+ .resetToPrefValue();
+ this.closeDoNotTrackDialog_();
+ },
+
/** @private */
onManageCertificatesTap_: function() {
// <if expr="use_nss_certs">
@@ -145,6 +242,7 @@ Polymer({
/** @private */
onDialogClosed_: function() {
settings.navigateToPreviousRoute();
+ this.$.clearBrowsingDataTrigger.focus();
},
/** @private */
diff --git a/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html b/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
index 5d83ffb60bb..0bb75c311a5 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
+++ b/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
@@ -10,7 +10,8 @@
<template>
<style include="settings-shared">
</style>
- <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
+ <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"
+ ignore-enter-key>
<div class="title">$i18n{powerwashDialogTitle}</div>
<div class="body">
<span>
diff --git a/chromium/chrome/browser/resources/settings/reset_page/reset_page.html b/chromium/chrome/browser/resources/settings/reset_page/reset_page.html
index ce27e28e009..dd9e6804a71 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/reset_page.html
+++ b/chromium/chrome/browser/resources/settings/reset_page/reset_page.html
@@ -21,8 +21,8 @@
$i18n{resetPageDescription}
</div>
</div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{resetPageTitle}"
+ <button id="resetProfileArrow" is="paper-icon-button-light"
+ class="subpage-arrow" aria-label="$i18n{resetPageTitle}"
aria-describedby="resetProfileSecondary"></button>
</div>
<template is="dom-if" if="[[showResetProfileDialog_]]" restamp>
@@ -38,8 +38,8 @@
$i18n{powerwashDescription}
</div>
</div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{powerwashTitle}"
+ <button id="powerwashArrow" is="paper-icon-button-light"
+ class="subpage-arrow" aria-label="$i18n{powerwashTitle}"
aria-describedby="powerwashSecondary"></button>
</div>
<template is="dom-if" if="[[showPowerwashDialog_]]" restamp>
diff --git a/chromium/chrome/browser/resources/settings/reset_page/reset_page.js b/chromium/chrome/browser/resources/settings/reset_page/reset_page.js
index 20ca0b88db1..c46eace46b2 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/reset_page.js
+++ b/chromium/chrome/browser/resources/settings/reset_page/reset_page.js
@@ -59,6 +59,7 @@ Polymer({
/** @private */
onResetProfileDialogClose_: function() {
settings.navigateToPreviousRoute();
+ this.$.resetProfileArrow.focus();
},
// <if expr="chromeos">
@@ -74,6 +75,7 @@ Polymer({
/** @private */
onPowerwashDialogClose_: function() {
this.showPowerwashDialog_ = false;
+ this.$.powerwashArrow.focus();
},
// </if>
});
diff --git a/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html b/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
index f471d72d482..0240e33a0d8 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
+++ b/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html
@@ -15,15 +15,12 @@
<dom-module id="settings-reset-profile-dialog">
<template>
<style include="settings-shared action-link">
- .footer a {
- vertical-align: middle;
- }
-
paper-spinner {
margin: 0 8px;
}
</style>
- <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}" ignore-popstate>
+ <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"
+ ignore-popstate ignore-enter-key>
<div class="title">
[[getPageTitle_(isTriggered_, triggeredResetToolName_)]]
</div>
@@ -48,10 +45,8 @@
</paper-button>
</div>
<div class="footer border-top-divider">
- <paper-checkbox id="sendSettings"
- checked>$i18n{resetPageFeedback}</paper-checkbox>
- <a is="action-link"
- on-tap="onShowReportedSettingsTap_">$i18n{viewReportedSettings}</a>
+ <paper-checkbox id="sendSettings" checked>
+ $i18nRaw{resetPageFeedback}</paper-checkbox>
</div>
</dialog>
</template>
diff --git a/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js b/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js
index 5e89ad531d5..5328fe42652 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js
+++ b/chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js
@@ -75,6 +75,13 @@ Polymer({
this.addEventListener('cancel', function() {
this.browserProxy_.onHideResetProfileDialog();
}.bind(this));
+
+ this.$$('paper-checkbox a').addEventListener(
+ 'tap', this.onShowReportedSettingsTap_.bind(this));
+ // Prevent toggling of the checkbox when hitting the "Enter" key on the
+ // link.
+ this.$$('paper-checkbox a').addEventListener(
+ 'keydown', function(e) { e.stopPropagation(); });
},
/** @private */
@@ -123,9 +130,11 @@ Polymer({
/**
* Displays the settings that will be reported in a new tab.
+ * @param {!Event} e
* @private
*/
- onShowReportedSettingsTap_: function() {
+ onShowReportedSettingsTap_: function(e) {
this.browserProxy_.showReportedSettings();
+ e.stopPropagation();
},
});
diff --git a/chromium/chrome/browser/resources/settings/route.html b/chromium/chrome/browser/resources/settings/route.html
index 102248ead53..1300e8577e7 100644
--- a/chromium/chrome/browser/resources/settings/route.html
+++ b/chromium/chrome/browser/resources/settings/route.html
@@ -1,3 +1,4 @@
<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="i18n_setup.html">
<script src="route.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/route.js b/chromium/chrome/browser/resources/settings/route.js
index 87a714c04bc..8dfa435c8b8 100644
--- a/chromium/chrome/browser/resources/settings/route.js
+++ b/chromium/chrome/browser/resources/settings/route.js
@@ -18,8 +18,16 @@ cr.define('settings', function() {
/** @type {number} */
this.depth = 0;
+ /**
+ * @type {boolean} Whether this route corresponds to a navigable
+ * dialog. Those routes don't belong to a "section".
+ */
+ this.isNavigableDialog = false;
+
// Below are all legacy properties to provide compatibility with the old
- // routing system. TODO(tommycli): Remove once routing refactor complete.
+ // routing system.
+
+ /** @type {string} */
this.section = '';
};
@@ -94,11 +102,16 @@ cr.define('settings', function() {
// Navigable dialogs. These are the only non-section children of root pages.
// These are disfavored. If we add anymore, we should add explicit support.
r.IMPORT_DATA = r.BASIC.createChild('/importData');
+ r.IMPORT_DATA.isNavigableDialog = true;
r.SIGN_OUT = r.BASIC.createChild('/signOut');
+ r.SIGN_OUT.isNavigableDialog = true;
r.CLEAR_BROWSER_DATA = r.ADVANCED.createChild('/clearBrowserData');
+ r.CLEAR_BROWSER_DATA.isNavigableDialog = true;
r.RESET_DIALOG = r.ADVANCED.createChild('/resetProfileSettings');
+ r.RESET_DIALOG.isNavigableDialog = true;
r.TRIGGERED_RESET_DIALOG =
r.ADVANCED.createChild('/triggeredResetProfileSettings');
+ r.TRIGGERED_RESET_DIALOG.isNavigableDialog = true;
// <if expr="chromeos">
r.INTERNET = r.BASIC.createSection('/internet', 'internet');
@@ -120,6 +133,7 @@ cr.define('settings', function() {
// <if expr="chromeos">
r.ANDROID_APPS = r.BASIC.createSection('/androidApps', 'androidApps');
+ r.ANDROID_APPS_DETAILS = r.ANDROID_APPS.createChild('/androidApps/details');
// </if>
r.ON_STARTUP = r.BASIC.createSection('/onStartup', 'onStartup');
@@ -148,9 +162,12 @@ cr.define('settings', function() {
r.CERTIFICATES = r.PRIVACY.createChild('/certificates');
r.SITE_SETTINGS = r.PRIVACY.createChild('/content');
- r.SITE_SETTINGS_ALL = r.SITE_SETTINGS.createChild('all');
- r.SITE_SETTINGS_SITE_DETAILS =
- r.SITE_SETTINGS_ALL.createChild('/content/siteDetails');
+
+ if (loadTimeData.getBoolean('enableSiteSettings')) {
+ r.SITE_SETTINGS_ALL = r.SITE_SETTINGS.createChild('all');
+ r.SITE_SETTINGS_SITE_DETAILS =
+ r.SITE_SETTINGS_ALL.createChild('/content/siteDetails');
+ }
r.SITE_SETTINGS_HANDLERS = r.SITE_SETTINGS.createChild('/handlers');
@@ -178,6 +195,8 @@ cr.define('settings', function() {
r.SITE_SETTINGS_PDF_DOCUMENTS = r.SITE_SETTINGS.createChild('pdfDocuments');
r.SITE_SETTINGS_PROTECTED_CONTENT =
r.SITE_SETTINGS.createChild('protectedContent');
+ r.SITE_SETTINGS_SUBRESOURCE_FILTER =
+ r.SITE_SETTINGS.createChild('subresourceFilter');
// <if expr="chromeos">
r.DATETIME = r.ADVANCED.createSection('/dateTime', 'dateTime');
@@ -206,7 +225,9 @@ cr.define('settings', function() {
// </if>
r.ACCESSIBILITY = r.ADVANCED.createSection('/accessibility', 'a11y');
+// <if expr="chromeos">
r.MANAGE_ACCESSIBILITY = r.ACCESSIBILITY.createChild('/manageAccessibility');
+// </if>
r.SYSTEM = r.ADVANCED.createSection('/system', 'system');
r.RESET = r.ADVANCED.createSection('/reset', 'reset');
@@ -353,6 +374,11 @@ cr.define('settings', function() {
* parameter during navigation. Defaults to false.
*/
var navigateTo = function(route, opt_dynamicParameters, opt_removeSearch) {
+ // The ADVANCED route only serves as a parent of subpages, and should not
+ // be possible to navigate to it directly.
+ if (route == settings.Route.ADVANCED)
+ route = settings.Route.BASIC;
+
var params = opt_dynamicParameters || new URLSearchParams();
var removeSearch = !!opt_removeSearch;
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/search_engines_page/compiled_resources2.gyp
index 89c67ad13a7..5d0a0abd7c0 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/compiled_resources2.gyp
@@ -20,7 +20,7 @@
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
'search_engines_browser_proxy',
- '../compiled_resources2.gyp:focusable_iron_list_item_behavior',
+ '../compiled_resources2.gyp:focus_row_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -47,7 +47,6 @@
{
'target_name': 'search_engines_list',
'dependencies': [
- '../compiled_resources2.gyp:global_scroll_target_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'search_engines_browser_proxy',
],
@@ -56,6 +55,7 @@
{
'target_name': 'search_engines_page',
'dependencies': [
+ '../compiled_resources2.gyp:global_scroll_target_behavior',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html b/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html
index 68407effe06..5232404d0b1 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html
@@ -11,12 +11,19 @@
<template>
<style include="settings-shared search-engine-entry">
.name-column {
+ align-items: center;
+ display: flex;
flex: 3;
+ word-break: break-word;
}
.keyword-column {
flex: 7;
}
+
+ .favicon-image + span {
+ -webkit-margin-end: 8px;
+ }
</style>
<div class="list-item">
<div class="name-column">
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js b/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js
index 30600fd9666..25a90f06005 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js
@@ -12,11 +12,11 @@ Polymer({
properties: {
/** @type {!SearchEngine} */
engine: Object,
-
- /** @private {!settings.ExtensionControlBrowserProxy} */
- browserProxy_: Object,
},
+ /** @private {?settings.ExtensionControlBrowserProxy} */
+ browserProxy_: null,
+
/** @override */
created: function() {
this.browserProxy_ =
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html
index 31ec66cb223..e1161cee009 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html
@@ -7,24 +7,37 @@
<dom-module id="settings-search-engine-dialog">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ :host {
+ --paper-input-container: {
+ /**
+ * Saves space for error message. Using calc to leave just enough
+ * space at all font sizes (default 0, grow/shrink with font-size).
+ * Using padding instead of padding-bottom to prevent
+ * paper-input-container's default padding rule to eat up the
+ * padding-bottom rule.
+ */
+ padding: 8px 0 calc(1rem - 8px) 0;
+ };
+ }
+ </style>
<dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
<div class="title">[[dialogTitle_]]</div>
- <div class="body" on-keypress="onKeypress_">
+ <div class="body">
<paper-input always-float-label id="searchEngine"
label="$i18n{searchEnginesSearchEngine}"
- error-message="$i18n{searchEnginesNotValid}"
+ error-message="$i18n{notValid}"
value="{{searchEngine_}}" on-input="validate_"
autofocus>
</paper-input>
<paper-input always-float-label id="keyword"
label="$i18n{searchEnginesKeyword}"
- error-message="$i18n{searchEnginesNotValid}"
+ error-message="$i18n{notValid}"
value="{{keyword_}}" on-focus="validate_" on-input="validate_">
</paper-input>
<paper-input always-float-label id="queryUrl"
label="$i18n{searchEnginesQueryURLExplanation}"
- error-message="$i18n{searchEnginesNotValid}"
+ error-message="$i18n{notValid}"
value="{{queryUrl_}}" on-focus="validate_" on-input="validate_"
disabled$="[[model.urlLocked]]">
</paper-input>
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
index 76e1e35c4b3..bf275f9ac54 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
@@ -92,15 +92,6 @@ Polymer({
},
/**
- * @param {!KeyboardEvent} e
- * @private
- */
- onKeypress_: function(e) {
- if (e.key == 'Enter' && !this.$.actionButton.disabled)
- this.onActionButtonTap_();
- },
-
- /**
* @param {!Event} event
* @private
*/
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html
index 033e9fae423..aba01dfb53f 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html
@@ -4,7 +4,7 @@
<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../controls/extension_controlled_indicator.html">
-<link rel="import" href="../focusable_iron_list_item_behavior.html">
+<link rel="import" href="../focus_row_behavior.html">
<link rel="import" href="search_engine_dialog.html">
<link rel="import" href="search_engine_entry_css.html">
<link rel="import" href="search_engines_browser_proxy.html">
@@ -40,17 +40,13 @@
pointer-events: none;
visibility: hidden;
}
-
- :host(.no-outline) {
- outline: none;
- }
</style>
<template is="dom-if" if="[[showEditSearchEngineDialog_]]" restamp>
<settings-search-engine-dialog model="[[engine]]">
</settings-search-engine-dialog>
</template>
- <div class="list-item">
+ <div class="list-item" focus-row-container>
<div id="name-column">
<div class="favicon-image"
style="background-image: [[getIconSet_(engine.iconURL)]]"></div>
@@ -58,8 +54,9 @@
</div>
<div id="keyword-column">[[engine.keyword]]</div>
<div id="url-column" class="text-elide">[[engine.url]]</div>
- <paper-icon-button icon="cr:more-vert" tabindex$="[[tabindex]]"
- on-tap="onDotsTap_" title="$i18n{moreActions}">
+ <paper-icon-button icon="cr:more-vert" on-tap="onDotsTap_"
+ title="$i18n{moreActions}" focus-row-control
+ focus-type='cr-menu-button'>
</paper-icon-button>
<dialog is="cr-action-menu">
<button class="dropdown-item" role="option" on-tap="onMakeDefaultTap_"
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js
index 8c1dbd6f441..7fe46848124 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js
@@ -9,7 +9,7 @@
Polymer({
is: 'settings-search-engine-entry',
- behaviors: [FocusableIronListItemBehavior],
+ behaviors: [FocusRowBehavior],
properties: {
/** @type {!SearchEngine} */
@@ -106,6 +106,7 @@ Polymer({
// previous dialog's contents are cleared.
dialog.addEventListener('close', function() {
this.showEditSearchEngineDialog_ = false;
+ this.$$('paper-icon-button').focus();
}.bind(this));
}.bind(this));
},
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html
index 8fe6ca13469..04c9a28a3c5 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html
@@ -1,31 +1,34 @@
<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="../global_scroll_target_behavior.html">
<link rel="import" href="../settings_vars_css.html">
<link rel="import" href="search_engine_entry.html">
<dom-module id="settings-search-engines-list">
<template>
- <style include="cr-shared-style">
- .headers {
+ <style include="settings-shared">
+ #headers {
display: flex;
padding: 10px 0;
}
- .headers .name,
- .headers .keyword {
+ #headers .name,
+ #headers .keyword {
flex: 3;
}
- .headers .url {
+ #headers .url {
flex: 4;
}
- div#outer {
+ #outer {
@apply(--settings-list-frame-padding);
}
+ /* TODO(dbeam): this rule results in incorrectly showing a top border for
+ * "Other Search Engines", which hides the headers while still adding a
+ * dividing line (even though there's no content above the other engines
+ * to actually divide). */
settings-search-engine-entry {
border-top: var(--settings-separator-line);
}
@@ -35,17 +38,20 @@
}
</style>
<div id="outer">
- <div class="headers" hidden$="[[hideHeaders]]">
+ <div id="headers" class="column-header" hidden$="[[hideHeaders]]">
<div class="name">$i18n{searchEnginesSearchEngine}</div>
<div class="keyword">$i18n{searchEnginesKeyword}</div>
<div class="url">$i18n{searchEnginesQueryURL}</div>
<div class="icon-placeholder"></div>
</div>
<div id="container" class="scroll-container">
- <iron-list items="[[engines]]" scroll-target="[[subpageScrollTarget]]">
+ <iron-list items="[[engines]]" scroll-target="[[scrollTarget]]"
+ class$="[[getIronListClass_(scrollTarget)]]"
+ scroll-offset="[[scrollOffset]]">
<template>
<settings-search-engine-entry engine="[[item]]"
- tabindex$="[[tabIndex]]">
+ tabindex$="[[tabIndex]]" iron-list-tab-index="[[tabIndex]]"
+ last-focused="{{lastFocused_}}">
</settings-search-engine-entry>
</template>
</iron-list>
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.js b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.js
index 83801f706d7..41346884591 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.js
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.js
@@ -9,19 +9,34 @@
Polymer({
is: 'settings-search-engines-list',
- behaviors: [settings.GlobalScrollTargetBehavior],
-
properties: {
/** @type {!Array<!SearchEngine>} */
engines: Array,
- /** @override */
- subpageRoute: {
- type: Object,
- value: settings.Route.SEARCH_ENGINES,
- },
-
/** Whether column headers should be displayed */
hideHeaders: Boolean,
+
+ /**
+ * The scroll target that this list should use.
+ * @type {?HTMLElement}
+ */
+ scrollTarget: {
+ type: Element,
+ value: null, // Required to populate class.
+ },
+
+ /** Used to fix scrolling glitch when list is not top most element. */
+ scrollOffset: Number,
+
+ /** @private {Object}*/
+ lastFocused_: Object,
+ },
+
+ /**
+ * Fix height of list if no scrollTarget is present.
+ * @return {string}
+ */
+ getIronListClass_: function() {
+ return this.scrollTarget ? '' : 'fixed-height-list';
},
});
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.html b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
index e4c8dcba009..4cf645c01cf 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.html
@@ -7,6 +7,7 @@
<link rel="import" href="search_engine_dialog.html">
<link rel="import" href="search_engines_list.html">
<link rel="import" href="omnibox_extension_entry.html">
+<link rel="import" href="../global_scroll_target_behavior.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="settings-search-engines-page">
@@ -40,14 +41,15 @@
<div id="noOtherEngines" hidden="[[otherEngines.length]]">
$i18n{searchEnginesNoOtherEngines}
</div>
- <settings-search-engines-list engines="[[otherEngines]]" hide-headers>
+ <settings-search-engines-list id="otherEngines" engines="[[otherEngines]]"
+ hide-headers scroll-target="[[subpageScrollTarget]]">
</settings-search-engines-list>
<template is="dom-if" if="[[showExtensionsList_]]">
<div class="settings-box first">
<h2>$i18n{searchEnginesExtension}</h2>
</div>
- <iron-list id="extensions" class="extension-engines" selectable
- items="[[extensions]]">
+ <iron-list id="extensions" class="extension-engines fixed-height-list"
+ selectable items="[[extensions]]">
<template>
<settings-omnibox-extension-entry engine="[[item]]"
tabindex$="[[tabIndex]]">
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.js b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.js
index a9379bfc6f1..51008d2ba95 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.js
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.js
@@ -9,7 +9,7 @@
Polymer({
is: 'settings-search-engines-page',
- behaviors: [WebUIListenerBehavior],
+ behaviors: [settings.GlobalScrollTargetBehavior, WebUIListenerBehavior],
properties: {
/** @type {!Array<!SearchEngine>} */
@@ -30,6 +30,15 @@ Polymer({
value: function() { return []; }
},
+ /**
+ * Needed by GlobalScrollTargetBehavior.
+ * @override
+ */
+ subpageRoute: {
+ type: Object,
+ value: settings.Route.SEARCH_ENGINES,
+ },
+
/** @private {boolean} */
showAddSearchEngineDialog_: Boolean,
@@ -50,6 +59,11 @@ Polymer({
getSearchEnginesList().then(this.enginesChanged_.bind(this));
this.addWebUIListener(
'search-engines-changed', this.enginesChanged_.bind(this));
+
+ // Sets offset in iron-list that uses the page as a scrollTarget.
+ Polymer.RenderStatus.afterNextRender(this, function() {
+ this.$.otherEngines.scrollOffset = this.$.otherEngines.offsetTop;
+ });
},
/** @private */
@@ -82,6 +96,7 @@ Polymer({
// previous dialog's contents are cleared.
dialog.addEventListener('close', function() {
this.showAddSearchEngineDialog_ = false;
+ this.$.addSearchEngine.focus();
}.bind(this));
}.bind(this));
},
diff --git a/chromium/chrome/browser/resources/settings/search_page/search_page.html b/chromium/chrome/browser/resources/settings/search_page/search_page.html
index 7fc9c1a194d..853f73bd18b 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.html
@@ -1,3 +1,4 @@
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/html/polymer.html">
@@ -33,32 +34,42 @@
-webkit-margin-start: var(--settings-indent-width);
}
</style>
- <settings-animated-pages id="pages" section="search">
+ <settings-animated-pages id="pages" section="search"
+ focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<!-- Omnibox search engine -->
<div class="settings-box first block">
<div id="search-wrapper">
- <p class="start">$i18nRaw{searchExplanation}</p>
+ <p id="searchExplanation" class="start">
+ $i18nRaw{searchExplanation}
+ </p>
+ <template is="dom-if" if="[[isDefaultSearchControlledByPolicy_(
+ prefs.default_search_provider_data.template_url_data)]]">
+ <cr-policy-pref-indicator pref="[[
+ prefs.default_search_provider_data.template_url_data]]">
+ </cr-policy-pref-indicator>
+ </template>
<div>
<select class="md-select" on-change="onChange_"
- disabled$="[[
- prefs.default_search_provider.enabled.extensionId]]">
+ aria-labelledby="searchExplanation"
+ disabled$="[[isDefaultSearchEngineEnforced_(
+ prefs.default_search_provider_data.template_url_data)]]">
<template is="dom-repeat" items="[[searchEngines_]]">
- <option selected$="[[item.default]]">[[item.name]]</option>
+ <option selected="[[item.default]]">[[item.name]]</option>
</template>
</select>
<span class="md-select-underline"></span>
</div>
</div>
<template is="dom-if"
- if="[[prefs.default_search_provider.enabled.extensionId]]">
+ if="[[prefs.default_search_provider_data.template_url_data.extensionId]]">
<extension-controlled-indicator
extension-id="[[
- prefs.default_search_provider.enabled.extensionId]]"
+ prefs.default_search_provider_data.template_url_data.extensionId]]"
extension-name="[[
- prefs.default_search_provider.enabled.controlledByName]]"
+ prefs.default_search_provider_data.template_url_data.controlledByName]]"
extension-can-be-disabled="[[
- prefs.default_search_provider.enabled.extensionCanBeDisabled]]"
+ prefs.default_search_provider_data.template_url_data.extensionCanBeDisabled]]"
on-disable-extension="onDisableExtension_">
</extension-controlled-indicator>
</template>
@@ -66,7 +77,7 @@
<template is="dom-if" if="[[googleNowAvailable_]]">
<!-- Google Now cards in the launcher -->
- <div class="settings-box continuation">
+ <div class="settings-box continuation indented">
<settings-toggle-button id="googleNowEnable" class="start"
pref="{{prefs.google_now_launcher.enabled}}"
label="$i18n{searchEnableGoogleNowLabel}">
@@ -76,7 +87,7 @@
<template is="dom-if" if="[[hotwordInfo_.allowed]]">
<!-- Hotword (OK Google) -->
- <div class="settings-box two-line continuation">
+ <div class="settings-box two-line continuation indented">
<settings-toggle-button id="hotwordSearchEnable" class="start"
pref="{{hotwordSearchEnablePref_}}"
label="$i18n{searchOkGoogleLabel}"
@@ -120,17 +131,13 @@
</template>
<!-- Manage search engines -->
- <div id="subpage-trigger" class="settings-box two-line"
+ <div id="subpage-trigger" class="settings-box"
on-tap="onManageSearchEnginesTap_" actionable>
<div class="start">
$i18n{searchEnginesManage}
- <div class="secondary" id="manageSearchEnginesSecondary">
- $i18n{searchEnginesManageDescription}
- </div>
</div>
<button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{searchEnginesManage}"
- aria-describedby="manageSearchEnginesSecondary"></button>
+ aria-label="$i18n{searchEnginesManage}"></button>
</div>
</neon-animatable>
<template is="dom-if" route-path="/searchEngines">
diff --git a/chromium/chrome/browser/resources/settings/search_page/search_page.js b/chromium/chrome/browser/resources/settings/search_page/search_page.js
index 01f0016cf2a..f817fb4d6c7 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.js
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.js
@@ -39,6 +39,9 @@ Polymer({
/** @private */
googleNowAvailable_: Boolean,
+
+ /** @type {?Map<string, string>} */
+ focusConfig_: Object,
},
/** @private {?settings.SearchEnginesBrowserProxy} */
@@ -54,16 +57,14 @@ Polymer({
// Omnibox search engine
var updateSearchEngines = function(searchEngines) {
this.set('searchEngines_', searchEngines.defaults);
+ this.requestHotwordInfoUpdate_();
}.bind(this);
this.browserProxy_.getSearchEnginesList().then(updateSearchEngines);
cr.addWebUIListener('search-engines-changed', updateSearchEngines);
- // Hotword (OK Google)
+ // Hotword (OK Google) listener
cr.addWebUIListener(
'hotword-info-update', this.hotwordInfoUpdate_.bind(this));
- this.browserProxy_.getHotwordInfo().then(function(hotwordInfo) {
- this.hotwordInfoUpdate_(hotwordInfo);
- }.bind(this));
// Google Now cards in the launcher
cr.addWebUIListener(
@@ -72,6 +73,10 @@ Polymer({
this.browserProxy_.getGoogleNowAvailability().then(function(available) {
this.googleNowAvailabilityUpdate_(available);
}.bind(this));
+
+ this.focusConfig_ = new Map();
+ this.focusConfig_.set(
+ settings.Route.SEARCH_ENGINES.path, '#subpage-trigger .subpage-arrow');
},
/** @private */
@@ -101,6 +106,13 @@ Polymer({
!!this.hotwordSearchEnablePref_.value);
},
+ /** @private */
+ requestHotwordInfoUpdate_: function() {
+ this.browserProxy_.getHotwordInfo().then(function(hotwordInfo) {
+ this.hotwordInfoUpdate_(hotwordInfo);
+ }.bind(this));
+ },
+
/**
* @param {!SearchPageHotwordInfo} hotwordInfo
* @private
@@ -165,5 +177,23 @@ Polymer({
*/
doNothing_: function(event) {
event.stopPropagation();
- }
+ },
+
+ /**
+ * @param {!chrome.settingsPrivate.PrefObject} pref
+ * @return {boolean}
+ * @private
+ */
+ isDefaultSearchControlledByPolicy_: function(pref) {
+ return pref.controlledBy == chrome.settingsPrivate.ControlledBy.USER_POLICY;
+ },
+
+ /**
+ * @param {!chrome.settingsPrivate.PrefObject} pref
+ * @return {boolean}
+ * @private
+ */
+ isDefaultSearchEngineEnforced_: function(pref) {
+ return pref.enforcement == chrome.settingsPrivate.Enforcement.ENFORCED;
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/search_settings.js b/chromium/chrome/browser/resources/settings/search_settings.js
index 78960bbf444..ad541dd43c2 100644
--- a/chromium/chrome/browser/resources/settings/search_settings.js
+++ b/chromium/chrome/browser/resources/settings/search_settings.js
@@ -2,6 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+cr.exportPath('settings');
+
+/**
+ * A data structure used by callers to combine the results of multiple search
+ * requests.
+ *
+ * @typedef {{
+ * canceled: Boolean,
+ * didFindMatches: Boolean,
+ * wasClearSearch: Boolean,
+ * }}
+ */
+settings.SearchResult;
+
cr.define('settings', function() {
/** @const {string} */
var WRAPPER_CSS_CLASS = 'search-highlight-wrapper';
@@ -30,15 +44,11 @@ cr.define('settings', function() {
var IGNORED_ELEMENTS = new Set([
'CONTENT',
'CR-EVENTS',
+ 'DIALOG',
'IMG',
'IRON-ICON',
'IRON-LIST',
'PAPER-ICON-BUTTON',
- /* TODO(dpapad): paper-item is used for dynamically populated dropdown
- * menus. Perhaps a better approach is to mark the entire dropdown menu such
- * that search algorithm can skip it as a whole instead.
- */
- 'PAPER-ITEM',
'PAPER-RIPPLE',
'PAPER-SLIDER',
'PAPER-SPINNER',
@@ -125,8 +135,7 @@ cr.define('settings', function() {
function doSearch(node) {
if (node.nodeName == 'TEMPLATE' && node.hasAttribute('route-path') &&
!node.if && !node.hasAttribute(SKIP_SEARCH_CSS_ATTRIBUTE)) {
- getSearchManager().queue_.addRenderTask(
- new RenderTask(request, node));
+ request.queue_.addRenderTask(new RenderTask(request, node));
return;
}
@@ -304,7 +313,7 @@ cr.define('settings', function() {
parent.querySelector('[route-path="' + routePath + '"]');
// Register a SearchAndHighlightTask for the part of the DOM that was
// just rendered.
- getSearchManager().queue_.addSearchAndHighlightTask(
+ this.request.queue_.addSearchAndHighlightTask(
new SearchAndHighlightTask(this.request, assert(renderedNode)));
resolve();
}.bind(this));
@@ -372,8 +381,12 @@ cr.define('settings', function() {
/**
* @constructor
+ * @param {!settings.SearchRequest} request
*/
- function TaskQueue() {
+ function TaskQueue(request) {
+ /** @private {!settings.SearchRequest} */
+ this.request_ = request;
+
/**
* @private {{
* high: !Array<!Task>,
@@ -452,18 +465,14 @@ cr.define('settings', function() {
this.running_ = true;
window.requestIdleCallback(function() {
- function startNextTask() {
- this.running_ = false;
- this.consumePending_();
- }
- if (task.request.id ==
- getSearchManager().activeRequest_.id) {
- task.exec().then(startNextTask.bind(this));
- } else {
- // Dropping this task without ever executing it, since a new search
- // has been issued since this task was queued.
- startNextTask.call(this);
+ if (!this.request_.canceled) {
+ task.exec().then(function() {
+ this.running_ = false;
+ this.consumePending_();
+ }.bind(this));
}
+ // Nothing to do otherwise. Since the request corresponding to this
+ // queue was canceled, the queue is disposed along with the request.
}.bind(this));
return;
}
@@ -472,38 +481,52 @@ cr.define('settings', function() {
/**
* @constructor
+ *
+ * @param {string} rawQuery
+ * @param {!HTMLElement} root
*/
- var SearchRequest = function(rawQuery) {
- /** @type {number} */
- this.id = SearchRequest.nextId_++;
-
+ var SearchRequest = function(rawQuery, root) {
/** @private {string} */
this.rawQuery_ = rawQuery;
+ /** @private {!HTMLElement} */
+ this.root_ = root;
+
/** @type {?RegExp} */
this.regExp = this.generateRegExp_();
/**
- * Whether this request was fully processed.
+ * Whether this request was canceled before completing.
* @type {boolean}
*/
- this.finished = false;
+ this.canceled = false;
/** @private {boolean} */
this.foundMatches_ = false;
/** @type {!PromiseResolver} */
this.resolver = new PromiseResolver();
- };
- /** @private {number} */
- SearchRequest.nextId_ = 0;
+ /** @private {!TaskQueue} */
+ this.queue_ = new TaskQueue(this);
+ this.queue_.onEmpty(function() {
+ this.resolver.resolve(this);
+ }.bind(this));
+ };
/** @private {!RegExp} */
SearchRequest.SANITIZE_REGEX_ = /[-[\]{}()*+?.,\\^$|#\s]/g;
SearchRequest.prototype = {
/**
+ * Fires this search request.
+ */
+ start: function() {
+ this.queue_.addTopLevelSearchTask(
+ new TopLevelSearchTask(this, this.root_));
+ },
+
+ /**
* @return {?RegExp}
* @private
*/
@@ -561,37 +584,36 @@ cr.define('settings', function() {
* @implements {SearchManager}
*/
var SearchManagerImpl = function() {
- /** @private {?settings.SearchRequest} */
- this.activeRequest_ = null;
+ /** @private {!Set<!settings.SearchRequest>} */
+ this.activeRequests_ = new Set();
- /** @private {!TaskQueue} */
- this.queue_ = new TaskQueue();
- this.queue_.onEmpty(function() {
- this.activeRequest_.finished = true;
- this.activeRequest_.resolver.resolve(this.activeRequest_);
- this.activeRequest_ = null;
- }.bind(this));
+ /** @private {?string} */
+ this.lastSearchedText_ = null;
};
cr.addSingletonGetter(SearchManagerImpl);
SearchManagerImpl.prototype = {
/** @override */
search: function(text, page) {
- // Creating a new request only if the |text| changed.
- if (!this.activeRequest_ || !this.activeRequest_.isSame(text)) {
- // Resolving previous search request without marking it as
- // 'finished', if any, and dropping all pending tasks.
- this.queue_.reset();
- if (this.activeRequest_)
- this.activeRequest_.resolver.resolve(this.activeRequest_);
-
- this.activeRequest_ = new SearchRequest(text);
+ // Cancel any pending requests if a request with different text is
+ // submitted.
+ if (text != this.lastSearchedText_) {
+ this.activeRequests_.forEach(function(request) {
+ request.canceled = true;
+ request.resolver.resolve(request);
+ });
+ this.activeRequests_.clear();
}
- this.queue_.addTopLevelSearchTask(
- new TopLevelSearchTask(this.activeRequest_, page));
-
- return this.activeRequest_.resolver.promise;
+ this.lastSearchedText_ = text;
+ var request = new SearchRequest(text, page);
+ this.activeRequests_.add(request);
+ request.start();
+ return request.resolver.promise.then(function() {
+ // Stop tracking requests that finished.
+ this.activeRequests_.delete(request);
+ return request;
+ }.bind(this));
},
};
diff --git a/chromium/chrome/browser/resources/settings/settings.html b/chromium/chrome/browser/resources/settings/settings.html
index 191d31446a2..f56ed01b94b 100644
--- a/chromium/chrome/browser/resources/settings/settings.html
+++ b/chromium/chrome/browser/resources/settings/settings.html
@@ -1,25 +1,27 @@
<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading">
<head>
<meta charset="utf-8">
<title>$i18n{settings}</title>
<if expr="not use_vulcanize">
<base href="chrome://$i18n{hostname}">
</if>
- <link rel="import" href="chrome://resources/html/polymer.html">
- <link rel="import" href="settings_ui/settings_ui.html">
- <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="import" href="chrome://resources/html/i18n_template.html">
- <!-- Do not add any <link rel="..."> elements below here. Imports outside of
- <head> are disallowed by HTML5 and cause undefined behavior that
- confuses Polymer's lifecycle methods: crbug.com/638074. -->
<style>
html {
+ background-color: #f1f1f1;
overflow: hidden;
}
+
+ .loading {
+ /* --google-blue-700 in disguise. Replaced when settings-ui loads. */
+ border-top: 56px solid rgb(51, 103, 214);
+ }
</style>
</head>
<body>
<settings-ui></settings-ui>
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+ <link rel="import" href="chrome://resources/html/polymer.html">
+ <link rel="import" href="settings_ui/settings_ui.html">
</body>
</html>
diff --git a/chromium/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp
index 2efdb05237c..bb2d24bffb4 100644
--- a/chromium/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/settings_main/compiled_resources2.gyp
@@ -6,12 +6,14 @@
{
'target_name': 'settings_main',
'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp:iron-a11y-announcer-extracted',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'../compiled_resources2.gyp:route',
'../compiled_resources2.gyp:search_settings',
'../about_page/compiled_resources2.gyp:about_page',
'../basic_page/compiled_resources2.gyp:basic_page',
'../settings_page/compiled_resources2.gyp:main_page_behavior',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'../settings_page/compiled_resources2.gyp:settings_page_visibility',
'../settings_ui/compiled_resources2.gyp:settings_ui_types',
],
diff --git a/chromium/chrome/browser/resources/settings/settings_main/settings_main.html b/chromium/chrome/browser/resources/settings/settings_main/settings_main.html
index 76c372399c9..e20499dee98 100644
--- a/chromium/chrome/browser/resources/settings/settings_main/settings_main.html
+++ b/chromium/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -1,10 +1,12 @@
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/promise_resolver.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="../about_page/about_page.html">
<link rel="import" href="../basic_page/basic_page.html">
+<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../route.html">
<link rel="import" href="../settings_vars_css.html">
diff --git a/chromium/chrome/browser/resources/settings/settings_main/settings_main.js b/chromium/chrome/browser/resources/settings/settings_main/settings_main.js
index 22b4bd86fb2..49397d85763 100644
--- a/chromium/chrome/browser/resources/settings/settings_main/settings_main.js
+++ b/chromium/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -85,6 +85,13 @@ Polymer({
/** @override */
attached: function() {
this.listen(this, 'freeze-scroll', 'onFreezeScroll_');
+ this.listen(this, 'lazy-loaded', 'onLazyLoaded_');
+ },
+
+ /** @private */
+ onLazyLoaded_: function() {
+ Polymer.dom.flush();
+ this.updateOverscrollForPage_();
},
/** @override */
@@ -254,19 +261,28 @@ Polymer({
setTimeout(function() {
var whenSearchDone =
assert(this.getPage_(settings.Route.BASIC)).searchContents(query);
- whenSearchDone.then(function(request) {
+ whenSearchDone.then(function(result) {
resolve();
- if (!request.finished) {
+ if (result.canceled) {
// Nothing to do here. A previous search request was canceled
- // because a new search request was issued before the first one
- // completed.
+ // because a new search request was issued with a different query
+ // before the previous completed.
return;
}
this.toolbarSpinnerActive = false;
- this.inSearchMode_ = !request.isSame('');
+ this.inSearchMode_ = !result.wasClearSearch;
this.showNoResultsFound_ =
- this.inSearchMode_ && !request.didFindMatches();
+ this.inSearchMode_ && result.didFindMatches;
+
+ if (this.inSearchMode_) {
+ Polymer.IronA11yAnnouncer.requestAvailability();
+ this.fire('iron-announce', {
+ text: this.showNoResultsFound_ ?
+ loadTimeData.getString('searchNoResults') :
+ loadTimeData.getStringF('searchResults', query)
+ });
+ }
}.bind(this));
}.bind(this), 0);
}.bind(this));
diff --git a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
index 849f62e0f5e..cc6fb7cedb5 100644
--- a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -92,7 +92,7 @@
</a>
</if>
<a id="people" href="/people" hidden="[[!pageVisibility.people]]">
- <iron-icon icon="settings:people"></iron-icon>
+ <iron-icon icon="cr:person"></iron-icon>
$i18n{peoplePageTitle}
</a>
<a href="/appearance" hidden="[[!pageVisibility.appearance]]">
@@ -133,8 +133,7 @@
</iron-icon></paper-button>
<iron-collapse id="advancedSubmenu" opened="[[advancedOpened]]"
hidden="[[!pageVisibility.advancedSettings]]">
- <iron-selector id="subMenu" selectable="a" attr-for-selected="href"
- on-iron-activate="onSelectorActivate_">
+ <iron-selector id="subMenu" selectable="a" attr-for-selected="href">
<if expr="chromeos">
<a href="/dateTime">
<iron-icon icon="settings:access-time"></iron-icon>
diff --git a/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.js b/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.js
index 8fdf5f7e6e6..3886816a911 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.js
+++ b/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.js
@@ -11,6 +11,16 @@
var MainPageBehaviorImpl = {
properties: {
/**
+ * Help CSS to alter style during the horizontal swipe animation.
+ * Note that this is unrelated to the |currentAnimation_| (which refers to
+ * the vertical exapand animation).
+ */
+ isSubpageAnimating: {
+ reflectToAttribute: true,
+ type: Boolean,
+ },
+
+ /**
* Whether a search operation is in progress or previous search results are
* being displayed.
* @private {boolean}
@@ -25,12 +35,24 @@ var MainPageBehaviorImpl = {
/** @type {?HTMLElement} The scrolling container. */
scroller: null,
+ listeners: {
+ 'neon-animation-finish': 'onNeonAnimationFinish_'
+ },
+
/** @override */
attached: function() {
- if (this.domHost && this.domHost.parentNode.tagName == 'PAPER-HEADER-PANEL')
- this.scroller = this.domHost.parentNode.scroller;
- else
- this.scroller = document.body; // Used in unit tests.
+ this.scroller = this.domHost ? this.domHost.parentNode : document.body;
+ },
+
+ /**
+ * Remove the is-animating attribute once the animation is complete.
+ * This may catch animations finishing more often than needed, which is not
+ * known to cause any issues (e.g. when animating from a shallower page to a
+ * deeper page; or when transitioning to the main page).
+ * @private
+ */
+ onNeonAnimationFinish_: function() {
+ this.isSubpageAnimating = false;
},
/**
@@ -42,20 +64,33 @@ var MainPageBehaviorImpl = {
!!oldRoute && !!oldRoute.parent && !!oldRoute.section &&
oldRoute.parent.section != oldRoute.section;
- // Always scroll to the top if navigating from a section to the root route
- // or when navigating to the About page.
- if (this.scroller &&
- ((oldRouteWasSection && newRoute == settings.Route.BASIC) ||
- newRoute == settings.Route.ABOUT)) {
- this.scroller.scrollTop = 0;
- return;
+ if (this.scroller) {
+ // When navigating from a section to the root route, we just need to
+ // scroll to the top, and can early exit afterwards.
+ if (oldRouteWasSection && newRoute == settings.Route.BASIC) {
+ this.scroller.scrollTop = 0;
+ return;
+ }
+
+ // When navigating to the About page, we need to scroll to the top, and
+ // still do the rest of section management.
+ if (newRoute == settings.Route.ABOUT)
+ this.scroller.scrollTop = 0;
}
// Scroll to the section except for back/forward. Also scroll for any
// in-page back/forward navigations (from a section or the root page).
- var scrollToSection =
- !settings.lastRouteChangeWasPopstate() || oldRouteWasSection ||
- oldRoute == settings.Route.BASIC;
+ // Also always scroll when coming from either the About or root page.
+ var scrollToSection = !settings.lastRouteChangeWasPopstate() ||
+ oldRouteWasSection || oldRoute == settings.Route.BASIC ||
+ oldRoute == settings.Route.ABOUT;
+
+ // TODO(dschuyler): This doesn't set the flag in the case of going to or
+ // from the main page. It seems sensible to set the flag in those cases,
+ // unfortunately bug 708465 happens. Figure out why that is and then set
+ // this flag more broadly.
+ if (oldRoute && oldRoute.isSubpage() && newRoute.isSubpage())
+ this.isSubpageAnimating = true;
// For previously uncreated pages (including on first load), allow the page
// to render before scrolling to or expanding the section.
@@ -116,6 +151,14 @@ var MainPageBehaviorImpl = {
promise = this.expandSection_(currentSection);
else if (scrollToSection)
currentSection.scrollIntoView();
+ } else if (
+ this.tagName == 'SETTINGS-BASIC-PAGE' &&
+ settings.Route.ADVANCED.contains(currentRoute) &&
+ // Need to exclude routes that correspond to 'non-sectioned' children of
+ // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly.
+ !currentRoute.isNavigableDialog) {
+ assert(currentRoute.section);
+ promise = this.$$('#advancedPageTemplate').get();
}
// When this animation ends, another may be necessary. Call this function
@@ -256,10 +299,12 @@ var MainPageBehaviorImpl = {
this.getSection(settings.getCurrentRoute().section);
// Scroll to the new section or the original position.
- if (newSection && !settings.lastRouteChangeWasPopstate())
+ if (newSection && !settings.lastRouteChangeWasPopstate() &&
+ !settings.getCurrentRoute().isSubpage()) {
newSection.scrollIntoView();
- else
+ } else {
this.scroller.scrollTop = this.origScrollTop_;
+ }
this.currentAnimation_ = section.animateCollapse(
/** @type {!HTMLElement} */(this.scroller));
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
index 8340f045b3d..71838bc9e0a 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
@@ -1,8 +1,6 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-out-animation.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-left-animation.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-right-animation.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-left-animation.html">
@@ -10,6 +8,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animated-pages.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.html">
+<link rel="import" href="../animation/fade_animations.html">
<link rel="import" href="../route.html">
<dom-module id="settings-animated-pages">
@@ -27,7 +26,8 @@
position: static;
}
</style>
- <neon-animated-pages id="animatedPages" attr-for-selected="route-path">
+ <neon-animated-pages id="animatedPages" attr-for-selected="route-path"
+ on-iron-select="onIronSelect_">
<content select="*"></content>
</neon-animated-pages>
</template>
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
index 97d51cd7eb4..cdcee5c765f 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
@@ -13,6 +13,7 @@
* <!-- Insert your section controls here -->
* </settings-animated-pages>
*/
+
Polymer({
is: 'settings-animated-pages',
@@ -26,11 +27,23 @@ Polymer({
*
* The section name must match the name specified in route.js.
*/
- section: {
- type: String,
- },
+ section: String,
+
+ /**
+ * A Map specifying which element should be focused when exiting a subpage.
+ * The key of the map holds a settings.Route path, and the value holds a
+ * query selector that identifies the desired element.
+ * @type {?Map<string, string>}
+ */
+ focusConfig: Object,
},
+ /**
+ * The last "previous" route reported by the router.
+ * @private {?settings.Route}
+ */
+ previousRoute_: null,
+
/** @override */
created: function() {
// Observe the light DOM so we know when it's ready.
@@ -39,6 +52,41 @@ Polymer({
},
/**
+ * @param {!Event} e
+ * @private
+ */
+ onIronSelect_: function(e) {
+ if (!this.focusConfig || !this.previousRoute_)
+ return;
+
+ // Don't attempt to focus any anchor element, unless last navigation was a
+ // 'pop' (backwards) navigation.
+ if (!settings.lastRouteChangeWasPopstate())
+ return;
+
+ // Only handle iron-select events from neon-animatable elements and the
+ // given whitelist of settings-subpage instances.
+ if (!e.detail.item.matches(
+ 'neon-animatable, ' +
+ 'settings-subpage#site-settings, ' +
+ 'settings-subpage[route-path=\"' +
+ settings.Route.SITE_SETTINGS_COOKIES.path + '\"]')) {
+ return;
+ }
+
+ var selector = this.focusConfig.get(this.previousRoute_.path);
+ if (selector) {
+ // neon-animatable has "display: none" until the animation finishes, so
+ // calling focus() on any of its children has no effect until
+ // "display: none" is removed. Therefore can't call focus() from within
+ // the currentRouteChanged callback. Using 'iron-select' listener which
+ // fires after the animation has finished allows focus() to work as
+ // expected.
+ this.querySelector(selector).focus();
+ }
+ },
+
+ /**
* Called initially once the effective children are ready.
* @private
*/
@@ -66,11 +114,13 @@ Polymer({
/** @protected */
currentRouteChanged: function(newRoute, oldRoute) {
+ this.previousRoute_ = oldRoute;
+
if (newRoute.section == this.section && newRoute.isSubpage()) {
this.switchToSubpage_(newRoute, oldRoute);
} else {
- this.$.animatedPages.exitAnimation = 'fade-out-animation';
- this.$.animatedPages.entryAnimation = 'fade-in-animation';
+ this.$.animatedPages.exitAnimation = 'settings-fade-out-animation';
+ this.$.animatedPages.entryAnimation = 'settings-fade-in-animation';
this.$.animatedPages.selected = 'default';
}
},
@@ -102,8 +152,8 @@ Polymer({
this.$.animatedPages.entryAnimation = 'slide-from-left-animation';
} else {
// The old route is not a subpage or is at the same level, so just fade.
- this.$.animatedPages.exitAnimation = 'fade-out-animation';
- this.$.animatedPages.entryAnimation = 'fade-in-animation';
+ this.$.animatedPages.exitAnimation = 'settings-fade-out-animation';
+ this.$.animatedPages.entryAnimation = 'settings-fade-in-animation';
if (!oldRoute.isSubpage()) {
// Set the height the expand animation should start at before
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
index 73789e20352..aedba645e4a 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
@@ -14,20 +14,16 @@
<template>
<style include="settings-shared">
:host {
- --iron-icon-fill-color: var(--settings-nav-grey);
display: block;
padding-bottom: 60px;
}
- .settings-box.first {
+ #headerLine {
min-height: 40px;
+ padding-bottom: 24px;
padding-top: 8px;
}
- .settings-box.first > h1 {
- -webkit-margin-start: 4px;
- }
-
#learnMore {
@apply(--cr-paper-icon-button-margin);
align-items: center;
@@ -40,8 +36,8 @@
paper-icon-button {
/* Centers the ripple on the icon with appropriate margin on right. */
- -webkit-margin-end: 8px;
- -webkit-margin-start: -8px;
+ -webkit-margin-end: 10px;
+ -webkit-margin-start: -10px;
}
paper-spinner {
@@ -60,7 +56,7 @@
-webkit-margin-start: 16px;
}
</style>
- <div class="settings-box first">
+ <div class="settings-box first" id="headerLine">
<paper-icon-button icon="settings:arrow-back" on-tap="onTapBack_"
aria-label="$i18n{back}">
</paper-icon-button>
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
index 2f84151f48d..c3aacac5b94 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
@@ -24,7 +24,7 @@
--paper-input-suffix: {
/* Required to align the icon in |clearSearch| vertically. */
line-height: 0;
- }
+ };
}
paper-icon-button {
@@ -37,11 +37,13 @@
#searchIcon {
height: 16px;
padding: 4px;
+ vertical-align: middle;
width: 16px;
}
paper-input-container {
display: inline-block;
+ vertical-align: middle;
width: 160px; /* Special width for search input. */
}
@@ -49,17 +51,9 @@
-webkit-appearance: none;
}
- #prompt,
#searchInput {
font-size: 92.3076923%; /* To 12px from 13px. */
- }
-
- #prompt {
- color: var(--paper-grey-600);
- }
-
- :host([has-search-text]) #prompt {
- visibility: hidden;
+ min-height: 24px;
}
#searchInput {
@@ -73,10 +67,9 @@
</style>
<iron-icon id="searchIcon" icon="cr:search"></iron-icon>
<paper-input-container no-label-float>
- <label id="prompt">[[label]]</label>
<input id="searchInput" type="search" on-search="onSearchTermSearch"
- on-input="onSearchTermInput" aria-labelledby="prompt" incremental>
- </input>
+ on-input="onSearchTermInput" aria-labelledby="prompt" incremental
+ autofocus$="[[autofocus]]" placeholder="[[label]]">
<paper-icon-button suffix icon="cr:cancel" id="clearSearch"
on-tap="onTapClear_" title="[[clearLabel]]"
hidden$="[[!hasSearchText]]">
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.js b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.js
index 0f2d4e22ccb..fd4af0675b9 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.js
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.js
@@ -12,6 +12,10 @@ Polymer({
behaviors: [CrSearchFieldBehavior],
+ properties: {
+ autofocus: Boolean,
+ },
+
/** @return {!HTMLInputElement} */
getSearchInput: function() {
return this.$.searchInput;
diff --git a/chromium/chrome/browser/resources/settings/settings_page_css.html b/chromium/chrome/browser/resources/settings/settings_page_css.html
index 6aa289ef187..e26e9d7e995 100644
--- a/chromium/chrome/browser/resources/settings/settings_page_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_page_css.html
@@ -15,15 +15,13 @@
width: 96%;
}
- :host(.showing-subpage) {
+ :host(.showing-subpage),
+ :host(.showing-subpage) #basicPage,
+ :host(.showing-subpage) #advancedPage {
/* The subpage container should extend to the bottom of the page. */
height: 100%;
}
- :host > div {
- height: inherit;
- }
-
:host > div > :not(.expanded) {
/* The margin and padding here are doing two things: make the total
* separation 24px; and make scrollIntoView align the section header
diff --git a/chromium/chrome/browser/resources/settings/settings_resources.grd b/chromium/chrome/browser/resources/settings/settings_resources.grd
index 5760518c6a2..e9a963543d4 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources.grd
@@ -58,6 +58,12 @@
<structure name="IDR_SETTINGS_DETAILED_BUILD_INFO_HTML"
file="about_page/detailed_build_info.html"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_UPDATE_WARNING_DIALOG_HTML"
+ file="about_page/update_warning_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_UPDATE_WARNING_DIALOG_JS"
+ file="about_page/update_warning_dialog.js"
+ type="chrome_html" />
</if>
<structure name="IDR_SETTINGS_ADD_SITE_DIALOG_HTML"
file="site_settings/add_site_dialog.html"
@@ -90,11 +96,11 @@
<structure name="IDR_SETTINGS_ANIMATION_ANIMATION_JS"
file="animation/animation.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_ANIMATION_ANIMATION_GROUP_HTML"
- file="animation/animation_group.html"
+ <structure name="IDR_SETTINGS_ANIMATION_FADE_ANIMATIONS_HTML"
+ file="animation/fade_animations.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_ANIMATION_ANIMATION_GROUP_JS"
- file="animation/animation_group.js"
+ <structure name="IDR_SETTINGS_ANIMATION_FADE_ANIMATIONS_JS"
+ file="animation/fade_animations.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_HTML"
file="settings_page/settings_animated_pages.html"
@@ -125,6 +131,12 @@
file="appearance_page/appearance_page.js"
type="chrome_html"
preprocess="true" />
+ <structure name="IDR_SETTINGS_APPEARANCE_HOME_URL_INPUT_HTML"
+ file="appearance_page/home_url_input.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_APPEARANCE_HOME_URL_INPUT_JS"
+ file="appearance_page/home_url_input.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_BASIC_PAGE_JS"
file="basic_page/basic_page.js"
preprocess="true"
@@ -271,11 +283,11 @@
<structure name="IDR_SETTINGS_GLOBAL_SCROLL_TARGET_BEHAVIOR_JS"
file="global_scroll_target_behavior.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_FOCUSABLE_IRON_LIST_ITEM_BEHAVIOR_HTML"
- file="focusable_iron_list_item_behavior.html"
+ <structure name="IDR_SETTINGS_FOCUS_ROW_BEHAVIOR_HTML"
+ file="focus_row_behavior.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_FOCUSABLE_IRON_LIST_ITEM_BEHAVIOR_JS"
- file="focusable_iron_list_item_behavior.js"
+ <structure name="IDR_SETTINGS_FOCUS_ROW_BEHAVIOR_JS"
+ file="focus_row_behavior.js"
type="chrome_html" />
<if expr="use_nss_certs">
<structure name="IDR_SETTINGS_CERTIFICATE_MANAGER_PAGE_HTML"
@@ -401,12 +413,6 @@
<structure name="IDR_SETTINGS_CONTROLS_DROPDOWN_MENU_JS"
file="controls/settings_dropdown_menu.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CONTROLS_INPUT_HTML"
- file="controls/settings_input.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CONTROLS_INPUT_JS"
- file="controls/settings_input.js"
- type="chrome_html" />
<structure name="IDR_SETTINGS_CONTROLS_PREF_CONTROL_BEHAVIOR_HTML"
file="controls/pref_control_behavior.html"
type="chrome_html" />
@@ -419,11 +425,17 @@
<structure name="IDR_SETTINGS_CONTROLS_RADIO_GROUP_JS"
file="controls/settings_radio_group.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CONTROLS_SETTINGS_IDLE_RENDER_HTML"
- file="controls/settings_idle_render.html"
+ <structure name="IDR_SETTINGS_CONTROLS_SETTINGS_IDLE_LOAD_HTML"
+ file="controls/settings_idle_load.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_CONTROLS_SETTINGS_IDLE_LOAD_JS"
+ file="controls/settings_idle_load.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CONTROLS_SETTINGS_IDLE_RENDER_JS"
- file="controls/settings_idle_render.js"
+ <structure name="IDR_SETTINGS_CONTROLS_SLIDER_HTML"
+ file="controls/settings_slider.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_CONTROLS_SLIDER_JS"
+ file="controls/settings_slider.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_CONTROLS_TOGGLE_BUTTON_HTML"
file="controls/settings_toggle_button.html"
@@ -990,6 +1002,10 @@
preprocess="true"
file="settings.html"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_LAZY_LOAD_HTML"
+ preprocess="true"
+ file="lazy_load.html"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_USB_DEVICES_HTML"
file="site_settings/usb_devices.html"
type="chrome_html" />
@@ -1015,6 +1031,12 @@
<structure name="IDR_SETTINGS_ANDROID_APPS_PAGE_JS"
file="android_apps_page/android_apps_page.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_ANDROID_APPS_SUBPAGE_HTML"
+ file="android_apps_page/android_apps_subpage.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ANDROID_APPS_SUBPAGE_JS"
+ file="android_apps_page/android_apps_subpage.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_ANDROID_APPS_BROWSER_PROXY_JS"
file="android_apps_page/android_apps_browser_proxy.js"
type="chrome_html"
@@ -1142,6 +1164,12 @@
<structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_JS"
file="internet_page/network_summary_item.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_TETHER_CONNECTION_DIALOG_HTML"
+ file="internet_page/tether_connection_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_TETHER_CONNECTION_DIALOG_JS"
+ file="internet_page/tether_connection_dialog.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_CAMERA_HTML"
file="people_page/camera.html"
type="chrome_html"
diff --git a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
index 41872001dca..fcd5540c552 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
@@ -14,6 +14,8 @@
<includes>
<include name="IDR_MD_SETTINGS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_MD_SETTINGS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MD_SETTINGS_LAZY_LOAD_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MD_SETTINGS_LAZY_LOAD_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
</includes>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/settings/settings_shared_css.html b/chromium/chrome/browser/resources/settings/settings_shared_css.html
index e1a9d4da6d7..aa9e0ae1ace 100644
--- a/chromium/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_shared_css.html
@@ -28,8 +28,8 @@
font-size: inherit;
font-weight: 500;
margin: 0;
- padding-top: 24px;
padding-bottom: 12px;
+ padding-top: 24px;
}
iron-icon[icon='cr:check'],
@@ -38,9 +38,8 @@
}
paper-button {
- height: 32px;
+ height: 36px;
margin: 0;
- border-radius: 4px;
}
paper-button[toggles][active] {
@@ -86,6 +85,15 @@
};
}
+ .primary-toggle {
+ color: var(--paper-grey-600);
+ font-weight: 500;
+ }
+
+ .primary-toggle[checked] {
+ color: var(--google-blue-500);
+ }
+
/* See notes in .primary-button. */
.secondary-button {
--paper-button: {
@@ -118,15 +126,19 @@
paper-checkbox {
--paper-checkbox-checked-color: var(--google-blue-500);
- --paper-checkbox-label-spacing: var(--checkbox-spacing);
+ --paper-checkbox-label-spacing: var(--settings-control-spacing);
--paper-checkbox-size: var(--checkbox-size);
--paper-checkbox-unchecked-color: var(--paper-grey-600);
-webkit-margin-start: var(--checkbox-margin-start);
}
+ controlled-radio-button,
paper-radio-button {
--paper-radio-button-checked-color: var(--google-blue-500);
- --paper-radio-button-label-spacing: 18px;
+ --paper-radio-button-label-spacing: 22px;
+ --paper-radio-button-radio-container: {
+ flex-shrink: 0;
+ };
--paper-radio-button-unchecked-color: var(--paper-grey-600);
-webkit-margin-start: 2px;
align-items: center;
@@ -170,7 +182,7 @@
}
/* A list-item is intended to be contained within a list-frame. The list
- * frame will setup the initial start margin. */
+ * frame will set up the initial start margin. */
.list-item {
align-items: center;
display: flex;
@@ -208,11 +220,17 @@
/* This button has no ink ripple. */
.list-button[is='action-link'] {
- min-height: inherit;
- display: flex;
align-items: center;
+ display: flex;
flex: 1;
font-weight: 500;
+ min-height: inherit;
+ }
+
+ .fixed-height-list {
+ max-height: calc((var(--settings-row-min-height) +
+ var(--settings-separator-height)) * 6);
+ overflow-y: auto;
}
/* A row with two lines of text. Often the lower line will be .secondary.
@@ -295,6 +313,12 @@
flex: auto;
}
+ .no-outline,
+ [scrollable] .no-outline {
+ background: none;
+ outline: none;
+ }
+
/* The secondary-action wraps a clickable sub-area of a .settings-box.
* An example is the |sign out| button on the People settings.
* Here is an example with and without a secondary action box:
@@ -323,7 +347,7 @@
-webkit-margin-start: calc(
var(--checkbox-margin-start) +
var(--checkbox-size) +
- var(--checkbox-spacing));
+ var(--settings-control-spacing));
}
.favicon-image {
@@ -367,6 +391,11 @@
top: auto;
transform: rotate(-135deg);
}
+
+ .column-header {
+ color: var(--paper-grey-600);
+ font-weight: 500;
+ }
</style>
</template>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html
index fc366132325..ac2d13300b1 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html
+++ b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -3,7 +3,7 @@
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="../direction_delegate.html">
<link rel="import" href="../global_scroll_target_behavior.html">
<link rel="import" href="../i18n_setup.html">
@@ -24,30 +24,16 @@
<style include="settings-shared">
:host {
@apply(--layout-fit);
- --paper-header-panel-waterfall-container: {
- overflow-x: auto; /* Undo paper-header-panel default of 'hidden'. */
- overflow-y: overlay;
- };
-webkit-user-select: none;
- background-color: var(--settings-background-color);
- color: var(--paper-grey-800);
+ color: var(--paper-grey-900);
display: flex;
flex-direction: column;
line-height: 154%; /* Apply 20px line-height to all texts by default. */
overflow: hidden; /* Prevent double scroll bar bugs. */
}
- paper-header-panel {
- flex: 1;
- }
-
- .paper-header {
- -webkit-padding-start: 24px;
- align-items: center;
- border-bottom: var(--settings-separator-line);
- display: flex;
- font-size: 123.08%; /* go to 16px from 13px */
- min-height: 56px;
+ .drawer-header {
+ outline: none;
}
.last {
@@ -64,11 +50,36 @@
@apply(--layout-center);
--cr-toolbar-field-width: var(--settings-card-max-width);
--iron-icon-fill-color: white;
- background-color: var(--settings-title-bar-background-color);
+ background-color: var(--google-blue-700);
color: white;
min-height: 56px;
z-index: 2;
}
+
+ #container {
+ flex: 1;
+ overflow: overlay;
+ position: relative;
+ }
+
+ #dropShadow {
+ /* TODO(dpapad): This box-shadow is repeated in Settings, History and
+ Downloads. Define a CSS variable instead and re-use. */
+ box-shadow: inset 0 5px 6px -3px rgba(0, 0, 0, 0.4);
+ height: 6px;
+ left: 0;
+ opacity: 0;
+ pointer-events: none;
+ position: absolute;
+ right: 0;
+ top: 56px;
+ transition: opacity 500ms;
+ z-index: 1;
+ }
+
+ #dropShadow.has-shadow {
+ opacity: 1;
+ }
</style>
<settings-prefs id="prefs" prefs="{{prefs}}"></settings-prefs>
<cr-toolbar page-name="$i18n{settings}"
@@ -78,10 +89,11 @@
spinner-active="[[toolbarSpinnerActive_]]"
menu-label="$i18n{menuButtonLabel}"
on-search-changed="onSearchChanged_"
+ role="none"
show-menu>
</cr-toolbar>
- <dialog id="drawer" is="cr-drawer">
- <div class="drawer-header">$i18n{settings}</div>
+ <dialog id="drawer" is="cr-drawer" on-close="onMenuClosed_">
+ <div class="drawer-header" tabindex="-1">$i18n{settings}</div>
<div class="drawer-content">
<template is="dom-if" id="drawerTemplate">
<settings-menu page-visibility="[[pageVisibility_]]"
@@ -92,14 +104,17 @@
</template>
</div>
</dialog>
- <paper-header-panel id="headerPanel" mode="waterfall">
+ <div id="dropShadow"></div>
+ <div id="container" class="no-outline">
+ <!-- Used by IntersectionObserver, has a 0px height intentionally -->
+ <div id="intersectionProbe"></div>
<settings-main id="main" prefs="{{prefs}}"
toolbar-spinner-active="{{toolbarSpinnerActive_}}"
page-visibility="[[pageVisibility_]]"
show-android-apps="[[showAndroidApps_]]"
advanced-toggle-expanded="{{advancedOpened_}}">
</settings-main>
- </paper-header-panel>
+ </div>
</template>
<script src="settings_ui.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
index e6fbee50e50..e3e0e591127 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -90,6 +90,8 @@ Polymer({
}.bind(this));
CrPolicyStrings = {
+ controlledSettingExtension:
+ loadTimeData.getString('controlledSettingExtension'),
controlledSettingPolicy:
loadTimeData.getString('controlledSettingPolicy'),
controlledSettingRecommendedMatches:
@@ -158,16 +160,44 @@ Polymer({
loadTimeData.getBoolean('androidAppsAllowed');
},
+ /** @private {?IntersectionObserver} */
+ intersectionObserver_: null,
+
/** @override */
attached: function() {
+ document.documentElement.classList.remove('loading');
+
+ setTimeout(function() {
+ chrome.send(
+ 'metricsHandler:recordTime',
+ ['Settings.TimeUntilInteractive', window.performance.now()]);
+ });
+
// Preload bold Roboto so it doesn't load and flicker the first time used.
document.fonts.load('bold 12px Roboto');
- settings.setGlobalScrollTarget(this.$.headerPanel.scroller);
+ settings.setGlobalScrollTarget(this.$.container);
+
+ // Setup drop shadow logic.
+ var callback = function(entries) {
+ assert(entries.length == 1);
+ this.$.dropShadow.classList.toggle(
+ 'has-shadow', entries[0].intersectionRatio == 0);
+ }.bind(this);
+
+ this.intersectionObserver_ = new IntersectionObserver(
+ callback,
+ /** @type {IntersectionObserverInit} */ ({
+ root: this.$.container,
+ threshold: 0,
+ }));
+ this.intersectionObserver_.observe(this.$.intersectionProbe);
},
/** @override */
detached: function() {
settings.resetRouteForTesting();
+ this.intersectionObserver_.disconnect();
+ this.intersectionObserver_ = null;
},
/** @param {!settings.Route} route */
@@ -237,6 +267,17 @@ Polymer({
},
/** @private */
+ onMenuClosed_: function() {
+ // Add tab index so that the container can be focused.
+ this.$.container.setAttribute('tabindex', '-1');
+ this.$.container.focus();
+
+ listenOnce(this.$.container, ['blur', 'pointerdown'], function() {
+ this.$.container.removeAttribute('tabindex');
+ }.bind(this));
+ },
+
+ /** @private */
directionDelegateChanged_: function() {
this.$.drawer.align = this.directionDelegate.isRtl() ?
'right' : 'left';
diff --git a/chromium/chrome/browser/resources/settings/settings_vars_css.html b/chromium/chrome/browser/resources/settings/settings_vars_css.html
index 1fa88f765cc..69e23aca873 100644
--- a/chromium/chrome/browser/resources/settings/settings_vars_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_vars_css.html
@@ -13,11 +13,10 @@
--settings-actionable: var(--cr-actionable);
- --settings-background-color: rgb(241, 241, 241);
--settings-box-row-padding: 20px;
--settings-box-row-indent: calc(
var(--settings-box-row-padding) + var(--settings-indent-width));
- --settings-indent-width: 36px;
+ --settings-indent-width: 40px;
--settings-card-max-width: 680px;
--settings-disabled-opacity: .65;
--settings-error-color: var(--paper-red-700);
@@ -56,9 +55,9 @@
color: var(--paper-grey-600);
font-weight: 400;
};
+ --settings-separator-height: var(--cr-separator-height);
--settings-separator-line: var(--cr-separator-line);
- --settings-title-bar-background-color: var(--google-blue-700);
--settings-title-bar-color: rgb(255, 255, 255);
--settings-title-search-color: rgb(192, 199, 205);
--settings-toggle-bar-size: {
@@ -82,7 +81,7 @@
--checkbox-margin-start: 2px;
--checkbox-size: 16px;
- --checkbox-spacing: 18px;
+ --settings-control-spacing: var(--cr-control-spacing);
--iron-icon-fill-color: var(--paper-grey-600);
--iron-icon-height: var(--cr-icon-size);
--iron-icon-width: var(--cr-icon-size);
@@ -103,18 +102,23 @@
color: inherit;
font-size: inherit;
font-weight: inherit;
- line-height: inherit;
+ line-height: 154%;
vertical-align: baseline;
};
--paper-input-container-label: {
font-size: inherit;
- line-height: inherit;
- }
+ line-height: 154%;
+ };
+ --paper-input-container-label-floating: {
+ /* Using "rem" to make it easier to equalize with other labels. */
+ font-size: 1rem;
+ line-height: 1.65rem;
+ };
--paper-input-error: {
font-size: 92.31%; /* Should be 12px when 100% is 13px. */
- line-height: inherit;
+ line-height: 154%;
overflow: visible; /* Half-visible error message is not useful at all. */
- }
+ };
--paper-input-max-width: 264px;
--paper-radio-button-ink-size: 40px;
--paper-radio-button-label-color: inherit;
@@ -135,7 +139,7 @@
--settings-input-underline: {
border-color: var(--paper-grey-300);
- }
+ };
--paper-input-container-underline: var(--settings-input-underline);
}
diff --git a/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.html b/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.html
index dab13419719..30d34f60aab 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.html
@@ -1,7 +1,6 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="../i18n_setup.html">
@@ -20,12 +19,11 @@
<dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
<div class="title">$i18n{addSiteTitle}</div>
<div class="body">
- <iron-a11y-keys id="keys" keys="enter"
- on-keys-pressed="onSubmit_"></iron-a11y-keys>
<paper-input id="site" always-float-label label="$i18n{addSite}"
placeholder="$i18n{addSiteExceptionPlaceholder}"
- value="{{site_}}" on-input="validate_" autofocus></paper-input>
- <paper-checkbox id="incognito">
+ value="{{site_}}" on-input="validate_"
+ error-message="$i18n{notValidWebAddress}" autofocus></paper-input>
+ <paper-checkbox id="incognito" hidden$="[[!showIncognitoSessionOnly_]]">
$i18n{incognitoSiteOnly}
</paper-checkbox>
</div>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.js b/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.js
index 59d1ac63ff9..41eecca19c8 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.js
@@ -25,6 +25,9 @@ Polymer({
*/
contentSetting: String,
+ /** @private */
+ showIncognitoSessionOnly_: Boolean,
+
/**
* The site to add an exception for.
* @private
@@ -44,8 +47,10 @@ Polymer({
* Block list.
*/
open: function(type) {
- this.addWebUIListener('onIncognitoStatusChanged',
- this.onIncognitoStatusChanged_.bind(this));
+ this.addWebUIListener('onIncognitoStatusChanged', function(isActive) {
+ this.showIncognitoSessionOnly_ = isActive &&
+ this.contentSetting != settings.PermissionValues.SESSION_ONLY;
+ }.bind(this));
this.browserProxy.updateIncognitoStatus();
this.$.dialog.showModal();
},
@@ -55,7 +60,16 @@ Polymer({
* @private
*/
validate_: function() {
+ // If input is empty, disable the action button, but don't show the red
+ // invalid message.
+ if (this.$.site.value.trim() == '') {
+ this.$.site.invalid = false;
+ this.$.add.disabled = true;
+ return;
+ }
+
this.browserProxy.isPatternValid(this.site_).then(function(isValid) {
+ this.$.site.invalid = !isValid;
this.$.add.disabled = !isValid;
}.bind(this));
},
@@ -66,19 +80,6 @@ Polymer({
},
/**
- * A handler for when we get notified of the current profile creating or
- * destroying their incognito counterpart.
- * @param {boolean} incognitoEnabled Whether the current profile has an
- * incognito profile.
- * @private
- */
- onIncognitoStatusChanged_: function(incognitoEnabled) {
- this.$.incognito.disabled = !incognitoEnabled;
- if (!incognitoEnabled)
- this.$.incognito.checked = false;
- },
-
- /**
* The tap handler for the Add [Site] button (adds the pattern and closes
* the dialog).
* @private
diff --git a/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.html b/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.html
index f5545bb885d..333f4eda399 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.html
@@ -9,22 +9,18 @@
<dom-module id="category-default-setting">
<template>
<style include="settings-shared"></style>
- <div class="settings-box first two-line">
- <div class="start secondary">[[sliderDescription_]]</div>
- <settings-toggle-button id="toggle" pref="{{controlParams_}}"
- disabled$="[[isToggleDisabled_(category)]]">
- </settings-toggle-button>
- </div>
+ <settings-toggle-button id="toggle"
+ class="settings-box first"
+ pref="{{controlParams_}}" label="[[optionLabel_]]"
+ sub-label="[[optionDescription]]"
+ disabled$="[[isToggleDisabled_(category)]]">
+ </settings-toggle-button>
<template is="dom-if" if="[[subOptionLabel]]">
- <div class="settings-box">
- <div class="start">
- [[subOptionLabel]]
- <div class="secondary">[[subOptionSecondary]]</div>
- </div>
- <settings-toggle-button disabled$="[[!controlParams_.value]]"
- id="subOptionToggle" pref="{{subControlParams_}}">
- </settings-toggle-button>
- </div>
+ <settings-toggle-button id="subOptionToggle"
+ class="settings-box" pref="{{subControlParams_}}"
+ label="[[subOptionLabel]]" sub-label="[[subOptionDescription]]"
+ disabled$="[[!controlParams_.value]]">
+ </settings-toggle-button>
</template>
</template>
<script src="category_default_setting.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js b/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js
index f481cc5da4e..2ceb2a78a4d 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js
@@ -13,6 +13,20 @@ Polymer({
behaviors: [SiteSettingsBehavior, WebUIListenerBehavior],
properties: {
+ /* The second line, shown under the |optionLabel_| line. (optional) */
+ optionDescription: String,
+
+ /* The second line, shown under the |subOptionLabel| line. (optional) */
+ subOptionDescription: String,
+
+ /* The sub-option is a separate toggle. Setting this label will show the
+ * additional toggle. Shown above |subOptionDescription|. (optional) */
+ subOptionLabel: String,
+
+ /* The on/off text for |optionLabel_| below. */
+ toggleOffLabel: String,
+ toggleOnLabel: String,
+
/** @private {chrome.settingsPrivate.PrefObject} */
controlParams_: {
type: Object,
@@ -21,6 +35,13 @@ Polymer({
},
},
+ /**
+ * The label to be shown next to the toggle (above |optionDescription|).
+ * This will be either toggleOffLabel or toggleOnLabel.
+ * @private
+ */
+ optionLabel_: String,
+
/** @private {!DefaultContentSetting} */
priorDefaultContentSetting_: {
type: Object,
@@ -30,12 +51,6 @@ Polymer({
},
/**
- * The description to be shown next to the slider.
- * @private
- */
- sliderDescription_: String,
-
- /**
* Cookies and Flash settings have a sub-control that is used to mimic a
* tri-state value.
* @private {chrome.settingsPrivate.PrefObject}
@@ -46,10 +61,6 @@ Polymer({
return /** @type {chrome.settingsPrivate.PrefObject} */({});
},
},
-
- /* Labels for the toggle on/off positions. */
- toggleOffLabel: String,
- toggleOnLabel: String,
},
observers: [
@@ -79,6 +90,8 @@ Polymer({
case settings.ContentSettingsTypes.JAVASCRIPT:
case settings.ContentSettingsTypes.POPUPS:
case settings.ContentSettingsTypes.PROTOCOL_HANDLERS:
+ case settings.ContentSettingsTypes.SUBRESOURCE_FILTER:
+
// "Allowed" vs "Blocked".
this.browserProxy.setDefaultValueForContentType(
this.category,
@@ -185,7 +198,7 @@ Polymer({
this.category).then(function(defaultValue) {
this.updateControlParams_(defaultValue);
- // Flash only shows ALLOW or BLOCK descriptions on the slider.
+ // Flash only shows ALLOW or BLOCK descriptions on the toggle.
var setting = defaultValue.setting;
if (this.category == settings.ContentSettingsTypes.PLUGINS &&
setting == settings.PermissionValues.IMPORTANT_CONTENT) {
@@ -196,7 +209,7 @@ Polymer({
setting = settings.PermissionValues.ALLOW;
}
var categoryEnabled = setting != settings.PermissionValues.BLOCK;
- this.sliderDescription_ =
+ this.optionLabel_ =
categoryEnabled ? this.toggleOnLabel : this.toggleOffLabel;
}.bind(this));
},
@@ -208,5 +221,5 @@ Polymer({
isToggleDisabled_: function() {
return this.category == settings.ContentSettingsTypes.POPUPS &&
loadTimeData.getBoolean('isGuest');
- }
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
index 3fe8e0f1f0a..02143c7969d 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
@@ -17,17 +17,20 @@
<site-list
category="[[category]]"
category-subtype="[[PermissionValues.BLOCK]]"
- category-header="$i18n{siteSettingsBlock}">
+ category-header="$i18n{siteSettingsBlock}"
+ read-only-list="[[readOnlyList]]">
</site-list>
<site-list
category="[[category]]"
category-subtype="[[PermissionValues.SESSION_ONLY]]"
- category-header="$i18n{siteSettingsSessionOnly}">
+ category-header="$i18n{siteSettingsSessionOnly}"
+ read-only-list="[[readOnlyList]]">
</site-list>
<site-list
category="[[category]]"
category-subtype="[[PermissionValues.ALLOW]]"
- category-header="$i18n{siteSettingsAllow}">
+ category-header="$i18n{siteSettingsAllow}"
+ read-only-list="[[readOnlyList]]">
</site-list>
</template>
<script src="category_setting_exceptions.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
index 4a972fa02ea..0e457fefd77 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
@@ -10,6 +10,18 @@
Polymer({
is: 'category-setting-exceptions',
+ properties: {
+ /**
+ * Some content types (like Location) do not allow the user to manually
+ * edit the exception list from within Settings.
+ * @private
+ */
+ readOnlyList: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
/** @override */
ready: function() {
this.PermissionValues = settings.PermissionValues;
diff --git a/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
index 80a76e2cc53..52ae44c087f 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
@@ -175,6 +175,8 @@
'target_name': 'site_settings_behavior',
'dependencies': [
'../compiled_resources2.gyp:route',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_pref_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
@@ -189,6 +191,7 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(EXTERNS_GYP):chrome_send',
+ 'constants',
'cookie_tree_node',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chromium/chrome/browser/resources/settings/site_settings/constants.js b/chromium/chrome/browser/resources/settings/site_settings/constants.js
index e11e3bfdc0d..ea801eb704d 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/constants.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/constants.js
@@ -16,11 +16,11 @@ settings.ContentSettingsTypes = {
COOKIES: 'cookies',
IMAGES: 'images',
JAVASCRIPT: 'javascript',
- PLUGINS: 'plugins',
+ PLUGINS: 'plugins', // AKA Flash.
POPUPS: 'popups',
GEOLOCATION: 'location',
NOTIFICATIONS: 'notifications',
- MIC: 'media-stream-mic',
+ MIC: 'media-stream-mic', // AKA Microphone.
CAMERA: 'media-stream-camera',
PROTOCOL_HANDLERS: 'register-protocol-handler',
UNSANDBOXED_PLUGINS: 'ppapi-broker',
@@ -32,6 +32,7 @@ settings.ContentSettingsTypes = {
// <if expr="chromeos">
PROTECTED_CONTENT: 'protectedContent',
// </if>
+ SUBRESOURCE_FILTER: 'subresource-filter',
};
/**
diff --git a/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html b/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html
index ea1abb33866..f8166f6f0e0 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.html
@@ -12,9 +12,9 @@
<div class="title">$i18n{editSiteTitle}</div>
<div class="body">
<paper-input always-float-label label="$i18n{addSite}"
- placeholder="$i18n{addSiteExceptionPlaceholder}"
- value="{{origin_}}" on-input="validate_" on-keypress="onKeypress_"
- autofocus>
+ placeholder="$i18n{addSiteExceptionPlaceholder}" value="{{origin_}}"
+ on-input="validate_" error-message="$i18n{notValidWebAddress}"
+ invalid="[[invalid_]]" autofocus>
</paper-input>
</div>
<div class="button-container">
@@ -22,7 +22,9 @@
<paper-button class="cancel-button" on-tap="onCancelTap_"
id="cancel">$i18n{cancel}</paper-button>
<paper-button id="actionButton" class="action-button"
- on-tap="onActionButtonTap_">$i18n{edit}</paper-button>
+ on-tap="onActionButtonTap_" disabled="[[invalid_]]">
+ $i18n{edit}
+ </paper-button>
</div>
</div>
</dialog>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js b/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js
index e44f6b79416..bc5cc802430 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js
@@ -17,6 +17,15 @@ Polymer({
/** @private */
origin_: String,
+
+ /**
+ * Whether the current input is invalid.
+ * @private
+ */
+ invalid_: {
+ type: Boolean,
+ value: false,
+ },
},
/** @private {!settings.SiteSettingsPrefsBrowserProxy} */
@@ -39,21 +48,17 @@ Polymer({
/** @private */
onActionButtonTap_: function() {
if (this.model.origin != this.origin_) {
- // TODO(dpapad): Only COOKIES category can be edited currently,
- // crbug.com/695578.
- var category = settings.ContentSettingsTypes.COOKIES;
-
// The way to "edit" an exception is to remove it and and a new one.
this.browserProxy_.resetCategoryPermissionForOrigin(
this.model.origin,
this.model.embeddingOrigin,
- category,
+ this.model.category,
this.model.incognito);
this.browserProxy_.setCategoryPermissionForOrigin(
this.origin_,
this.origin_,
- category,
+ this.model.category,
this.model.setting,
this.model.incognito);
}
@@ -61,19 +66,15 @@ Polymer({
this.$.dialog.close();
},
- /**
- * @param {!KeyboardEvent} e
- * @private
- */
- onKeypress_: function(e) {
- if (e.key == 'Enter' && !this.$.actionButton.disabled)
- this.onActionButtonTap_();
- },
-
/** @private */
validate_: function() {
+ if (this.$$('paper-input').value.trim() == '') {
+ this.invalid_ = true;
+ return;
+ }
+
this.browserProxy_.isPatternValid(this.origin_).then(function(isValid) {
- this.$.actionButton.disabled = !isValid;
+ this.invalid_ = !isValid;
}.bind(this));
},
});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/media_picker.html b/chromium/chrome/browser/resources/settings/site_settings/media_picker.html
index 0bcd6a228a7..28c07fc855e 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/media_picker.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/media_picker.html
@@ -12,7 +12,8 @@
</style>
<div class="settings-box first" id="picker" hidden>
<div class="md-select-wrapper">
- <select id="mediaPicker" class="md-select" on-change="onChange_">
+ <select id="mediaPicker" class="md-select" on-change="onChange_"
+ aria-label$="[[label]]">
<template is="dom-repeat" items="[[devices]]">
<option value$="[[item.id]]">[[item.name]]</option>
</template>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/media_picker.js b/chromium/chrome/browser/resources/settings/site_settings/media_picker.js
index 829b74a4160..178e06498e5 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/media_picker.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/media_picker.js
@@ -18,6 +18,9 @@ Polymer({
*/
type: String,
+ /** Label for a11y purposes. */
+ label: String,
+
/**
* The devices available to pick from.
* @type {Array<MediaPickerEntry>}
diff --git a/chromium/chrome/browser/resources/settings/site_settings/pdf_documents.html b/chromium/chrome/browser/resources/settings/site_settings/pdf_documents.html
index 3c42c4baed8..87637718d23 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/pdf_documents.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/pdf_documents.html
@@ -10,10 +10,8 @@
}
</style>
<div class="settings-box first two-line">
- <div class="start secondary">
- $i18n{siteSettingsPdfDifferentApplication}
- </div>
- <settings-toggle-button id="toggle"
+ <settings-toggle-button id="toggle" class="start"
+ label="$i18n{siteSettingsPdfDifferentApplication}"
pref="{{prefs.plugins.always_open_pdf_externally}}">
</settings-toggle-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html b/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html
index 33fbfecd710..4cea82f8706 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html
@@ -16,14 +16,14 @@
display: block;
}
- .site-settings-header {
+ .column-header {
-webkit-margin-start: 20px;
margin-bottom: 15px;
margin-top: 15px;
}
</style>
<div class="settings-box first two-line">
- <div id="categoryLabel" class="start secondary">
+ <div id="categoryLabel" class="start">
[[computeHandlersDescription_(categoryEnabled)]]
</div>
<paper-toggle-button id="toggle" checked="{{categoryEnabled}}"
@@ -32,7 +32,7 @@
</div>
<template is="dom-repeat" items="[[protocols]]" as="protocol">
- <div class="site-settings-header">[[protocol.protocol]]</div>
+ <div class="column-header">[[protocol.protocol]]</div>
<div class="list-frame menu-content vertical-list">
<template is="dom-repeat" items="[[protocol.handlers]]">
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data.html b/chromium/chrome/browser/resources/settings/site_settings/site_data.html
index c1aa8dcb9ed..0700aaa39d3 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data.html
@@ -31,7 +31,7 @@
</style>
<div class="settings-box first subtitle-row">
<div class="start">
- <div>$i18n{siteSettingsCookieHeader}</div>
+ <h2>$i18n{siteSettingsCookieHeader}</h2>
</div>
<settings-subpage-search id="filter" on-search-changed="onSearchChanged_"
label="$i18n{siteSettingsCookieSearch}">
@@ -46,7 +46,8 @@
</div>
<div class="list-frame vertical-list">
<template is="dom-repeat" id="list" items="[[sites]]" filter="showItem_"
- rendered-item-count="{{renderedItemCount}}">
+ rendered-item-count="{{renderedItemCount::dom-change}}"
+ notify-dom-change>
<div class="list-item two-line" on-tap="onSiteTap_" actionable>
<div class="favicon-image" style$="[[computeSiteIcon(item.site)]]">
</div>
@@ -69,7 +70,8 @@
</div>
<!-- Confirm Delete dialog -->
- <dialog is="cr-dialog" id="confirmDeleteDialog" close-text="$i18n{close}">
+ <dialog is="cr-dialog" id="confirmDeleteDialog" close-text="$i18n{close}"
+ on-close="onConfirmDeleteDialogClosed_">
<div class="title">$i18n{siteSettingsCookieRemoveDialogTitle}</div>
<div class="body">[[confirmationDeleteMsg_]]</div>
<div class="button-container">
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data.js b/chromium/chrome/browser/resources/settings/site_settings/site_data.js
index cd140bf0ce6..d7dca1afc11 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data.js
@@ -34,6 +34,30 @@ Polymer({
/** @private */
confirmationDeleteMsg_: String,
+
+ /** @type {!Map<string, string>} */
+ focusConfig: {
+ type: Object,
+ observer: 'focusConfigChanged_',
+ },
+ },
+
+ /**
+ * @param {!Map<string, string>} newConfig
+ * @param {?Map<string, string>} oldConfig
+ * @private
+ */
+ focusConfigChanged_: function(newConfig, oldConfig) {
+ // focusConfig is set only once on the parent, so this observer should only
+ // fire once.
+ assert(!oldConfig);
+
+ // Populate the |focusConfig| map of the parent <settings-animated-pages>
+ // element, with additional entries that correspond to subpage trigger
+ // elements residing in this element's Shadow DOM.
+ this.focusConfig.set(
+ settings.Route.SITE_SETTINGS_DATA_DETAILS.path,
+ '* /deep/ #filter /deep/ #searchInput');
},
/** @override */
@@ -83,6 +107,11 @@ Polymer({
this.$.confirmDeleteDialog.close();
},
+ /** @private */
+ onConfirmDeleteDialogClosed_: function() {
+ this.$.removeShowingSites.focus();
+ },
+
/**
* Shows a dialog to confirm the deletion of multiple sites.
* @param {!Event} e
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js b/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
index 7196b784d48..ed83ad966cd 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
@@ -15,12 +15,6 @@ Polymer({
properties: {
/**
- * The browser proxy used to retrieve and change cookies.
- * @type {settings.SiteSettingsPrefsBrowserProxy}
- */
- browserProxy: Object,
-
- /**
* The cookie entries for the given site.
* @type {!Array<!CookieDetails>}
* @private
@@ -40,9 +34,15 @@ Polymer({
siteId_: String,
},
+ /**
+ * The browser proxy used to retrieve and change cookies.
+ * @private {?settings.SiteSettingsPrefsBrowserProxy}
+ */
+ browserProxy_: null,
+
/** @override */
ready: function() {
- this.browserProxy =
+ this.browserProxy_ =
settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
this.addWebUIListener('onTreeItemRemoved',
@@ -69,7 +69,7 @@ Polymer({
getCookieDetails_: function() {
if (!this.site_)
return;
- this.browserProxy.getCookieDetails(this.site_).then(
+ this.browserProxy_.getCookieDetails(this.site_).then(
this.onCookiesLoaded_.bind(this),
this.onCookiesLoadFailed_.bind(this));
},
@@ -124,7 +124,7 @@ Polymer({
* @private
*/
onRemove_: function(event) {
- this.browserProxy.removeCookie(
+ this.browserProxy_.removeCookie(
/** @type {!CookieDetails} */(event.currentTarget.dataset).idPath);
},
@@ -132,7 +132,7 @@ Polymer({
* A handler for when the user opts to remove all cookies.
*/
removeAll: function() {
- this.browserProxy.removeCookie(this.siteId_);
+ this.browserProxy_.removeCookie(this.siteId_);
},
});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details.html b/chromium/chrome/browser/resources/settings/site_settings/site_details.html
index 029e887bd8e..d65bdd63f1b 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.html
@@ -83,7 +83,7 @@
label="$i18n{siteSettingsNotifications}" site="[[site]]">
</site-details-permission>
<site-details-permission category="{{ContentSettingsTypes.JAVASCRIPT}}"
- icon="settings:input" id="javascript"
+ icon="settings:code" id="javascript"
label="$i18n{siteSettingsJavascript}" site="[[site]]">
</site-details-permission>
<site-details-permission category="{{ContentSettingsTypes.PLUGINS}}"
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html
index c5f56fe7683..4bdebb326e5 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html
@@ -20,6 +20,7 @@
<div class="middle" id="permissionHeader">[[label]]</div>
<div class="md-select-wrapper">
<select id="permission" class="md-select"
+ aria-labelledby="permissionHeader"
on-change="onPermissionSelectionChange_">
<option id="allow" value$="[[PermissionValues.ALLOW]]">
$i18n{siteSettingsActionAllow}
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_list.html b/chromium/chrome/browser/resources/settings/site_settings/site_list.html
index 106409c2b51..5d84fea2ffc 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list.html
@@ -1,6 +1,7 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
@@ -29,8 +30,9 @@
<div id="category">
<div class="settings-box first" hidden$="[[allSites]]">
<h2 class="start">[[categoryHeader]]</h2>
- <paper-button class="secondary-button header-aligned-button" id="icon"
- on-tap="onAddSiteTap_">
+ <paper-button id="addSite"
+ class="secondary-button header-aligned-button"
+ hidden="[[readOnlyList]]" on-tap="onAddSiteTap_">
$i18n{add}
</paper-button>
</div>
@@ -50,7 +52,7 @@
$i18n{siteSettingsActionSessionOnly}
</button>
<button class="dropdown-item" role="option" id="edit"
- on-tap="onEditTap_" hidden$="[[!showEditAction_]]">
+ on-tap="onEditTap_">
$i18n{edit}
</button>
<button class="dropdown-item" role="option" id="reset"
@@ -64,7 +66,8 @@
</div>
<div class="list-frame menu-content vertical-list" id="listContainer">
<template is="dom-repeat" items="[[sites]]">
- <div class="list-item" actionable$="[[enableSiteSettings_]]" on-tap="onOriginTap_">
+ <div class="list-item" actionable$="[[enableSiteSettings_]]"
+ on-tap="onOriginTap_">
<div class="favicon-image"
style$="[[computeSiteIcon(item.origin)]]">
</div>
@@ -75,13 +78,19 @@
<div class="selectable secondary text-elide" id="siteDescription"
>[[computeSiteDescription_(item)]]</div>
</div>
-
- <template is="dom-if" if="[[!!computeIconControlledBy_(item)]]">
- <iron-icon icon="[[computeIconControlledBy_(item)]]"></iron-icon>
+ <template is="dom-if" if="[[item.controlledBy]]">
+ <cr-policy-pref-indicator pref="[[item]]"
+ icon-aria-label="[[label]]">
+ </cr-policy-pref-indicator>
</template>
- <paper-icon-button id="dots" icon="cr:more-vert"
- hidden="[[isActionMenuHidden_(item.source)]]"
+ <paper-icon-button id="resetSite" icon="cr:delete"
+ hidden="[[isResetButtonHidden_(
+ item.enforcement, readOnlyList)]]"
+ on-tap="onResetButtonTap_" alt="$i18n{siteSettingsActionReset}">
+ </paper-icon-button>
+ <paper-icon-button id="actionMenuButton" icon="cr:more-vert"
+ hidden="[[isActionMenuHidden_(item.enforcement, readOnlyList)]]"
on-tap="onShowActionMenuTap_" title="$i18n{moreActions}">
</paper-icon-button>
<template is="dom-if" if="[[enableSiteSettings_]]">
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_list.js b/chromium/chrome/browser/resources/settings/site_settings/site_list.js
index ed7a2b3747c..7c17e9de560 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list.js
@@ -3,18 +3,6 @@
// found in the LICENSE file.
/**
- * Enumeration mapping all possible controlled-by values for exceptions to
- * icons.
- * @enum {string}
- */
-var iconControlledBy = {
- 'extension': 'cr:extension',
- 'HostedApp': 'cr:extension',
- 'platform_app': 'cr:extension',
- 'policy' : 'cr20:domain',
-};
-
-/**
* @fileoverview
* 'site-list' shows a list of Allowed and Blocked sites for a given
* category.
@@ -35,6 +23,16 @@ Polymer({
},
/**
+ * Some content types (like Location) do not allow the user to manually
+ * edit the exception list from within Settings.
+ * @private
+ */
+ readOnlyList: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
* The site serving as the model for the currently open action menu.
* @private {?SiteException}
*/
@@ -52,7 +50,9 @@ Polymer({
*/
sites: {
type: Array,
- value: function() { return []; },
+ value: function() {
+ return [];
+ },
},
/**
@@ -64,10 +64,10 @@ Polymer({
},
/**
- * The type of category this widget is displaying data for. Normally
- * either 'allow' or 'block', representing which sites are allowed or
- * blocked respectively.
- */
+ * The type of category this widget is displaying data for. Normally
+ * either 'allow' or 'block', representing which sites are allowed or
+ * blocked respectively.
+ */
categorySubtype: {
type: String,
value: settings.INVALID_CATEGORY_SUBTYPE,
@@ -93,22 +93,6 @@ Polymer({
showSessionOnlyAction_: Boolean,
/**
- * Whether to show the 'edit' action in the action menu.
- * @private
- */
- showEditAction_: Boolean,
-
- /**
- * Keeps track of the incognito status of the current profile (whether one
- * exists).
- * @private
- */
- incognitoProfileActive_: {
- type: Boolean,
- value: false,
- },
-
- /**
* All possible actions in the action menu.
* @private
*/
@@ -124,9 +108,13 @@ Polymer({
},
},
- observers: [
- 'configureWidget_(category, categorySubtype)'
- ],
+ /**
+ * The element to return focus to, when the currently active dialog is closed.
+ * @private {?HTMLElement}
+ */
+ activeDialogAnchor_: null,
+
+ observers: ['configureWidget_(category, categorySubtype)'],
ready: function() {
this.addWebUIListener('contentSettingSitePermissionChanged',
@@ -146,18 +134,21 @@ Polymer({
this.configureWidget_();
},
- onIncognitoStatusChanged_: function(incognitoEnabled) {
- // A change notification is not sent for each site that is deleted during
- // incognito profile destruction. Therefore, we reconfigure the list when
- // the incognito profile is destroyed, except for SESSION_ONLY, which won't
- // have any incognito exceptions.
+ /**
+ * Called for each site list when incognito is enabled or disabled. Only
+ * called on change (opening N incognito windows only fires one message).
+ * Another message is sent when the *last* incognito window closes.
+ * @private
+ */
+ onIncognitoStatusChanged_: function() {
+ // The SESSION_ONLY list won't have any incognito exceptions. (Minor
+ // optimization, not required).
if (this.categorySubtype == settings.PermissionValues.SESSION_ONLY)
return;
- if (this.incognitoProfileActive_)
- this.configureWidget_(); // The incognito profile is being destroyed.
-
- this.incognitoProfileActive_ = incognitoEnabled;
+ // A change notification is not sent for each site. So we repopulate the
+ // whole list when the incognito profile is created or destroyed.
+ this.populateList_();
},
/**
@@ -183,34 +174,35 @@ Polymer({
},
/**
- * Returns which icon, if any, should represent the fact that this exception
- * is controlled.
- * @param {!SiteException} item The item from the list we're computing the
- * icon for.
- * @return {string} The icon to show (or blank, if none).
+ * Whether there are any site exceptions added for this content setting.
+ * @return {boolean}
+ * @private
*/
- computeIconControlledBy_: function(item) {
- if (this.allSites)
- return '';
- return iconControlledBy[item.source] || '';
+ hasSites_: function() {
+ return !!this.sites.length;
},
/**
- * Whether there are any site exceptions added for this content setting.
+ * @param {chrome.settingsPrivate.Enforcement} enforcement The level of
+ * enforcement.
+ * @param {boolean} readOnlyList Whether the site exception list is read-only.
* @return {boolean}
* @private
*/
- hasSites_: function() {
- return !!this.sites.length;
+ isResetButtonHidden_: function(enforcement, readOnlyList) {
+ return enforcement == chrome.settingsPrivate.Enforcement.ENFORCED ||
+ this.allSites || !readOnlyList;
},
/**
- * @param {string} source Where the setting came from.
+ * @param {string} enforcement Whether the exception is controlled.
+ * @param {boolean} readOnlyList Whether the site exception list is read-only.
* @return {boolean}
* @private
*/
- isActionMenuHidden_: function(source) {
- return this.isExceptionControlled_(source) || this.allSites;
+ isActionMenuHidden_: function(enforcement, readOnlyList) {
+ return enforcement == chrome.settingsPrivate.Enforcement.ENFORCED ||
+ this.allSites || readOnlyList;
},
/**
@@ -219,6 +211,7 @@ Polymer({
* @private
*/
onAddSiteTap_: function(e) {
+ assert(!this.readOnlyList);
e.preventDefault();
var dialog = document.createElement('add-site-dialog');
dialog.category = this.category;
@@ -228,8 +221,9 @@ Polymer({
dialog.open(this.categorySubtype);
dialog.addEventListener('close', function() {
+ this.$.addSite.focus();
dialog.remove();
- });
+ }.bind(this));
},
/**
@@ -253,14 +247,24 @@ Polymer({
/**
* Process the exception list returned from the native layer.
- * @param {!Array<!Array<SiteException>>} data List of sites (exceptions) to
- * process.
+ * @param {!Array<!Array<RawSiteException>>} data List of sites (exceptions)
+ * to process.
* @private
*/
processExceptions_: function(data) {
- var sites = [];
- for (var i = 0; i < data.length; ++i)
- sites = this.appendSiteList_(sites, data[i]);
+ var sites = /** @type {!Array<RawSiteException>} */ ([]);
+ for (var i = 0; i < data.length; ++i) {
+ var exceptionList = data[i];
+ for (var k = 0; k < exceptionList.length; ++k) {
+ if (!this.allSites &&
+ (exceptionList[k].setting == settings.PermissionValues.DEFAULT ||
+ exceptionList[k].setting != this.categorySubtype)) {
+ continue;
+ }
+
+ sites.push(exceptionList[k]);
+ }
+ }
this.sites = this.toSiteArray_(sites);
},
@@ -291,34 +295,11 @@ Polymer({
},
/**
- * Appends to |list| the sites for a given category and subtype.
- * @param {!Array<SiteException>} sites The site list to add to.
- * @param {!Array<SiteException>} exceptionList List of sites (exceptions) to
- * add.
- * @return {!Array<SiteException>} The list of sites.
- * @private
- */
- appendSiteList_: function(sites, exceptionList) {
- for (var i = 0; i < exceptionList.length; ++i) {
- if (!this.allSites) {
- if (exceptionList[i].setting == settings.PermissionValues.DEFAULT)
- continue;
-
- if (exceptionList[i].setting != this.categorySubtype)
- continue;
- }
-
- sites.push(exceptionList[i]);
- }
- return sites;
- },
-
- /**
* Converts a list of exceptions received from the C++ handler to
* full SiteException objects. If this site-list is used as an all sites
* view, the list is sorted by site name, then protocol and port and de-duped
* (by origin).
- * @param {!Array<SiteException>} sites A list of sites to convert.
+ * @param {!Array<RawSiteException>} sites A list of sites to convert.
* @return {!Array<SiteException>} A list of full SiteExceptions. Sorted and
* deduped if allSites is set.
* @private
@@ -379,8 +360,6 @@ Polymer({
this.showSessionOnlyAction_ =
this.categorySubtype != settings.PermissionValues.SESSION_ONLY &&
this.category == settings.ContentSettingsTypes.COOKIES;
- this.showEditAction_ =
- this.category == settings.ContentSettingsTypes.COOKIES;
},
/**
@@ -411,58 +390,65 @@ Polymer({
},
/**
- * A handler for activating one of the menu action items.
- * @param {string} action The permission to set (Allow, Block, SessionOnly,
- * etc).
+ * @param {?SiteException} site
* @private
*/
- onActionMenuActivate_: function(action) {
- var origin = this.actionMenuSite_.origin;
- var incognito = this.actionMenuSite_.incognito;
- var embeddingOrigin = this.actionMenuSite_.embeddingOrigin;
- if (action == settings.PermissionValues.DEFAULT) {
- this.browserProxy.resetCategoryPermissionForOrigin(
- origin, embeddingOrigin, this.category, incognito);
- } else {
- this.browserProxy.setCategoryPermissionForOrigin(
- origin, embeddingOrigin, this.category, action, incognito);
- }
+ resetPermissionForOrigin_: function(site) {
+ assert(site);
+ this.browserProxy.resetCategoryPermissionForOrigin(
+ site.origin, site.embeddingOrigin, this.category, site.incognito);
+ },
+
+ /**
+ * @param {string} permissionValue
+ * @private
+ */
+ setPermissionForActionMenuSite_: function(permissionValue) {
+ assert(this.actionMenuSite_);
+ this.browserProxy.setCategoryPermissionForOrigin(
+ this.actionMenuSite_.origin, this.actionMenuSite_.embeddingOrigin,
+ this.category, permissionValue, this.actionMenuSite_.incognito);
},
/** @private */
onAllowTap_: function() {
- this.onActionMenuActivate_(settings.PermissionValues.ALLOW);
+ this.setPermissionForActionMenuSite_(settings.PermissionValues.ALLOW);
this.closeActionMenu_();
},
/** @private */
onBlockTap_: function() {
- this.onActionMenuActivate_(settings.PermissionValues.BLOCK);
+ this.setPermissionForActionMenuSite_(settings.PermissionValues.BLOCK);
this.closeActionMenu_();
},
/** @private */
onSessionOnlyTap_: function() {
- this.onActionMenuActivate_(settings.PermissionValues.SESSION_ONLY);
+ this.setPermissionForActionMenuSite_(
+ settings.PermissionValues.SESSION_ONLY);
this.closeActionMenu_();
},
/** @private */
onEditTap_: function() {
+ // Close action menu without resetting |this.actionMenuSite_| since it is
+ // bound to the dialog.
+ /** @type {!CrActionMenuElement} */ (
+ this.$$('dialog[is=cr-action-menu]')).close();
this.showEditExceptionDialog_ = true;
},
/** @private */
onEditExceptionDialogClosed_: function() {
this.showEditExceptionDialog_ = false;
- // Close action menu after dialog has been closed, otherwise
- // |actionMenuSite_| is reset while the dialog is still accessing it.
- this.closeActionMenu_();
+ this.actionMenuSite_ = null;
+ this.activeDialogAnchor_.focus();
+ this.activeDialogAnchor_ = null;
},
/** @private */
onResetTap_: function() {
- this.onActionMenuActivate_(settings.PermissionValues.DEFAULT);
+ this.resetPermissionForOrigin_(this.actionMenuSite_);
this.closeActionMenu_();
},
@@ -488,17 +474,27 @@ Polymer({
* @param {!{model: !{item: !SiteException}}} e
* @private
*/
+ onResetButtonTap_: function(e) {
+ this.resetPermissionForOrigin_(e.model.item);
+ },
+
+ /**
+ * @param {!{model: !{item: !SiteException}}} e
+ * @private
+ */
onShowActionMenuTap_: function(e) {
+ this.activeDialogAnchor_ = /** @type {!HTMLElement} */ (
+ Polymer.dom(/** @type {!Event} */ (e)).localTarget);
+
this.actionMenuSite_ = e.model.item;
/** @type {!CrActionMenuElement} */ (
- this.$$('dialog[is=cr-action-menu]')).showAt(
- /** @type {!Element} */ (
- Polymer.dom(/** @type {!Event} */ (e)).localTarget));
+ this.$$('dialog[is=cr-action-menu]')).showAt(this.activeDialogAnchor_);
},
/** @private */
closeActionMenu_: function() {
this.actionMenuSite_ = null;
+ this.activeDialogAnchor_ = null;
var actionMenu = /** @type {!CrActionMenuElement} */ (
this.$$('dialog[is=cr-action-menu]'));
if (actionMenu.open)
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.js b/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
index 936596566da..121f5d66db0 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
@@ -6,12 +6,28 @@
* @fileoverview Behavior common to Site Settings classes.
*/
+
+/**
+ * The source information on site exceptions doesn't exactly match the
+ * controlledBy values.
+ * TODO(dschuyler): Can they be unified (and this dictionary removed)?
+ * @type {!Object}
+ */
+var kControlledByLookup = {
+ 'extension': chrome.settingsPrivate.ControlledBy.EXTENSION,
+ 'HostedApp': chrome.settingsPrivate.ControlledBy.EXTENSION,
+ 'platform_app': chrome.settingsPrivate.ControlledBy.EXTENSION,
+ 'policy': chrome.settingsPrivate.ControlledBy.USER_POLICY,
+};
+
+
/** @polymerBehavior */
var SiteSettingsBehaviorImpl = {
properties: {
/**
* The string ID of the category this element is displaying data for.
* See site_settings/constants.js for possible values.
+ * @type {!settings.ContentSettingsTypes}
*/
category: String,
@@ -38,7 +54,8 @@ var SiteSettingsBehaviorImpl = {
* @return {string} The URL with a scheme, or an empty string.
*/
ensureUrlHasScheme: function(url) {
- if (url.length == 0) return url;
+ if (url.length == 0)
+ return url;
return url.includes('://') ? url : 'http://' + url;
},
@@ -93,17 +110,6 @@ var SiteSettingsBehaviorImpl = {
},
/**
- * Returns true if this exception is controlled by, for example, a policy or
- * set by an extension.
- * @param {string} source The source controlling the extension
- * @return {boolean} Whether it is being controlled.
- * @protected
- */
- isExceptionControlled_: function(source) {
- return source != undefined && source != 'preference';
- },
-
- /**
* Returns the icon to use for a given site.
* @param {string} site The url of the site to fetch the icon for.
* @return {string} The background-image style with the favicon.
@@ -146,8 +152,8 @@ var SiteSettingsBehaviorImpl = {
/**
* Convert an exception (received from the C++ handler) to a full
* SiteException.
- * @param {!Object} exception The raw site exception from C++.
- * @return {SiteException} The expanded (full) SiteException.
+ * @param {!RawSiteException} exception The raw site exception from C++.
+ * @return {!SiteException} The expanded (full) SiteException.
* @private
*/
expandSiteException: function(exception) {
@@ -159,14 +165,22 @@ var SiteSettingsBehaviorImpl = {
this.getEmbedderString(embeddingOrigin, this.category);
}
+ var enforcement = '';
+ if (exception.source == 'policy' || exception.source == 'extension')
+ enforcement = chrome.settingsPrivate.Enforcement.ENFORCED;
+
+ var controlledBy = kControlledByLookup[exception.source] || '';
+
return {
+ category: this.category,
origin: origin,
displayName: exception.displayName,
embeddingOrigin: embeddingOrigin,
embeddingDisplayName: embeddingDisplayName,
incognito: exception.incognito,
setting: exception.setting,
- source: exception.source,
+ enforcement: enforcement,
+ controlledBy: controlledBy,
};
},
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js b/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
index 651257799ea..82954acfcc7 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
@@ -19,6 +19,8 @@ var ContentSettingProvider = {
};
/**
+ * The site exception information passed form the C++ handler.
+ * See also: SiteException.
* @typedef {{embeddingOrigin: string,
* embeddingDisplayName: string,
* incognito: boolean,
@@ -27,6 +29,21 @@ var ContentSettingProvider = {
* setting: string,
* source: string}}
*/
+var RawSiteException;
+
+/**
+ * The site exception after it has been converted/filtered for UI use.
+ * See also: RawSiteException.
+ * @typedef {{category: !settings.ContentSettingsTypes,
+ * embeddingOrigin: string,
+ * embeddingDisplayName: string,
+ * incognito: boolean,
+ * origin: string,
+ * displayName: string,
+ * setting: string,
+ * enforcement: string,
+ * controlledBy: string}}
+ */
var SiteException;
/**
@@ -42,18 +59,6 @@ var CategoryDefaultsPref;
var DefaultContentSetting;
/**
- * @typedef {{location: Array<SiteException>,
- * notifications: Array<SiteException>}}
- */
-var ExceptionListPref;
-
-/**
- * @typedef {{defaults: CategoryDefaultsPref,
- * exceptions: ExceptionListPref}}
- */
-var SiteSettingsPref;
-
-/**
* @typedef {{name: string,
* id: string}}
*/
@@ -120,14 +125,14 @@ cr.define('settings', function() {
/**
* Gets the exceptions (site list) for a particular category.
* @param {string} contentType The name of the category to query.
- * @return {!Promise<!Array<!SiteException>>}
+ * @return {!Promise<!Array<!RawSiteException>>}
*/
getExceptionList: function(contentType) {},
/**
* Gets the exception details for a particular site.
* @param {string} site The name of the site.
- * @return {!Promise<!SiteException>}
+ * @return {!Promise<!RawSiteException>}
*/
getSiteDetails: function(site) {},
@@ -321,15 +326,20 @@ cr.define('settings', function() {
/** @override */
resetCategoryPermissionForOrigin: function(
primaryPattern, secondaryPattern, contentType, incognito) {
- chrome.send('resetCategoryPermissionForOrigin',
+ chrome.send(
+ 'resetCategoryPermissionForOrigin',
[primaryPattern, secondaryPattern, contentType, incognito]);
},
/** @override */
setCategoryPermissionForOrigin: function(
primaryPattern, secondaryPattern, contentType, value, incognito) {
- chrome.send('setCategoryPermissionForOrigin',
- [primaryPattern, secondaryPattern, contentType, value, incognito]);
+ // TODO(dschuyler): It may be incorrect for JS to send the embeddingOrigin
+ // pattern. Look into removing this parameter from site_settings_handler.
+ // Ignoring the |secondaryPattern| and using '' instead is a quick-fix.
+ chrome.send(
+ 'setCategoryPermissionForOrigin',
+ [primaryPattern, '', contentType, value, incognito]);
},
/** @override */
diff --git a/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html b/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html
index 57a312cc5f8..f1451873e83 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html
@@ -14,7 +14,7 @@
display: block;
}
- .site-settings-header {
+ .column-header {
-webkit-margin-start: 20px;
margin-bottom: 15px;
margin-top: 15px;
@@ -22,7 +22,7 @@
</style>
<template is="dom-repeat" items="[[devices_]]">
- <div class="site-settings-header">[[item.objectName]]</div>
+ <div class="column-header">[[item.objectName]]</div>
<div class="list-frame menu-content vertical-list">
<div class="list-item">
diff --git a/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html b/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html
index 2806ac8c943..50bd0b1446a 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html
@@ -16,15 +16,15 @@
.zoom-label {
-webkit-margin-end: 16px;
+ color: var(--paper-grey-600);
}
- .empty-message {
+ #empty {
margin-top: 15px;
}
</style>
<div class="list-frame vertical-list" id="listContainer">
- <template is="dom-repeat" items="[[sites_]]" id="list"
- rendered-item-count="{{renderedCount}}">
+ <template is="dom-repeat" items="[[sites_]]" id="list">
<div class="list-item">
<div class="favicon-image"
style$="[[computeSiteIcon(item.originForFavicon)]]">
@@ -34,13 +34,13 @@
</div>
<div class="zoom-label">[[item.zoom]]</div>
<div>
- <paper-icon-button icon="cr:clear"
- on-tap="removeZoomLevel_">
+ <paper-icon-button icon="cr:clear" on-tap="removeZoomLevel_"
+ title="$i18n{siteSettingsRemoveZoomLevel}"></paper-icon-button>
</div>
</div>
</template>
- <template is="dom-if" if="{{!renderedCount}}">
- <div class="empty-message" id="empty">
+ <template is="dom-if" if="[[!sites_.length]]">
+ <div id="empty">
$i18n{siteSettingsNoZoomedSites}
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
index a2f49dd9df3..17cfd6ef5f5 100644
--- a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
+++ b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -26,7 +26,7 @@
<div class="settings-box line-only">
</div>
</template>
- <div class="settings-box two-line first"
+ <div id="cookies" class="settings-box two-line first"
category$="[[ContentSettingsTypes.COOKIES]]"
data-route="SITE_SETTINGS_COOKIES" on-tap="onTapNavigate_" actionable>
<iron-icon icon="settings:cookie"></iron-icon>
@@ -44,7 +44,7 @@
aria-label="$i18n{siteSettingsCookies}"
aria-describedby="cookiesSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="location" class="settings-box two-line"
category$="[[ContentSettingsTypes.GEOLOCATION]]"
data-route="SITE_SETTINGS_LOCATION" on-tap="onTapNavigate_" actionable>
<iron-icon icon="settings:location-on"></iron-icon>
@@ -61,7 +61,7 @@
aria-label="$i18n{siteSettingsLocation}"
aria-describedby="locationSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="camera" class="settings-box two-line"
category$="[[ContentSettingsTypes.CAMERA]]"
data-route="SITE_SETTINGS_CAMERA"
on-tap="onTapNavigate_" actionable>
@@ -79,7 +79,8 @@
aria-label="$i18n{siteSettingsCamera}"
aria-describedby="cameraSecondary"></button>
</div>
- <div class="settings-box two-line" category$="[[ContentSettingsTypes.MIC]]"
+ <div id="microphone" class="settings-box two-line"
+ category$="[[ContentSettingsTypes.MIC]]"
data-route="SITE_SETTINGS_MICROPHONE" on-tap="onTapNavigate_"
actionable>
<iron-icon icon="settings:mic"></iron-icon>
@@ -96,7 +97,7 @@
aria-label="$i18n{siteSettingsMic}"
aria-describedby="micSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="notifications" class="settings-box two-line"
category$="[[ContentSettingsTypes.NOTIFICATIONS]]"
data-route="SITE_SETTINGS_NOTIFICATIONS" on-tap="onTapNavigate_"
actionable>
@@ -114,14 +115,14 @@
aria-label="$i18n{siteSettingsNotifications}"
aria-describedby="notificationsSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="javascript" class="settings-box two-line"
category$="[[ContentSettingsTypes.JAVASCRIPT]]"
data-route="SITE_SETTINGS_JAVASCRIPT" on-tap="onTapNavigate_"
actionable>
- <iron-icon icon="settings:input"></iron-icon>
+ <iron-icon icon="settings:code"></iron-icon>
<div class="middle">
$i18n{siteSettingsJavascript}
- <div class="secondary" is="javascriptSecondary">
+ <div class="secondary" id="javascriptSecondary">
[[defaultSettingLabel_(
default_.javascript,
'$i18nPolymer{siteSettingsAllowed}',
@@ -132,7 +133,7 @@
aria-label="$i18n{siteSettingsJavascript}"
aria-describedby="javascriptSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="flash" class="settings-box two-line"
category$="[[ContentSettingsTypes.PLUGINS]]"
data-route="SITE_SETTINGS_FLASH" on-tap="onTapNavigate_" actionable>
<iron-icon icon="cr:extension"></iron-icon>
@@ -150,7 +151,7 @@
aria-label="$i18n{siteSettingsFlash}"
aria-describedby="flashSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="images" class="settings-box two-line"
category$="[[ContentSettingsTypes.IMAGES]]"
data-route="SITE_SETTINGS_IMAGES" on-tap="onTapNavigate_" actionable>
<iron-icon icon="settings:photo"></iron-icon>
@@ -167,7 +168,7 @@
aria-label="$i18n{siteSettingsImages}"
aria-describedby="imagesSecondary"></button>
</div>
- <div category$="[[ContentSettingsTypes.POPUPS]]"
+ <div id="popups" category$="[[ContentSettingsTypes.POPUPS]]"
class="settings-box two-line" data-route="SITE_SETTINGS_POPUPS"
on-tap="onTapNavigate_" actionable>
<iron-icon icon="cr:open-in-new"></iron-icon>
@@ -184,7 +185,27 @@
aria-label="$i18n{siteSettingsPopups}"
aria-describedby="popupsSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <template is="dom-if" if="[[enableSafeBrowsingSubresourceFilter_]]">
+ <div id="subresource-filter" class="settings-box two-line"
+ category$="[[ContentSettingsTypes.SUBRESOURCE_FILTER]]"
+ data-route="SITE_SETTINGS_SUBRESOURCE_FILTER" on-tap="onTapNavigate_"
+ actionable>
+ <iron-icon icon="cr:open-in-new"></iron-icon>
+ <div class="middle">
+ $i18n{siteSettingsSubresourceFilter}
+ <div class="secondary" id="subresourceFilterSecondary">
+ [[defaultSettingLabel_(
+ default_.subresourceFilter,
+ '$i18nPolymer{siteSettingsSubresourceFilterBlock}',
+ '$i18nPolymer{siteSettingsSubresourceFilterAllow}')]]
+ </div>
+ </div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{siteSettingsSubresourceFilter}"
+ aria-describedby="subresourceFilterSecondary"></button>
+ </div>
+ </template>
+ <div id="background-sync" class="settings-box two-line"
category$="[[ContentSettingsTypes.BACKGROUND_SYNC]]"
data-route="SITE_SETTINGS_BACKGROUND_SYNC" on-tap="onTapNavigate_"
actionable>
@@ -202,7 +223,7 @@
aria-label="$i18n{siteSettingsBackgroundSync}"
aria-describedby="backgroundSyncSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="automatic-downloads" class="settings-box two-line"
category$="[[ContentSettingsTypes.AUTOMATIC_DOWNLOADS]]"
data-route="SITE_SETTINGS_AUTOMATIC_DOWNLOADS"
on-tap="onTapNavigate_" actionable>
@@ -220,7 +241,7 @@
aria-label="$i18n{siteSettingsAutomaticDownloads}"
aria-describedby="automaticDownloadsSecondary"></button>
</div>
- <div class="settings-box two-line"
+ <div id="unsandboxed-plugins" class="settings-box two-line"
category$="[[ContentSettingsTypes.UNSANDBOXED_PLUGINS]]"
data-route="SITE_SETTINGS_UNSANDBOXED_PLUGINS"
on-tap="onTapNavigate_" actionable>
@@ -239,7 +260,7 @@
aria-describedby="unsandboxedPluginsSecondary"></button>
</div>
<template is="dom-if" if="[[!isGuest_]]">
- <div class="settings-box two-line"
+ <div id="protocol-handlers" class="settings-box two-line"
category$="[[ContentSettingsTypes.PROTOCOL_HANDLERS]]"
data-route="SITE_SETTINGS_HANDLERS"
on-tap="onTapNavigate_" actionable>
@@ -258,11 +279,11 @@
aria-describedby="handlersSecondary"></button>
</div>
</template>
- <div class="settings-box two-line"
+ <div id="midi-devices" class="settings-box two-line"
category$="[[ContentSettingsTypes.MIDI_DEVICES]]"
data-route="SITE_SETTINGS_MIDI_DEVICES"
on-tap="onTapNavigate_" actionable>
- <iron-icon icon="settings:music-note"></iron-icon>
+ <iron-icon icon="settings:midi"></iron-icon>
<div class="middle">
$i18n{siteSettingsMidiDevices}
<div class="secondary" id="midiDevicesSecondary">
@@ -273,33 +294,38 @@
</div>
</div>
<button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{siteSettingsMidiDevices}"></button>
+ aria-label="$i18n{siteSettingsMidiDevices}"
+ aria-describedby="midiDevicesSecondary"></button>
</div>
- <div class="settings-box" category$="[[ContentSettingsTypes.ZOOM_LEVELS]]"
- data-route="SITE_SETTINGS_ZOOM_LEVELS"
- on-tap="onTapNavigate_" actionable>
+ <div id="zoom-levels" class="settings-box"
+ category$="[[ContentSettingsTypes.ZOOM_LEVELS]]"
+ data-route="SITE_SETTINGS_ZOOM_LEVELS" on-tap="onTapNavigate_"
+ actionable>
<iron-icon icon="settings:zoom-in"></iron-icon>
<div class="middle">$i18n{siteSettingsZoomLevels}</div>
<button class="subpage-arrow" is="paper-icon-button-light"
aria-label="$i18n{siteSettingsZoomLevels}"></button>
</div>
- <div class="settings-box" category$="[[ContentSettingsTypes.USB_DEVICES]]"
- data-route="SITE_SETTINGS_USB_DEVICES"
- on-tap="onTapNavigate_" actionable>
+ <div id="usb-devices" class="settings-box"
+ category$="[[ContentSettingsTypes.USB_DEVICES]]"
+ data-route="SITE_SETTINGS_USB_DEVICES" on-tap="onTapNavigate_"
+ actionable>
<iron-icon icon="settings:usb"></iron-icon>
<div class="middle">$i18n{siteSettingsUsbDevices}</div>
<button class="subpage-arrow" is="paper-icon-button-light"
aria-label="$i18n{siteSettingsUsbDevices}"></button>
</div>
- <div class="settings-box" data-route="SITE_SETTINGS_PDF_DOCUMENTS"
- on-tap="onTapNavigate_" actionable>
+ <div id="pdf-documents" class="settings-box"
+ data-route="SITE_SETTINGS_PDF_DOCUMENTS" on-tap="onTapNavigate_"
+ actionable>
<iron-icon icon="settings:pdf"></iron-icon>
<div class="middle">$i18n{siteSettingsPdfDocuments}</div>
<button class="subpage-arrow" is="paper-icon-button-light"
aria-label="$i18n{siteSettingsPdfDocuments}"></button>
</div>
- <div class="settings-box" data-route="SITE_SETTINGS_PROTECTED_CONTENT"
- on-tap="onTapNavigate_" actionable>
+ <div id="protected-content" class="settings-box"
+ data-route="SITE_SETTINGS_PROTECTED_CONTENT" on-tap="onTapNavigate_"
+ actionable>
<iron-icon icon="settings:security"></iron-icon>
<div class="middle">$i18n{siteSettingsProtectedContent}</div>
<button class="subpage-arrow" is="paper-icon-button-light"
diff --git a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
index 1ef6a1fef40..a3d54f28062 100644
--- a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
+++ b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -40,6 +40,62 @@ Polymer({
type: Boolean,
value: function() { return loadTimeData.getBoolean('isGuest'); }
},
+
+ /** @private */
+ enableSafeBrowsingSubresourceFilter_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('enableSafeBrowsingSubresourceFilter');
+ }
+ },
+
+ /** @type {!Map<string, string>} */
+ focusConfig: {
+ type: Object,
+ observer: 'focusConfigChanged_',
+ },
+ },
+
+ /**
+ * @param {!Map<string, string>} newConfig
+ * @param {?Map<string, string>} oldConfig
+ * @private
+ */
+ focusConfigChanged_: function(newConfig, oldConfig) {
+ // focusConfig is set only once on the parent, so this observer should only
+ // fire once.
+ assert(!oldConfig);
+
+ // Populate the |focusConfig| map of the parent <settings-animated-pages>
+ // element, with additional entries that correspond to subpage trigger
+ // elements residing in this element's Shadow DOM.
+ var R = settings.Route;
+ [
+ [R.SITE_SETTINGS_COOKIES, 'cookies'],
+ [R.SITE_SETTINGS_LOCATION, 'location'],
+ [R.SITE_SETTINGS_CAMERA, 'camera'],
+ [R.SITE_SETTINGS_MICROPHONE, 'microphone'],
+ [R.SITE_SETTINGS_NOTIFICATIONS, 'notifications'],
+ [R.SITE_SETTINGS_JAVASCRIPT,'javascript'],
+ [R.SITE_SETTINGS_FLASH,'flash'],
+ [R.SITE_SETTINGS_IMAGES,'images'],
+ [R.SITE_SETTINGS_POPUPS,'popups'],
+ [R.SITE_SETTINGS_BACKGROUND_SYNC,'background-sync'],
+ [R.SITE_SETTINGS_AUTOMATIC_DOWNLOADS,'automatic-downloads'],
+ [R.SITE_SETTINGS_UNSANDBOXED_PLUGINS,'unsandboxed-plugins'],
+ [R.SITE_SETTINGS_HANDLERS,'protocol-handlers'],
+ [R.SITE_SETTINGS_MIDI_DEVICES,'midi-devices'],
+ [R.SITE_SETTINGS_SUBRESOURCE_FILTER,'subresource-filter'],
+ [R.SITE_SETTINGS_ZOOM_LEVELS,'zoom-levels'],
+ [R.SITE_SETTINGS_USB_DEVICES,'usb-devices'],
+ [R.SITE_SETTINGS_PDF_DOCUMENTS,'pdf-documents'],
+ [R.SITE_SETTINGS_PROTECTED_CONTENT,'protected-content'],
+ ].forEach(function(pair) {
+ var route = pair[0];
+ var id = pair[1];
+ this.focusConfig.set(
+ route.path, '* /deep/ #' + id + ' .subpage-arrow');
+ }.bind(this));
},
/** @override */
diff --git a/chromium/chrome/browser/resources/settings/system_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/system_page/compiled_resources2.gyp
index c9a14f8a0d3..748399f4190 100644
--- a/chromium/chrome/browser/resources/settings/system_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/system_page/compiled_resources2.gyp
@@ -17,6 +17,7 @@
'dependencies': [
'../compiled_resources2.gyp:lifetime_browser_proxy',
'system_page_browser_proxy',
+ '<(EXTERNS_GYP):settings_private',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/settings/system_page/system_page.html b/chromium/chrome/browser/resources/settings/system_page/system_page.html
index 6cd6aa205c3..41a4fb6f407 100644
--- a/chromium/chrome/browser/resources/settings/system_page/system_page.html
+++ b/chromium/chrome/browser/resources/settings/system_page/system_page.html
@@ -1,6 +1,7 @@
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="../controls/controlled_button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../controls/extension_controlled_indicator.html">
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../lifetime_browser_proxy.html">
@@ -31,11 +32,17 @@
</template>
</settings-toggle-button>
</div>
- <div class="settings-box">
- <controlled-button class="primary-button" pref="[[prefs.proxy]]"
- on-tap="onChangeProxySettingsTap_">
- $i18n{changeProxySettings}
- </controlled-button>
+ <div id="proxy" class="settings-box" on-tap="onProxyTap_"
+ actionable$="[[!isProxyEnforcedByPolicy_]]">
+ <div class="start">$i18n{proxySettingsLabel}</div>
+ <button is="paper-icon-button-light" class="icon-external"
+ aria-label="$i18n{proxySettingsLabel}"
+ hidden$="[[isProxyEnforcedByPolicy_]]"></button>
+ <template is="dom-if" if="[[isProxyEnforcedByPolicy_]]">
+ <cr-policy-pref-indicator pref="[[prefs.proxy]]"
+ icon-aria-label="$i18n{proxySettingsLabel}">
+ </cr-policy-pref-indicator>
+ </template>
</div>
<template is="dom-if" if="[[prefs.proxy.extensionId]]">
<div class="settings-box continuation">
diff --git a/chromium/chrome/browser/resources/settings/system_page/system_page.js b/chromium/chrome/browser/resources/settings/system_page/system_page.js
index d076182bcb8..b03f680f092 100644
--- a/chromium/chrome/browser/resources/settings/system_page/system_page.js
+++ b/chromium/chrome/browser/resources/settings/system_page/system_page.js
@@ -15,21 +15,23 @@ Polymer({
type: Object,
notify: true,
},
+
+ /** @private */
+ isProxyEnforcedByPolicy_: {
+ type: Boolean,
+ computed: 'computeIsProxyEnforcedByPolicy_(prefs.proxy.*)',
+ },
},
/**
- * @param {boolean} enabled Whether hardware acceleration is currently
- * enabled.
+ * @return {boolean}
* @private
*/
- shouldShowRestart_: function(enabled) {
- var proxy = settings.SystemPageBrowserProxyImpl.getInstance();
- return enabled != proxy.wasHardwareAccelerationEnabledAtStartup();
- },
-
- /** @private */
- onChangeProxySettingsTap_: function() {
- settings.SystemPageBrowserProxyImpl.getInstance().changeProxySettings();
+ computeIsProxyEnforcedByPolicy_: function() {
+ var pref = this.get('prefs.proxy');
+ // TODO(dbeam): do types of policy other than USER apply on ChromeOS?
+ return pref.enforcement == chrome.settingsPrivate.Enforcement.ENFORCED &&
+ pref.controlledBy == chrome.settingsPrivate.ControlledBy.USER_POLICY;
},
/** @private */
@@ -43,8 +45,24 @@ Polymer({
},
/** @private */
+ onProxyTap_: function() {
+ if (!this.isProxyEnforcedByPolicy_)
+ settings.SystemPageBrowserProxyImpl.getInstance().showProxySettings();
+ },
+
+ /** @private */
onRestartTap_: function() {
// TODO(dbeam): we should prompt before restarting the browser.
settings.LifetimeBrowserProxyImpl.getInstance().restart();
},
+
+ /**
+ * @param {boolean} enabled Whether hardware acceleration is currently
+ * enabled.
+ * @private
+ */
+ shouldShowRestart_: function(enabled) {
+ var proxy = settings.SystemPageBrowserProxyImpl.getInstance();
+ return enabled != proxy.wasHardwareAccelerationEnabledAtStartup();
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js b/chromium/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js
index e3c78236517..b9ac51b3328 100644
--- a/chromium/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/system_page/system_page_browser_proxy.js
@@ -9,8 +9,8 @@ cr.define('settings', function() {
function SystemPageBrowserProxy() {}
SystemPageBrowserProxy.prototype = {
- /** Allows the user to change native system proxy settings. */
- changeProxySettings: function() {},
+ /** Shows the native system proxy settings. */
+ showProxySettings: function() {},
/**
* @return {boolean} Whether hardware acceleration was enabled when the user
@@ -29,8 +29,8 @@ cr.define('settings', function() {
SystemPageBrowserProxyImpl.prototype = {
/** @override */
- changeProxySettings: function() {
- chrome.send('changeProxySettings');
+ showProxySettings: function() {
+ chrome.send('showProxySettings');
},
/** @override */
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
index ca7b87ef1da..ca47f6a9bf4 100644
--- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
+++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
@@ -1,9 +1,11 @@
<!doctype html>
-<html i18n-values="dir:textdirection;lang:language">
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
<link rel="import" href="chrome://resources/html/polymer.html">
+ <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+ <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="signin_shared_css.html">
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
@@ -15,6 +17,20 @@
-webkit-margin-start: 0;
}
</if>
+ /* TODO(dbeam): de-duplicate this style with MD Settings. */
+ paper-checkbox {
+ --paper-checkbox-checked-color: var(--google-blue-500);
+ --paper-checkbox-label-color: inherit;
+ --paper-checkbox-label-spacing: 22px;
+ --paper-checkbox-size: 16px;
+ --paper-checkbox-unchecked-color: var(--paper-grey-600);
+ -webkit-margin-start: 2px;
+ }
+<if expr="is_macosx">
+ html:not(.focus-allowed) paper-checkbox {
+ --paper-checkbox-ink-size: 0;
+ }
+</if>
</style>
</head>
<body>
@@ -56,8 +72,9 @@
<div id="chrome-logo" class="logo"></div>
<div>
<div class="title">$i18n{syncConfirmationChromeSyncTitle}</div>
- <div class="body text"
- i18n-values=".innerHTML:syncConfirmationChromeSyncBody"></div>
+ <div class="body text">
+ $i18nRaw{syncConfirmationChromeSyncBody}
+ </div>
</div>
</div>
<div class="message-container">
@@ -76,8 +93,10 @@
</div>
</div>
<div class="message-container">
- <div class="body"
- i18n-values=".innerHTML:syncConfirmationSyncSettingsLinkBody">
+ <div class="body">
+ <paper-checkbox id="configure-before-signing-in">
+ $i18n{syncConfirmationSyncSettingsLabel}
+ </paper-checkbox>
</div>
</div>
</div>
@@ -99,5 +118,4 @@
<script src="chrome://resources/js/util.js"></script>
<script src="sync_confirmation.js"></script>
<script src="chrome://sync-confirmation/strings.js"></script>
- <script src="chrome://resources/js/i18n_template.js"></script>
</html>
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
index 1f51ec8fdb4..53d68539b61 100644
--- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
+++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
@@ -6,23 +6,18 @@ cr.define('sync.confirmation', function() {
'use strict';
function onConfirm(e) {
- chrome.send('confirm');
+ chrome.send('confirm', [$('configure-before-signing-in').checked]);
}
function onUndo(e) {
chrome.send('undo');
}
- function onGoToSettings(e) {
- chrome.send('goToSettings');
- }
-
function initialize() {
document.addEventListener('keydown', onKeyDown);
$('confirmButton').addEventListener('click', onConfirm);
$('undoButton').addEventListener('click', onUndo);
if (loadTimeData.getBoolean('isSyncAllowed')) {
- $('settingsLink').addEventListener('click', onGoToSettings);
$('profile-picture').addEventListener('load', onPictureLoaded);
$('syncDisabledDetails').hidden = true;
} else {
@@ -37,6 +32,7 @@ cr.define('sync.confirmation', function() {
function clearFocus() {
document.activeElement.blur();
+ document.documentElement.classList.add('focus-allowed');
}
function setUserImageURL(url) {
@@ -56,7 +52,7 @@ cr.define('sync.confirmation', function() {
// on "enter" being pressed and the user hits "enter", perform the default
// action of the dialog, which is "OK, Got It".
if (e.key == 'Enter' &&
- !/^(A|PAPER-BUTTON)$/.test(document.activeElement.tagName)) {
+ !/^(A|PAPER-(BUTTON|CHECKBOX))$/.test(document.activeElement.tagName)) {
$('confirmButton').click();
e.preventDefault();
}
diff --git a/chromium/chrome/browser/resources/snippets_internals.js b/chromium/chrome/browser/resources/snippets_internals.js
index 7f623668eb0..6e8bbe94c78 100644
--- a/chromium/chrome/browser/resources/snippets_internals.js
+++ b/chromium/chrome/browser/resources/snippets_internals.js
@@ -15,7 +15,7 @@ cr.define('chrome.SnippetsInternals', function() {
});
$('submit-dump').addEventListener('click', function(event) {
- downloadJson(JSON.stringify(lastSuggestions));
+ downloadJson(JSON.stringify(lastSuggestions, null, 2));
event.preventDefault();
});
@@ -125,7 +125,7 @@ cr.define('chrome.SnippetsInternals', function() {
// create a link with download attribute and simulate a click, instead.)
var link = document.createElement('a');
link.download = 'snippets.json';
- link.href = 'data:,' + json;
+ link.href = 'data:application/json,' + encodeURI(json);
link.click();
}
diff --git a/chromium/chrome/browser/resources/uber/OWNERS b/chromium/chrome/browser/resources/uber/OWNERS
index 262db997c92..8624e36b003 100644
--- a/chromium/chrome/browser/resources/uber/OWNERS
+++ b/chromium/chrome/browser/resources/uber/OWNERS
@@ -1,2 +1,4 @@
dbeam@chromium.org
estade@chromium.org
+
+# COMPONENT: UI>Browser>WebUI
diff --git a/chromium/chrome/browser/resources/unpack_pak.py b/chromium/chrome/browser/resources/unpack_pak.py
index ce6a993f7ed..46692798eee 100755
--- a/chromium/chrome/browser/resources/unpack_pak.py
+++ b/chromium/chrome/browser/resources/unpack_pak.py
@@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import argparse
import os
import re
import sys
@@ -51,3 +52,16 @@ def unpack(pak_path, out_path):
os.makedirs(dirname)
with open(os.path.join(out_path, filename), 'w') as file:
file.write(text)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--pak_file')
+ parser.add_argument('--out_folder')
+ args = parser.parse_args()
+
+ unpack(args.pak_file, args.out_folder)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/chrome/browser/resources/vr_shell/OWNERS b/chromium/chrome/browser/resources/vr_shell/OWNERS
deleted file mode 100644
index 4df2af80929..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-bshe@chromium.org
-girard@chromium.org
-mthiesse@chromium.org
-cjgrant@chromium.org
diff --git a/chromium/chrome/browser/resources/vr_shell/compiled_resources2.gyp b/chromium/chrome/browser/resources/vr_shell/compiled_resources2.gyp
deleted file mode 100644
index 3c01fc12dc3..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/compiled_resources2.gyp
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
- 'targets': [
- {
- 'target_name': 'vr_shell_ui_api',
- 'dependencies': [
- '<(EXTERNS_GYP):chrome_send',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'vr_shell_ui_scene',
- 'dependencies': [
- 'vr_shell_ui_api',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'vk',
- 'dependencies': [
- 'vr_shell_ui_api',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'vr_shell_ui',
- 'dependencies': [
- 'vr_shell_ui_api',
- 'vr_shell_ui_scene',
- 'vk',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- ],
-}
diff --git a/chromium/chrome/browser/resources/vr_shell/vk.css b/chromium/chrome/browser/resources/vr_shell/vk.css
deleted file mode 100644
index 4604f4d0ccd..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/vk.css
+++ /dev/null
@@ -1,124 +0,0 @@
-/* Copyright 2017 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-.inputview-container {
- float: left;
- font-family: Roboto2, Roboto, 'Noto Sans', sans-serif;
- height: 340px;
- user-select: none;
- width: 1228px;
-}
-
-.inputview-spacerview {
- display: inline-block;
- float: left;
- overflow: hidden;
- padding: 32px;
- position: relative;
-}
-
-.inputview-layoutview {
- background-color: rgb(71, 71, 71);
- border: 2px solid rgb(128, 128, 128);
- border-radius: 10px;
- display: inline-block;
- float: left;
- overflow: hidden;
- padding: 32px;
- position: relative;
-}
-
-.inputview-softkey-view {
- box-sizing: border-box;
- display: inline-block;
- overflow: hidden;
- padding: 3px 2px;
-}
-
-.inputview-softkey {
- background-color: rgb(71, 71, 71);
- border-radius: 5px;
- display: block;
- height: 100%;
- position: relative;
- width: 100%;
-}
-
-.inputview-softkey:hover {
- background-color: rgb(110, 112, 114);
-}
-
-.inputview-softkey:active {
- background-color: rgb(90, 93, 95);
-}
-
-.inputview-softkey-spacer:hover {
- background-color: inherit;
-}
-
-.inputview-ch {
- color: rgba(236, 236, 236, 0.8);
- display: inline-block;
- font-size: 30px;
- position: absolute;
- text-align: center;
- top: 15%;
- width: 100%;
-}
-
-.inputview-ch {
- display: block;
-}
-
-.inputview-level {
- display: none;
-}
-
-.inputview-active-level-0 .inputview-level-0,
-.inputview-active-level-1 .inputview-level-1,
-.inputview-active-level-2 .inputview-level-2,
-.inputview-active-level-3 .inputview-level-3 {
- display: block;
-}
-
-.vk-icon {
- display: block;
- left: 50%;
- position: absolute;
- top: 50%;
-}
-
-.vk-escape-icon {
- background: url(../../../../ui/webui/resources/images/hidekeyboard.svg)
- transparent no-repeat 0 0/32px 32px;
- height: 32px;
- margin: -16px 0 0 -16px;
- width: 32px;
-}
-
-.vk-backspace-icon {
- background: url(../../../../ui/webui/resources/images/backspace.svg)
- transparent no-repeat 0 0/24px 24px;
- height: 24px;
- margin: -12px 0 0 -12px;
- width: 24px;
-}
-
-.vk-space-icon {
- background-color: rgba(165, 161, 169, 0.35);
- border-radius: 40px;
- height: 100%;
- left: 0;
- top: 0;
- width: 100%;
-}
-
-.inputview-code-space:hover {
- background-color: rgba(165, 161, 169, 0.35);
- border-radius: 40px;
-}
-.inputview-code-space:active {
- background-color: rgb(90, 93, 95);
-}
-
diff --git a/chromium/chrome/browser/resources/vr_shell/vk.js b/chromium/chrome/browser/resources/vr_shell/vk.js
deleted file mode 100644
index 8159bbf4863..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/vk.js
+++ /dev/null
@@ -1,437 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var vrShellVK = (function() {
- /** @const */ var VK_L_PANEL_LAYOUT = [
- [
- {'code': 'Key1', 'key': '1'},
- {'code': 'Key2', 'key': '2'},
- {'code': 'Key3', 'key': '3'},
- ],
- [
- {'code': 'Key4', 'key': '4'},
- {'code': 'Key5', 'key': '5'},
- {'code': 'Key6', 'key': '6'},
- ],
- [
- {'code': 'Key7', 'key': '7'},
- {'code': 'Key8', 'key': '8'},
- {'code': 'Key9', 'key': '9'},
- ],
- [
- {'code': 'KeyNegative', 'key': '-'},
- {'code': 'Key0', 'key': '0'},
- {'code': 'KeyPoint', 'key': '.'},
- ]
- ];
-
- /** @const */ var VK_R_PANEL_LAYOUT = [
- [
- {
- 'code': 'Backspace',
- 'key': 'Backspace',
- 'image-class': 'vk-backspace-icon'
- },
- ],
- [
- {
- 'code': 'Enter',
- 'key': 'Enter',
- 'height': 2.0,
- 'text' : '\u{021B2}',
- },
- ],
- [
- {
- 'code': 'Abort',
- 'key': 'Escape',
- 'image-class': 'vk-escape-icon',
- 'action': vkHide
- },
- ],
- ];
-
- /** @const */ var VK_LAYOUTS = {
- 'en-us-compact': {
- 'levels': [
- [
- // Level 0: Unshifted.
- [
- {'code': 'KeyQ', 'key': 'q'},
- {'code': 'KeyW', 'key': 'w'},
- {'code': 'KeyE', 'key': 'e'},
- {'code': 'KeyR', 'key': 'r'},
- {'code': 'KeyT', 'key': 't'},
- {'code': 'KeyY', 'key': 'y'},
- {'code': 'KeyU', 'key': 'u'},
- {'code': 'KeyI', 'key': 'i'},
- {'code': 'KeyO', 'key': 'o'},
- {'code': 'KeyP', 'key': 'p'},
- ],
- [
- {'width': 0.5, 'display': 'spacer'},
- {'code': 'KeyA', 'key': 'a'},
- {'code': 'KeyS', 'key': 's'},
- {'code': 'KeyD', 'key': 'd'},
- {'code': 'KeyF', 'key': 'f'},
- {'code': 'KeyG', 'key': 'g'},
- {'code': 'KeyH', 'key': 'h'},
- {'code': 'KeyJ', 'key': 'j'},
- {'code': 'KeyK', 'key': 'k'},
- {'code': 'KeyL', 'key': 'l'},
- ],
- [
- {
- 'code': 'ShiftLeft',
- 'key': 'Shift',
- 'text' : '\u{021E7}',
- 'action': vkLevel,
- 'level': 1
- },
- {'code': 'KeyZ', 'key': 'z'},
- {'code': 'KeyX', 'key': 'x'},
- {'code': 'KeyC', 'key': 'c'},
- {'code': 'KeyV', 'key': 'v'},
- {'code': 'KeyB', 'key': 'b'},
- {'code': 'KeyN', 'key': 'n'},
- {'code': 'KeyM', 'key': 'm'},
- {'code': '', 'key': '!'},
- {'code': '', 'key': '?'},
- ],
- [
- {
- 'code': 'AltRight',
- 'key': 'AltGraph',
- 'text': '=\\<',
- 'action': vkLevel,
- 'level': 2
- },
- {'code': 'Slash', 'key': '/'},
- {
- 'code': 'space',
- 'key': ' ',
- 'width': 6.00,
- 'image-class': 'vk-space-icon'
- },
- {'code': 'Comma', 'key': ','},
- {'code': 'Period', 'key': '.'},
- ]
- ],
- [
- // Level 1: Shifted.
- [
- {'code': 'KeyQ', 'key': 'Q'},
- {'code': 'KeyW', 'key': 'W'},
- {'code': 'KeyE', 'key': 'E'},
- {'code': 'KeyR', 'key': 'R'},
- {'code': 'KeyT', 'key': 'T'},
- {'code': 'KeyY', 'key': 'Y'},
- {'code': 'KeyU', 'key': 'U'},
- {'code': 'KeyI', 'key': 'I'},
- {'code': 'KeyO', 'key': 'O'},
- {'code': 'KeyP', 'key': 'P'},
- ],
- [
- {'width': 0.5, 'display': 'spacer'},
- {'code': 'KeyA', 'key': 'A'},
- {'code': 'KeyS', 'key': 'S'},
- {'code': 'KeyD', 'key': 'D'},
- {'code': 'KeyF', 'key': 'F'},
- {'code': 'KeyG', 'key': 'G'},
- {'code': 'KeyH', 'key': 'H'},
- {'code': 'KeyJ', 'key': 'J'},
- {'code': 'KeyK', 'key': 'K'},
- {'code': 'KeyL', 'key': 'L'},
- ],
- [
- {
- 'code': 'ShiftLeft',
- 'key': 'Shift',
- 'text' : '\u{021E7}',
- 'action': vkLevel,
- 'level': 0,
- },
- {'code': 'KeyZ', 'key': 'Z'},
- {'code': 'KeyX', 'key': 'X'},
- {'code': 'KeyC', 'key': 'C'},
- {'code': 'KeyV', 'key': 'V'},
- {'code': 'KeyB', 'key': 'B'},
- {'code': 'KeyN', 'key': 'N'},
- {'code': 'KeyM', 'key': 'M'},
- {'code': '', 'key': '!'},
- {'code': '', 'key': '?'},
- ],
- [
- {
- 'code': 'AltRight',
- 'key': 'AltGraph',
- 'text': '=\\<',
- 'action': vkLevel,
- 'level': 2
- },
- {'code': 'Slash', 'key': '/'},
- {
- 'code': 'space',
- 'key': ' ',
- 'width': 6.00,
- 'image-class': 'vk-space-icon'
- },
- {'code': 'Comma', 'key': ','},
- {'code': 'Period', 'key': '.'},
- ]
- ],
- [
- // Level 2: Symbols.
- [
- {'code': 'KeyQ', 'key': '!'},
- {'code': 'KeyW', 'key': '@'},
- {'code': 'KeyE', 'key': '#'},
- {'code': 'KeyR', 'key': '$'},
- {'code': 'KeyT', 'key': '%'},
- {'code': 'KeyY', 'key': '^'},
- {'code': 'KeyU', 'key': '&'},
- {'code': 'KeyI', 'key': '*'},
- {'code': 'KeyO', 'key': '('},
- {'code': 'KeyP', 'key': ')'},
- ],
- [
- {'width': 0.5, 'display': 'spacer'},
- {'code': 'KeyA', 'key': '~'},
- {'code': 'KeyS', 'key': '`'},
- {'code': 'KeyD', 'key': '|'},
- {'code': 'KeyF', 'key': '{'},
- {'code': 'KeyG', 'key': '}'},
- {'code': 'KeyH', 'key': '['},
- {'code': 'KeyJ', 'key': ']'},
- {'code': 'KeyK', 'key': '-'},
- {'code': 'KeyL', 'key': '_'},
- ],
- [
- {'code': 'ShiftLeft', 'key': '/'},
- {'code': 'KeyZ', 'key': '\\'},
- {'code': 'KeyX', 'key': '+'},
- {'code': 'KeyC', 'key': '='},
- {'code': 'KeyV', 'key': ':'},
- {'code': 'KeyB', 'key': ';'},
- {'code': 'KeyN', 'key': '\''},
- {'code': 'KeyM', 'key': '<'},
- {'key': '>'},
- {'key': '"'},
- ],
- [
- {
- 'code': 'AltRight',
- 'key': 'AltGraph',
- 'text': 'ABC',
- 'action': vkLevel,
- 'level': 0,
- },
- {'code': 'Slash', 'key': '/'},
- {
- 'code': 'space',
- 'key': ' ',
- 'width': 6.00,
- 'image-class': 'vk-space-icon'
- },
- {'code': 'Comma', 'key': ','},
- {'code': 'Period', 'key': '.'},
- ]
- ]
- ]
- }
- };
-
- /** @const */ var VK_BUTTON_SIZE = [64, 64, 'px'];
-
- var vkState = {'query': {'language': 'en-us', 'layout': 'compact'}};
-
- function vkHide(button) {
- // TODO(asimjour): Send a key event to support vkHide.
- }
-
- function vkLevel(button) {
- vkCh(button);
- vkActivateLevel(button.level);
- }
-
- function vkLevel0(button) {
- vkCh(button);
- vkActivateLevel(0);
- }
-
- function vkCh(button) {
- if (button.key || button.code) {
- // TODO(asimjour): Change the focus to the omnibox.
- if (button.code != 'AltRight')
- sendKey('key', button.code, button.key);
- if (vkState.level == 1)
- vkActivateLevel(0);
- }
- }
-
- function vkOnClick(e) {
- var button = e.vkButtonData;
- button.action(button);
- }
-
- function vkActivateLevel(n) {
- vkState.view.classList.remove('inputview-active-level-' + vkState.level);
- vkState.level = n;
- vkState.view.classList.add('inputview-active-level-' + vkState.level);
- }
-
- function vkNormalizeButtonData(buttonData) {
- if (!buttonData.text) {
- if (buttonData.key && !buttonData['image-class'])
- buttonData.text = buttonData.key;
- else
- buttonData.text = null;
- }
- buttonData.action = buttonData.action || vkCh;
- buttonData.width = buttonData.width || 1.00;
- buttonData.height = buttonData.height || 1.00;
-
- if (buttonData.display)
- buttonData.display = 'inputview-softkey-' + buttonData.display;
- else if (buttonData['image-class'])
- buttonData.display = 'inputview-softkey-0';
- else if (buttonData.text)
- buttonData.display = 'inputview-softkey-1';
- else
- buttonData.display = 'inputview-softkey-none';
-
- buttonData.styleWidth =
- (buttonData.width * VK_BUTTON_SIZE[0]) + VK_BUTTON_SIZE[2];
- buttonData.styleHeight =
- (buttonData.height * VK_BUTTON_SIZE[1]) + VK_BUTTON_SIZE[2];
- return buttonData;
- }
-
- function vkMkButton(index, buttonData) {
- var button = document.createElement('div');
-
- buttonData = vkNormalizeButtonData(buttonData);
- button.vkButtonData = buttonData
- button.classList.add('inputview-softkey-view');
- button.style.width = buttonData.styleWidth;
- button.style.height = buttonData.styleHeight;
- button.onclick = function() {
- vkOnClick(button);
- };
-
- var key = document.createElement('div');
- key.classList.add('inputview-softkey', buttonData.display);
- if (button.vkButtonData.code)
- key.classList.add('inputview-code-' + buttonData.code);
- var keyContent = key;
- if (button.vkButtonData['image-class']) {
- keyContent = document.createElement('div');
- keyContent.classList.add(button.vkButtonData['image-class'], 'vk-icon');
- key.appendChild(keyContent);
- }
- if (button.vkButtonData.class)
- keyContent.classList.add(button.vkButtonData.class);
-
- if (buttonData.text) {
- var charKey = document.createElement('div');
- charKey.classList.add('inputview-ch');
- charKey.textContent = buttonData.text;
- keyContent.appendChild(charKey);
- }
-
- button.appendChild(key);
- return button;
- }
-
- function vkMkRow(index, rowData) {
- var row = document.createElement('div');
- row.id = 'row' + index;
- row.classList.add('inputview-row');
- for (var c = 0; c < rowData.length; ++c)
- row.appendChild(vkMkButton(c, rowData[c]));
- return row;
- }
-
- function vkMkLevel(index, levelData) {
- var level = document.createElement('div');
- level.id = 'level' + index;
- level.classList.add('inputview-level', 'inputview-level-' + index);
- for (var r = 0; r < levelData.length; ++r)
- level.appendChild(vkMkRow(r, levelData[r]));
- return level;
- }
-
- function vkMkKb(view, layout) {
- vkState.view = view;
- vkState.layout = layout;
- vkState.levels = layout.levels.length;
- for (var key = 0; key < layout.levels.length; ++key)
- view.appendChild(vkMkLevel(key, vkState.layout.levels[key]));
- }
-
- function vkMkPanel(view, lPanelData) {
- for (var r = 0; r < lPanelData.length; ++r)
- view.appendChild(vkMkRow(r, lPanelData[r]));
- }
-
- function vkOnLoad() {
- // Build keyboard.
- vkState.layoutName = vkState.query.language + '-' + vkState.query.layout;
- vkMkKb(
- document.querySelector('#keyboardView'),
- VK_LAYOUTS[vkState.layoutName]);
- vkMkPanel(document.querySelector('#numberView'), VK_L_PANEL_LAYOUT);
- vkMkPanel(document.querySelector('#specialkeyView'), VK_R_PANEL_LAYOUT);
-
- vkActivateLevel(0);
- }
-
- // Flag values for ctrl, alt and shift as defined by EventFlags
- // in "event_constants.h".
- // @enum {number}
- var Modifier = {NONE: 0, ALT: 8, CONTROL: 4, SHIFT: 2};
-
- /** @const */ var DOM_KEYS = {
- 'Backspace': 0x08,
- 'Enter': 0x0D,
- 'Escape': 0x1B,
- 'AltGraph': 0x200103,
- };
-
- function domKeyValue(key) {
- if (key) {
- if (typeof key == 'number')
- return key;
- if (key.length == 1)
- return key.charCodeAt(0);
- if (DOM_KEYS.hasOwnProperty(key))
- return DOM_KEYS[key];
- }
- return 0;
- }
-
- /**
- * Dispatches a virtual key event. The system VK does not use the IME
- * API as its primary role is to work in conjunction with a non-VK aware
- * IME.
- */
- function sendKeyEvent(type, ch, code, name, modifiers) {
- var event = {
- type: type,
- charValue: ch,
- keyCode: code,
- keyName: name,
- modifiers: modifiers
- };
- api.doAction(api.Action.KEY_EVENT, event);
- }
-
- function sendKey(type, codeName, key) {
- sendKeyEvent(type, domKeyValue(key), 0, codeName, 0);
- }
-
- return {vkOnLoad: vkOnLoad};
-})();
-
-document.addEventListener('DOMContentLoaded', vrShellVK.vkOnLoad);
diff --git a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.css b/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.css
deleted file mode 100644
index c0d3d691425..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.css
+++ /dev/null
@@ -1,311 +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. */
-
-html {
- background-color: rgba(255, 255, 255, 0);
-}
-
-#ui {
- left: 0;
- position: absolute;
- top: 0;
- transform-origin: left top;
- width: 1920px;
-}
-
-/* This class manages the position of elements on the texture page.
- * Each UI element should have a bounding div of this class. */
-.ui-element {
- float: left;
- margin: 2px;
-}
-
-.webvr-message-box {
- align-items: center;
- display: flex;
- flex-direction: column;
- justify-content: center;
-}
-
-#webvr-not-secure-permanent .webvr-not-secure-icon {
- display: inline-block;
- margin: 20px 0;
- vertical-align: middle;
-}
-
-#webvr-not-secure-permanent .webvr-string {
- display: inline-block;
- margin: 20px 10.5px;
- vertical-align: middle;
-}
-
-/* This is a single-line (nowrap) short message. The width is elastic for
- * translations, and the underlying string had a request to translators
- * to keep it short. */
-#webvr-not-secure-permanent .webvr-box {
- background-color: white;
- border-radius: 6px;
- box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
- box-sizing: border-box;
- color: #444;
- font-size: 26px;
- height: 78px;
- min-width: 226px;
- overflow: hidden;
- padding: 0 20px;
- white-space: nowrap;
-}
-
-/* This uses fixed width but the height is elastic for translations. */
-#webvr-not-secure-transient > div {
- background-color: rgba(26, 26, 26, 0.8);
- border-radius: 6px;
- box-sizing: border-box;
- color: white;
- display: flex;
- flex-direction: column;
- font-size: 26px;
- justify-content: center;
- line-height: 1.4;
- min-height: 160px;
- overflow: hidden;
- padding: 20px;
- text-align: center;
- width: 512px;
-}
-
-.round-button {
- background-color: #eee;
- background-position: center;
- background-repeat: no-repeat;
- background-size: contain;
- border-radius: 10%;
- height: 96px;
- margin: auto auto;
- opacity: 0.8;
- transition: opacity 150ms ease-in-out;
- width: 96px;
-}
-
-.button-caption {
- color: white;
- font-size: 24px;
- max-width: 192px;
- opacity: 0;
- overflow: hidden;
- text-align: center;
- transition: opacity 150ms ease-in-out;
- white-space: nowrap;
-}
-
-.rect-button {
- background-color: #eee;
- border-radius: 6px;
- color: black;
- font-size: 20px;
- line-height: 96px;
- opacity: 0.8;
- overflow: hidden;
- text-align: center;
- text-transform: uppercase;
- vertical-align: middle;
- white-space: nowrap;
- width: 300px;
-}
-
-.rect-button:hover {
- opacity: 1;
-}
-
-#back-button,
-#forward-button {
- background-image: url(../../../../ui/webui/resources/images/vr_back.svg);
-}
-
-#reload-button {
- background-image: url(../../../../ui/webui/resources/images/vr_reload.svg);
-}
-
-#forward-button {
- transform: scaleX(-1);
-}
-
-#reload-ui-button {
- color: white;
- font-size: 24px;
- padding: 12px;
-}
-
-#reload-ui-button:hover {
- background-color: pink;
-}
-
-.tab {
- background-color: #eee;
- border-radius: 6px;
- color: black;
- display: inline-block;
- font-size: 20px;
- height: 30px;
- line-height: 30px;
- margin: 0 15px 0 15px;
- overflow: hidden;
- padding: 12px;
- vertical-align: middle;
- white-space: nowrap;
- width: 300px;
-}
-
-.tab-incognito {
- background-color: #525252;
- color: white;
-}
-
-/* The tab container element behaves like a scroll view (in conjunction with the
- * clip view). */
-#tab-container {
- height: 54px;
- overflow-x: scroll;
- overflow-y: hidden;
- white-space: nowrap;
- width: 1000px;
-}
-
-/* The tab clip element's width will be programmatically set to the total width
- * of all it's children (the tabs). By doing so, the tabs can be scrolled
- * horizontally in the tab container element. */
-#tab-clip {
- margin: 0 auto;
- overflow: hidden;
-}
-
-#url-indicator-container {
- --tranX: 0;
- --tranY: -0.65;
- --tranZ: -1.2;
-}
-
-#url-indicator-border {
- --fadeTimeMs: 500;
- --fadeYOffset: -0.1;
- --opacity: 0.9;
- --statusBarColor: rgb(66, 133, 244);
- background-color: #ececec;
- border-radius: 200px;
- padding: 6px;
-}
-
-#url-indicator {
- align-items: center;
- background-color: #ececec;
- border-radius: 200px;
- box-sizing: border-box;
- display: flex;
- height: 104px;
- justify-content: center;
- overflow: hidden;
- white-space: nowrap;
- width: 512px;
-}
-
-#url-indicator-content {
- align-items: center;
- display: flex;
- max-width: 448px;
-}
-
-.url-indicator-icon {
- -webkit-mask-size: 50px;
- display: none;
- flex: none;
- height: 50px;
- margin-right: 10px;
- width: 50px;
-}
-
-#url-indicator-info-icon {
- -webkit-mask-image: url(../../../../ui/webui/resources/images/i_circle.svg);
- background-color: rgb(90, 90, 90);
-}
-
-#url-indicator-lock-icon {
- -webkit-mask-image: url(../../../../ui/webui/resources/images/lock.svg);
- background-color: rgb(11, 128, 67);
-}
-
-#url-indicator-warning-icon {
- -webkit-mask-image: url(../../../../ui/webui/resources/images/warning.svg);
- background-color: rgb(199, 56, 33);
-}
-
-#url-indicator #url {
- color: #252525;
- font-size: 48px;
- overflow: hidden;
- white-space: nowrap;
- width: 100%;
-}
-
-#url-indicator #path {
- color: #868686;
-}
-
-#omnibox-ui-element {
- --tranX: 0;
- --tranY: -0.1;
- --tranZ: -1.0;
- background-color: transparent;
- box-sizing: border-box;
- font-family: arial;
- font-size: 16px;
- width: 400px;
-}
-
-#suggestions {
- border: 1px solid transparent;
- box-sizing: border-box;
-}
-
-.suggestion {
- align-items: center; /* Vertically center text in div. */
- background-color: white;
- /* Use a transparent border to hide text overflow, but allow background to
- * color show through. */
- border-left: 5px solid transparent;
- border-right: 5px solid transparent;
- box-sizing: border-box;
- display: flex;
- height: 24px;
- overflow: hidden;
- visibility: hidden;
- white-space: nowrap;
-}
-
-.suggestion:hover {
- background-color: orange;
-}
-
-#omnibox-url-element {
- background-color: white;
- border: 1px solid grey;
- box-sizing: border-box;
- display: flex;
- flex-direction: row-reverse; /* Right-justify for convienence. */
- margin-top: 2px;
- padding: 5px;
-}
-
-#omnibox-input-field {
- border: none;
- font-size: 16px;
- outline: none; /* Do not show an outline when focused. */
- overflow: hidden;
- white-space: nowrap;
- width: 100%;
-}
-
-#omnibox-clear-button {
- background: url(../../../../ui/webui/resources/images/x-hover.png) no-repeat center center;
- width: 18px;
-}
diff --git a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.html b/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.html
deleted file mode 100644
index c2839d19d84..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.html
+++ /dev/null
@@ -1,109 +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.
--->
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<if expr="is_android or is_ios">
-<meta name="viewport" content="width=device-width, initial-scale=1.0,
- maximum-scale=1.0, user-scalable=no">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-</if>
-<title>Vr Shell UIs</title>
-<link rel="stylesheet" href="vr_shell_ui.css">
-<link rel="stylesheet" href="vk.css">
-<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
-</head>
-<body>
- <div id="ui">
- <div id="webvr-not-secure-permanent" class="webvr-message-box ui-element">
- <div class="webvr-box">
- <img class="webvr-not-secure-icon" width="36" height="36"
- src="../../../../ui/webui/resources/images/i_circle.svg">
- <div class="webvr-string">$i18n{insecureWebVrContentPermanent}</div>
- </div>
- </div>
- <div id="webvr-not-secure-transient" class="webvr-message-box ui-element">
- <div>
- <div>$i18n{insecureWebVrContentTransient}</div>
- </div>
- </div>
- <div id="url-indicator-container" class="ui-element">
- <div id="url-indicator-border">
- <div id="url-indicator">
- <div id="url-indicator-content">
- <div id="url-indicator-info-icon" class="url-indicator-icon"></div>
- <div id="url-indicator-lock-icon" class="url-indicator-icon"></div>
- <div id="url-indicator-warning-icon" class="url-indicator-icon">
- </div>
- <div id="url">
- <span id="domain"></span><span id="path"></span>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div id="omnibox-ui-element" class="ui-element">
- <div id="suggestions">
- <div id="suggestion-4" class="suggestion"></div>
- <div id="suggestion-3" class="suggestion"></div>
- <div id="suggestion-2" class="suggestion"></div>
- <div id="suggestion-1" class="suggestion"></div>
- <div id="suggestion-0" class="suggestion"></div>
- </div>
- <div id="omnibox-url-element">
- <div id="omnibox-clear-button"></div>
- <input id="omnibox-input-field" type="url"></input>
- </div>
- </div>
- <div id="back-button" class="round-button ui-element"></div>
- <div id="reload-button" class="round-button ui-element"></div>
- <div id="forward-button" class="round-button ui-element"></div>
- <div id="back-button-caption" class="button-caption ui-element">
- $i18n{back}
- </div>
- <div id="reload-button-caption" class="button-caption ui-element">
- $i18n{reload}
- </div>
- <div id="forward-button-caption" class="button-caption ui-element">
- $i18n{forward}
- </div>
- <div id="reload-ui-button" class="ui-element">Reload UI</div>
- <div id="tab-template" class="tab"></div>
- <!--The tab container element behaves like a scroll view (in conjunction
- with the clip view). -->
- <div id="tab-container" class="ui-element">
- <!--The tab clip element's width will be programmatically set to the total
- width of all it's children (the tabs). By doing so, the tabs can be
- scrolled horizontally in the tab container element.-->
- <div id="tab-clip">
- </div>
- </div>
- <div id="new-tab" class="ui-element rect-button">
- $i18n{newTab}
- </div>
- <div id="new-incognito-tab" class="ui-element rect-button">
- $i18n{newIncognitoTab}
- </div>
- <div id="vkb-ui-element" class="ui-element" lang="en" dir="ltr">
- <div id="vkb" class="inputview-container">
- <div id="numberView" class="inputview-layoutview"></div>
- <div class="inputview-spacerview"></div>
- <div class="inputview-layoutview" id="keyboardView"></div>
- <div class="inputview-spacerview"></div>
- <div id="specialkeyView" class="inputview-layoutview"></div>
- </div>
- </div>
- </div>
-</body>
-
-<!-- Run script after creating body, to let it add its own elements. -->
-<script src="vr_shell_ui_api.js"></script>
-<script src="vr_shell_ui_scene.js"></script>
-<script src="vr_shell_ui.js"></script>
-<script src="vk.js"></script>
-</html>
diff --git a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.js
deleted file mode 100644
index 7dababd09ba..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui.js
+++ /dev/null
@@ -1,1073 +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.
-
-var vrShellUi = (function() {
- 'use strict';
-
- let ui = new scene.Scene();
- let uiManager;
- let nativeCommandHandler;
-
- let uiRootElement = document.querySelector('#ui');
- let uiStyle = window.getComputedStyle(uiRootElement);
- /** @const */ var ANIM_DURATION = 150;
-
- // This value should match the one in VrShellImpl.java
- /** @const */ var UI_DPR = 1.2;
-
- function getStyleFloat(style, property) {
- let value = parseFloat(style.getPropertyValue(property));
- return isNaN(value) ? 0 : value;
- }
-
- function getStyleString(style, property) {
- let str = style.getPropertyValue(property);
- return !str || 0 === str.length ? '' : str;
- }
-
- class ContentQuad {
- constructor() {
- /** @const */ this.SCREEN_HEIGHT = 1.6;
- /** @const */ this.SCREEN_RATIO = 16 / 9;
- /** @const */ this.BROWSING_SCREEN_DISTANCE = 2.0;
- /** @const */ this.FULLSCREEN_DISTANCE = 3.0;
- /** @const */ this.CSS_WIDTH_PIXELS = 960.0;
- /** @const */ this.CSS_HEIGHT_PIXELS = 640.0;
- /** @const */ this.DPR = 1.2;
- /** @const */ this.MENU_MODE_SCREEN_DISTANCE = 1.2;
- /** @const */ this.MENU_MODE_SCREEN_HEIGHT = 0.5;
- /** @const */ this.MENU_MODE_SCREEN_ELEVATION = 0.1;
- /** @const */ this.BACKGROUND_DISTANCE_MULTIPLIER = 1.414;
-
- this.menuMode = false;
- this.fullscreen = false;
-
- let element = new api.UiElement(0, 0, 0, 0);
- element.setFill(new api.Content());
- element.setVisible(false);
- element.setSize(
- this.SCREEN_HEIGHT * this.SCREEN_RATIO, this.SCREEN_HEIGHT);
- element.setTranslation(0, 0, -this.BROWSING_SCREEN_DISTANCE);
- this.elementId = ui.addElement(element);
-
- // Place an invisible (fill none) but hittable plane behind the content
- // quad, to keep the reticle roughly planar with the content if near
- // content.
- let backPlane = new api.UiElement(0, 0, 0, 0);
- backPlane.setSize(1000, 1000);
- backPlane.setTranslation(0, 0, -0.01);
- backPlane.setParentId(this.elementId);
- backPlane.setFill(new api.NoFill());
- ui.addElement(backPlane);
-
- this.updateState();
- }
-
- setEnabled(enabled) {
- let update = new api.UiElementUpdate();
- update.setVisible(enabled);
- ui.updateElement(this.elementId, update);
- if (enabled) {
- api.setContentCssSize(
- this.CSS_WIDTH_PIXELS, this.CSS_HEIGHT_PIXELS, this.DPR);
- } else {
- // TODO(mthiesse): Restore the webVR resolution (which matches native
- // display resolution).
- }
- }
-
- setMenuMode(enabled) {
- if (this.menuMode == enabled)
- return;
- this.menuMode = enabled;
- this.updateState()
- }
-
- setFullscreen(enabled) {
- if (this.fullscreen == enabled)
- return;
- this.fullscreen = enabled;
- this.updateState()
- }
-
- updateState() {
- // Defaults content quad parameters.
- let y = 0;
- let distance = this.BROWSING_SCREEN_DISTANCE;
- let height = this.SCREEN_HEIGHT;
-
- // Mode-specific overrides.
- if (this.menuMode) {
- y = this.MENU_MODE_SCREEN_ELEVATION;
- distance = this.MENU_MODE_SCREEN_DISTANCE;
- height = this.MENU_MODE_SCREEN_HEIGHT;
- } else if (this.fullscreen) {
- distance = this.FULLSCREEN_DISTANCE;
- }
-
- let anim;
- anim = new api.Animation(this.elementId, ANIM_DURATION);
- anim.setTranslation(0, y, -distance);
- anim.setEasing(new api.InOutEasing());
- ui.addAnimation(anim);
- anim = new api.Animation(this.elementId, ANIM_DURATION);
- anim.setSize(height * this.SCREEN_RATIO, height);
- anim.setEasing(new api.InOutEasing());
- ui.addAnimation(anim);
-
- ui.setBackgroundDistance(distance * this.BACKGROUND_DISTANCE_MULTIPLIER);
- }
-
- // TODO(crbug/643815): Add a method setting aspect ratio (and possible
- // animation of changing it).
-
- getElementId() {
- return this.elementId;
- }
- };
-
- class DomUiElement {
- constructor(domId) {
- let domElement = document.querySelector(domId);
-
- // Pull copy rectangle from the position of the element.
- let rect = domElement.getBoundingClientRect();
- let pixelX = Math.floor(rect.left);
- let pixelY = Math.floor(rect.top);
- let pixelWidth = Math.ceil(rect.right) - pixelX;
- let pixelHeight = Math.ceil(rect.bottom) - pixelY;
-
- let element = new api.UiElement(pixelX, pixelY, pixelWidth, pixelHeight);
- this.sizeX = pixelWidth / 1000;
- this.sizeY = pixelHeight / 1000;
- element.setSize(this.sizeX, this.sizeY);
-
- // Pull additional custom properties from CSS.
- let style = window.getComputedStyle(domElement);
- this.translationX = getStyleFloat(style, '--tranX');
- this.translationY = getStyleFloat(style, '--tranY');
- this.translationZ = getStyleFloat(style, '--tranZ');
- element.setTranslation(
- this.translationX, this.translationY, this.translationZ);
-
- this.uiElementId = ui.addElement(element);
- this.domElement = domElement;
- }
- };
-
- class Button {
- constructor(domId, callback, parentId) {
- let captionId = domId + '-caption';
- this.button = document.querySelector(domId);
- this.caption = document.querySelector(captionId);
-
- // Create an invisible parent, from which the button will hover.
- let backing = new api.UiElement(0, 0, 0, 0);
- backing.setParentId(parentId);
- backing.setVisible(false);
- this.backingElementId = ui.addElement(backing);
-
- this.buttonElement = new DomUiElement(domId);
- let update = new api.UiElementUpdate();
- update.setParentId(this.backingElementId);
- ui.updateElement(this.buttonElement.uiElementId, update);
-
- this.captionElement = new DomUiElement(captionId);
- update = new api.UiElementUpdate();
- update.setParentId(this.buttonElement.uiElementId);
- update.setTranslation(0, -this.captionElement.sizeY / 2, 0);
- update.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YBOTTOM);
- ui.updateElement(this.captionElement.uiElementId, update);
-
- this.button.addEventListener('mouseenter', this.onMouseEnter.bind(this));
- this.button.addEventListener('mouseleave', this.onMouseLeave.bind(this));
- this.button.addEventListener('click', callback);
- }
-
- setTranslation(x, y, z) {
- let update = new api.UiElementUpdate();
- update.setTranslation(x, y, z);
- ui.updateElement(this.backingElementId, update);
- }
-
- setVisible(visible) {
- let update = new api.UiElementUpdate();
- update.setVisible(visible);
- ui.updateElement(this.buttonElement.uiElementId, update);
- update = new api.UiElementUpdate();
- update.setVisible(visible);
- ui.updateElement(this.captionElement.uiElementId, update);
- }
-
- configure(buttonOpacity, captionOpacity, distanceForward) {
- this.button.style.opacity = buttonOpacity;
- this.caption.style.opacity = captionOpacity;
-
- let anim =
- new api.Animation(this.buttonElement.uiElementId, ANIM_DURATION);
- anim.setTranslation(0, 0, distanceForward);
- ui.addAnimation(anim);
- ui.flush();
- }
-
- onMouseEnter() {
- this.configure(1, 1, 0.015);
- }
-
- onMouseLeave() {
- this.configure(0.8, 0, 0);
- }
- };
-
- class Controls {
- constructor(contentQuadId) {
- this.enabled = false;
-
- this.buttons = [];
- let descriptors = [
- [
- '#back-button',
- function() {
- api.doAction(api.Action.HISTORY_BACK, {});
- }
- ],
- [
- '#reload-button',
- function() {
- api.doAction(api.Action.RELOAD, {});
- }
- ],
- [
- '#forward-button',
- function() {
- api.doAction(api.Action.HISTORY_FORWARD, {});
- }
- ],
- ];
-
- /** @const */ var BUTTON_Y = -0.27;
- /** @const */ var BUTTON_Z = -1;
- /** @const */ var BUTTON_SPACING = 0.11;
-
- let controls = new api.UiElement(0, 0, 0, 0);
- controls.setVisible(false);
- controls.setTranslation(0, BUTTON_Y, BUTTON_Z);
- this.controlsId = ui.addElement(controls);
-
- let startPosition = -BUTTON_SPACING * (descriptors.length / 2.0 - 0.5);
-
- for (let i = 0; i < descriptors.length; i++) {
- let domId = descriptors[i][0];
- let callback = descriptors[i][1];
- let button = new Button(domId, callback, this.controlsId);
- button.setTranslation(startPosition + i * BUTTON_SPACING, 0, 0);
- this.buttons.push(button);
- }
- }
-
- setEnabled(enabled) {
- this.enabled = enabled;
- this.configure();
- }
-
- configure() {
- for (let i = 0; i < this.buttons.length; i++) {
- this.buttons[i].setVisible(this.enabled);
- }
- }
- };
-
- /**
- * A button to trigger a reload of the HTML UI for development purposes.
- */
- class ReloadUiButton {
- constructor() {
- this.enabled = false;
- this.devMode = false;
-
- this.uiElement = new DomUiElement('#reload-ui-button');
- this.uiElement.domElement.addEventListener('click', function() {
- ui.purge();
- api.doAction(api.Action.RELOAD_UI, {});
- });
-
- let update = new api.UiElementUpdate();
- update.setVisible(false);
- update.setSize(0.25, 0.1);
- update.setTranslation(0, -1.0, -1.0);
- update.setRotation(1, 0, 0, -0.8);
- ui.updateElement(this.uiElement.uiElementId, update);
- }
-
- setEnabled(enabled) {
- this.enabled = enabled;
- this.updateState();
- }
-
- setDevMode(enabled) {
- this.devMode = enabled;
- this.updateState();
- }
-
- updateState() {
- let update = new api.UiElementUpdate();
- update.setVisible(this.enabled && this.devMode);
- ui.updateElement(this.uiElement.uiElementId, update);
- }
- };
-
- class SecureOriginWarnings {
- constructor() {
- /** @const */ var DISTANCE = 0.7;
- /** @const */ var ANGLE_UP = 16.3 * Math.PI / 180.0;
-
- this.enabled = false;
- this.secure = false;
- this.secureOriginTimer = null;
-
- // Permanent WebVR security warning. This warning is shown near the top of
- // the field of view.
- this.webVrSecureWarning = new DomUiElement('#webvr-not-secure-permanent');
- let update = new api.UiElementUpdate();
- update.setScale(DISTANCE, DISTANCE, 1);
- update.setTranslation(
- 0, DISTANCE * Math.sin(ANGLE_UP), -DISTANCE * Math.cos(ANGLE_UP));
- update.setRotation(1.0, 0.0, 0.0, ANGLE_UP);
- update.setHitTestable(false);
- update.setVisible(false);
- update.setLockToFieldOfView(true);
- ui.updateElement(this.webVrSecureWarning.uiElementId, update);
-
- // Temporary WebVR security warning. This warning is shown in the center
- // of the field of view, for a limited period of time.
- this.transientWarning = new DomUiElement('#webvr-not-secure-transient');
- update = new api.UiElementUpdate();
- update.setScale(DISTANCE, DISTANCE, 1);
- update.setTranslation(0, 0, -DISTANCE);
- update.setHitTestable(false);
- update.setVisible(false);
- update.setLockToFieldOfView(true);
- ui.updateElement(this.transientWarning.uiElementId, update);
- }
-
- setEnabled(enabled) {
- this.enabled = enabled;
- this.updateState();
- }
-
- setSecure(secure) {
- this.secure = secure;
- this.updateState();
- }
-
- updateState() {
- /** @const */ var TRANSIENT_TIMEOUT_MS = 30000;
-
- let visible = (this.enabled && !this.secure);
- if (this.secureOriginTimer) {
- clearInterval(this.secureOriginTimer);
- this.secureOriginTimer = null;
- }
- if (visible) {
- this.secureOriginTimer =
- setTimeout(this.onTransientTimer.bind(this), TRANSIENT_TIMEOUT_MS);
- }
- this.showOrHideWarnings(visible);
- }
-
- showOrHideWarnings(visible) {
- let update = new api.UiElementUpdate();
- update.setVisible(visible);
- ui.updateElement(this.webVrSecureWarning.uiElementId, update);
- update = new api.UiElementUpdate();
- update.setVisible(visible);
- ui.updateElement(this.transientWarning.uiElementId, update);
- }
-
- onTransientTimer() {
- let update = new api.UiElementUpdate();
- update.setVisible(false);
- ui.updateElement(this.transientWarning.uiElementId, update);
- this.secureOriginTimer = null;
- ui.flush();
- }
- };
-
- class UrlIndicator {
- constructor() {
- this.domUiElement = new DomUiElement('#url-indicator-container');
- this.enabled = false;
- this.hidden = false;
- this.loading = false;
- this.loadProgress = 0;
- this.level = 0;
- this.visibilityTimeout = 0;
- this.visibilityTimer = null;
- this.nativeState = {};
-
- // Initially invisible.
- let update = new api.UiElementUpdate();
- update.setVisible(false);
- ui.updateElement(this.domUiElement.uiElementId, update);
- this.nativeState.visible = false;
-
- // Pull some CSS properties so that Javascript can reconfigure the
- // indicator programmatically.
- let border =
- this.domUiElement.domElement.querySelector('#url-indicator-border');
- let style = window.getComputedStyle(border);
- this.statusBarColor = getStyleString(style, '--statusBarColor');
- this.backgroundColor = style.backgroundColor;
- this.fadeTimeMs = getStyleFloat(style, '--fadeTimeMs');
- this.fadeYOffset = getStyleFloat(style, '--fadeYOffset');
- this.opacity = getStyleFloat(style, '--opacity');
- }
-
- getSecurityIconElementId(level) {
- // See security_state.h and getSecurityIconResource() for this mapping.
- switch (level) {
- case 0: // NONE
- case 1: // HTTP_SHOW_WARNING
- case 4: // SECURITY_WARNING
- return '#url-indicator-info-icon';
- case 2: // SECURE:
- case 3: // EV_SECURE:
- return '#url-indicator-lock-icon';
- case 5: // SECURE_WITH_POLICY_INSTALLED_CERT (ChromeOS only)
- case 6: // DANGEROUS
- default:
- return '#url-indicator-warning-icon';
- }
- }
-
- setEnabled(enabled) {
- this.enabled = enabled;
- this.resetVisibilityTimer();
- this.updateState();
- }
-
- setLoading(loading) {
- this.loading = loading;
- this.loadProgress = 0;
- this.resetVisibilityTimer();
- this.updateState();
- }
-
- setLoadProgress(progress) {
- this.loadProgress = progress;
- this.updateState();
- }
-
- setURL(host, path) {
- let indicator = this.domUiElement.domElement;
- indicator.querySelector('#domain').textContent = host;
- indicator.querySelector('#path').textContent = path;
- this.resetVisibilityTimer();
- this.updateState();
- }
-
- setSecurityLevel(level) {
- document.querySelector('#url-indicator-warning-icon').style.display =
- 'none';
- document.querySelector('#url-indicator-info-icon').style.display = 'none';
- document.querySelector('#url-indicator-lock-icon').style.display = 'none';
- let icon = this.getSecurityIconElementId(level);
- document.querySelector(icon).style.display = 'block';
-
- this.resetVisibilityTimer();
- this.updateState();
- }
-
- setVisibilityTimeout(milliseconds) {
- this.visibilityTimeout = milliseconds;
- this.resetVisibilityTimer();
- this.updateState();
- }
-
- resetVisibilityTimer() {
- if (this.visibilityTimer) {
- clearInterval(this.visibilityTimer);
- this.visibilityTimer = null;
- }
- if (this.enabled && this.visibilityTimeout > 0 && !this.loading) {
- this.visibilityTimer = setTimeout(
- this.onVisibilityTimer.bind(this), this.visibilityTimeout);
- }
- }
-
- onVisibilityTimer() {
- this.visibilityTimer = null;
- this.updateState();
- }
-
- updateState() {
- this.setNativeVisibility(this.enabled);
-
- if (!this.enabled) {
- return;
- }
-
- let indicator = document.querySelector('#url-indicator-border');
- if (this.loading) {
- // Remap load progress range 0-100 as 5-95 percent, to avoid the
- // extremities of the rounded ends of the indicator.
- let percent = Math.round((this.loadProgress * 0.9 + 0.05) * 100);
- let gradient = 'linear-gradient(to right, ' + this.statusBarColor +
- ' 0%, ' + this.statusBarColor + ' ' + percent + '%, ' +
- this.backgroundColor + ' ' + percent + '%, ' +
- this.backgroundColor + ' 100%)';
- indicator.style.background = gradient;
- } else {
- indicator.style.background = this.backgroundColor;
- }
-
- let shouldBeHidden =
- !this.loading && this.visibilityTimeout > 0 && !this.visibilityTimer;
- if (shouldBeHidden != this.hidden) {
- // Make the box fade away if it's disappearing.
- this.hidden = shouldBeHidden;
-
- // Fade-out or fade-in the box.
- let opacityAnimation =
- new api.Animation(this.domUiElement.uiElementId, this.fadeTimeMs);
- opacityAnimation.setOpacity(this.hidden ? 0.0 : this.opacity);
- ui.addAnimation(opacityAnimation);
-
- // Drop the position as it fades, or raise the position if appearing.
- let yOffset = this.hidden ? this.fadeYOffset : 0;
- let positionAnimation =
- new api.Animation(this.domUiElement.uiElementId, this.fadeTimeMs);
- positionAnimation.setTranslation(
- this.domUiElement.translationX,
- this.domUiElement.translationY + yOffset,
- this.domUiElement.translationZ);
- ui.addAnimation(positionAnimation);
- }
-
- ui.flush();
- }
-
- setNativeVisibility(visible) {
- if (visible == this.nativeState.visible) {
- return;
- }
- this.nativeState.visible = visible;
- let update = new api.UiElementUpdate();
- update.setVisible(visible);
- ui.updateElement(this.domUiElement.uiElementId, update);
- ui.flush();
- }
- };
-
- class Background {
- constructor() {
- /** @const */ this.SCENE_GROUND_SIZE = 25.0;
- /** @const */ this.SCENE_HEIGHT = 4.0;
- /** @const */ this.GRIDLINE_COUNT = 10;
- /** @const */ this.HORIZON_COLOR = {r: 0.57, g: 0.57, b: 0.57, a: 1.0};
- /** @const */ this.CENTER_COLOR = {r: 0.48, g: 0.48, b: 0.48, a: 1.0};
- /** @const */ this.FULLSCREEN_BACKGROUND_COLOR =
- {r: 0.1, g: 0.1, b: 0.1, a: 1.0};
-
- // Make ground plane.
- let groundPlane = new api.UiElementUpdate();
- groundPlane.setVisible(true);
- groundPlane.setSize(this.SCENE_GROUND_SIZE, this.SCENE_GROUND_SIZE);
- groundPlane.setFill(
- new api.OpaqueGradient(this.HORIZON_COLOR, this.CENTER_COLOR));
- groundPlane.setTranslation(0, -this.SCENE_HEIGHT / 2, 0);
- groundPlane.setRotation(1.0, 0.0, 0.0, -Math.PI / 2);
- groundPlane.setDrawPhase(0);
- this.groundPlaneId = ui.addElement(groundPlane);
-
- // Make ceiling plane.
- let ceilingPlane = new api.UiElementUpdate();
- ceilingPlane.setVisible(true);
- ceilingPlane.setSize(this.SCENE_GROUND_SIZE, this.SCENE_GROUND_SIZE);
- ceilingPlane.setFill(
- new api.OpaqueGradient(this.HORIZON_COLOR, this.CENTER_COLOR));
- ceilingPlane.setTranslation(0, this.SCENE_HEIGHT / 2, 0);
- ceilingPlane.setRotation(1.0, 0.0, 0.0, Math.PI / 2);
- ceilingPlane.setDrawPhase(0);
- this.ceilingPlaneId = ui.addElement(ceilingPlane);
-
- // Ground grid.
- let groundGrid = new api.UiElementUpdate();
- groundGrid.setVisible(true);
- groundGrid.setSize(this.SCENE_GROUND_SIZE, this.SCENE_GROUND_SIZE);
- let transparentHorizonColor = {
- r: this.HORIZON_COLOR.r,
- g: this.HORIZON_COLOR.g,
- b: this.HORIZON_COLOR.b,
- a: 0
- };
- groundGrid.setFill(new api.GridGradient(
- transparentHorizonColor, this.HORIZON_COLOR, this.GRIDLINE_COUNT));
- groundGrid.setTranslation(0, -this.SCENE_HEIGHT / 2 + 0.01, 0);
- groundGrid.setRotation(1.0, 0.0, 0.0, -Math.PI / 2);
- groundGrid.setDrawPhase(0);
- this.groundGridId = ui.addElement(groundGrid);
-
- this.setHiddenBackground();
- }
-
- setElementVisible(elementId, visible) {
- let update = new api.UiElementUpdate();
- update.setVisible(visible);
- ui.updateElement(elementId, update);
- }
-
- setLightBackground() {
- this.setElementVisible(this.groundPlaneId, true);
- this.setElementVisible(this.ceilingPlaneId, true);
- this.setElementVisible(this.groundGridId, true);
- ui.setBackgroundColor(this.HORIZON_COLOR);
- }
-
- setDarkBackground() {
- this.setElementVisible(this.groundPlaneId, false);
- this.setElementVisible(this.ceilingPlaneId, false);
- this.setElementVisible(this.groundGridId, true);
- ui.setBackgroundColor(this.FULLSCREEN_BACKGROUND_COLOR);
- }
-
- setHiddenBackground() {
- this.setElementVisible(this.groundPlaneId, false);
- this.setElementVisible(this.ceilingPlaneId, false);
- this.setElementVisible(this.groundGridId, false);
- ui.setBackgroundColor(this.FULLSCREEN_BACKGROUND_COLOR);
- }
-
- setState(mode, menuMode, fullscreen) {
- switch (mode) {
- case api.Mode.STANDARD:
- if (fullscreen) {
- this.setDarkBackground();
- } else {
- this.setLightBackground();
- }
- break;
- case api.Mode.WEB_VR:
- if (menuMode) {
- this.setLightBackground();
- } else {
- this.setHiddenBackground();
- }
- break;
- }
- }
- };
-
- class Omnibox {
- constructor() {
- this.enabled = false;
-
- this.domUiElement = new DomUiElement('#omnibox-ui-element');
- let root = this.domUiElement.domElement;
- this.inputField = root.querySelector('#omnibox-input-field');
-
- // Initially invisible.
- let update = new api.UiElementUpdate();
- update.setVisible(true);
- ui.updateElement(this.domUiElement.uiElementId, update);
-
- // Field-clearing button.
- let clearButton = root.querySelector('#omnibox-clear-button');
- clearButton.addEventListener('click', function() {
- this.inputField.value = '';
- api.doAction(api.Action.OMNIBOX_CONTENT, {'text': ''});
- }.bind(this));
-
- // Watch for the enter key to trigger navigation.
- this.inputField.addEventListener('keypress', function(e) {
- if (e.keyCode == 13) {
- this.setSuggestions([]);
- api.doAction(
- // TODO(crbug.com/683344): Properly choose prefix.
- api.Action.LOAD_URL, {'url': 'http://' + e.target.value});
- }
- });
-
- // Watch for field input to generate suggestions.
- this.inputField.addEventListener('input', function(e) {
- api.doAction(api.Action.OMNIBOX_CONTENT, {'text': e.target.value});
- });
-
- // Clicking on suggestions triggers navigation.
- let elements = root.querySelectorAll('.suggestion');
- this.maxSuggestions = elements.length;
- for (var i = 0; i < elements.length; i++) {
- elements[i].addEventListener('click', function(index, e) {
- if (e.target.url) {
- api.doAction(api.Action.LOAD_URL, {'url': e.target.url});
- this.setSuggestions([]);
- }
- }.bind(this, i));
- }
- }
-
- setEnabled(enabled) {
- this.enabled = enabled;
- let update = new api.UiElementUpdate();
- update.setVisible(enabled);
- ui.updateElement(this.domUiElement.uiElementId, update);
- }
-
- setURL(url) {
- this.inputField.value = url;
- }
-
- setSuggestions(suggestions) {
- for (var i = 0; i < this.maxSuggestions; i++) {
- let element = document.querySelector('#suggestion-' + i);
- if (i >= suggestions.length) {
- element.textContent = '';
- element.style.visibility = 'hidden';
- element.url = null;
- } else {
- element.textContent = suggestions[i].description;
- element.style.visibility = 'visible';
- element.url = suggestions[i].url;
- }
- }
- }
- };
-
- // Shows the open tabs.
- //
- // The tab container is made of three <div> nesting levels. The first is the
- // tab container element, which acts like a scroll view. It has a fixed size
- // and corresponds to a UI element in the scene. The second level is the clip
- // element, which is programmatically set to the total width of all it's
- // children (the third nesting level). The clip element is needed to enable
- // horizontal scrolling and prevent the children from breaking to a new line.
- // The third nesting level comprises the actual tabs.
- //
- // TODO(crbug/641487): currently, tabs cannot be scrolled because the
- // scrolling event is not sent to UI elements.
- class TabContainer {
- constructor(contentQuadId) {
- /** @const */ var DOM_TAB_TEMPLATE_SELECTOR = '#tab-template';
- /** @const */ var DOM_TAB_CONTAINER_SELECTOR = '#tab-container';
- /** @const */ var DOM_TAB_CLIP_SELECTOR = '#tab-clip';
- /** @const */ var DOM_NEW_TAB_BUTTON_SELECTOR = '#new-tab';
- /** @const */ var DOM_NEW_INCOGNITO_TAB_BUTTON_SELECTOR =
- '#new-incognito-tab';
- /** @const */ var TAB_CONTAINER_Y_OFFSET = 0.4;
- /** @const */ var TAB_CONTAINER_Z_OFFSET = -1;
-
- this.domTabs = {};
- this.contentQuadId = contentQuadId;
- this.domTabTemplate = document.querySelector(DOM_TAB_TEMPLATE_SELECTOR);
- this.domTabContainer = document.querySelector(DOM_TAB_CONTAINER_SELECTOR);
- this.domTabClip = document.querySelector(DOM_TAB_CLIP_SELECTOR);
-
- // Add tab container to native scene.
- this.tabContainerElement = new DomUiElement(DOM_TAB_CONTAINER_SELECTOR);
- let positionUpdate = new api.UiElementUpdate();
- positionUpdate.setTranslation(
- 0, TAB_CONTAINER_Y_OFFSET, TAB_CONTAINER_Z_OFFSET);
- positionUpdate.setVisible(false);
- ui.updateElement(this.tabContainerElement.uiElementId, positionUpdate);
-
- // Add the new tab buttons to the native scene.
- let buttonConfigs = [
- {
- selector: DOM_NEW_TAB_BUTTON_SELECTOR, x: -0.2, incognito: false
- }, {
- selector: DOM_NEW_INCOGNITO_TAB_BUTTON_SELECTOR,
- x: 0.2,
- incognito: true
- }
- ];
- this.buttonElements = [];
- buttonConfigs.forEach(function(buttonConfig) {
- let buttonElement = new DomUiElement(buttonConfig.selector);
- let update = new api.UiElementUpdate();
- update.setTranslation(buttonConfig.x, 0.1, 0);
- update.setVisible(false);
- update.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YTOP);
- update.setParentId(this.tabContainerElement.uiElementId);
- ui.updateElement(buttonElement.uiElementId, update);
- buttonElement.domElement.addEventListener('click', function() {
- api.doAction(
- api.Action.OPEN_NEW_TAB, {'incognito': buttonConfig.incognito});
- });
- this.buttonElements.push(buttonElement);
- }, this);
-
- // Calculate the width of one tab so that we can properly set the clip
- // element's width.
- this.domTabWidth = this.domTabTemplate.offsetWidth;
- var domTabStyle = window.getComputedStyle(this.domTabTemplate);
- this.domTabWidth += parseInt(domTabStyle.marginLeft, 10) +
- parseInt(domTabStyle.marginRight, 10);
- }
-
- makeDomTab(tab) {
- // Make a copy of the template tab and add this copy to the tab container
- // view.
- let domTab = this.domTabTemplate.cloneNode(true);
- domTab.removeAttribute('id');
- domTab.addEventListener('click', function() {
- api.doAction(api.Action.SHOW_TAB, {'id': domTab.tab.id});
- });
- domTab.tab = tab;
- this.domTabClip.appendChild(domTab);
- this.domTabs[tab.id] = domTab;
- return domTab;
- }
-
- resizeClipElement() {
- // Resize clip element so that scrolling works.
- this.domTabClip.style.width =
- (Object.keys(this.domTabs).length * this.domTabWidth) + 'px';
- }
-
- setTabs(tabs) {
- // Remove all current tabs.
- while (this.domTabClip.firstChild) {
- this.domTabClip.removeChild(this.domTabClip.firstChild);
- }
- this.domTabs = {};
-
- // Add new tabs.
- for (let i = 0; i < tabs.length; i++) {
- this.addTab(tabs[i]);
- }
- }
-
- hasTab(tab) {
- return tab.id in this.domTabs;
- }
-
- addTab(tab) {
- this.makeDomTab(tab);
- this.updateTab(tab);
- this.resizeClipElement();
- }
-
- updateTab(tab) {
- let domTab = this.domTabs[tab.id];
- domTab.textContent = tab.title;
- domTab.classList.remove('tab-incognito');
- if (tab.incognito) {
- domTab.classList.add('tab-incognito');
- }
- }
-
- removeTab(tab) {
- let qualifiedTabId = tab.id;
- let domTab = this.domTabs[qualifiedTabId];
- delete this.domTabs[qualifiedTabId];
- this.domTabClip.removeChild(domTab);
- this.resizeClipElement();
- }
-
- setEnabled(enabled) {
- let update = new api.UiElementUpdate();
- update.setVisible(enabled);
- ui.updateElement(this.tabContainerElement.uiElementId, update);
- this.buttonElements.forEach(function(buttonElement) {
- let update = new api.UiElementUpdate();
- update.setVisible(enabled);
- ui.updateElement(buttonElement.uiElementId, update);
- }, this);
- }
- };
-
- class VirtualKeyboard {
- constructor(contentQuadId) {
- this.domUiElement = new DomUiElement('#vkb');
- let update = new api.UiElementUpdate();
- update.setParentId(contentQuadId);
- update.setVisible(false);
- update.setRotation(1.0, 0.0, 0.0, -0.9);
- update.setScale(1.8, 1.8, 1.8);
- update.setTranslation(0, -1.2, 0.1);
- update.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YBOTTOM);
- ui.updateElement(this.domUiElement.uiElementId, update);
- }
-
- setEnabled(enabled) {
- let update = new api.UiElementUpdate();
- update.setVisible(enabled);
- ui.updateElement(this.domUiElement.uiElementId, update);
- }
- };
-
- class UiManager {
- constructor() {
- this.mode = api.Mode.UNKNOWN;
- this.menuMode = false;
- this.fullscreen = false;
-
- this.background = new Background();
- this.contentQuad = new ContentQuad();
- let contentId = this.contentQuad.getElementId();
-
- this.controls = new Controls(contentId);
- this.secureOriginWarnings = new SecureOriginWarnings();
- this.urlIndicator = new UrlIndicator();
- this.omnibox = new Omnibox();
- this.reloadUiButton = new ReloadUiButton();
- this.tabContainer = new TabContainer(contentId);
- this.keyboard = new VirtualKeyboard(contentId);
- }
-
- setMode(mode) {
- this.mode = mode;
- this.updateState();
- }
-
- setFullscreen(fullscreen) {
- this.fullscreen = fullscreen;
- this.updateState();
- }
-
- handleAppButtonClicked() {
- this.menuMode = !this.menuMode;
- this.updateState();
- }
-
- updateState() {
- /** @const */ var URL_INDICATOR_VISIBILITY_TIMEOUT_MS = 5000;
-
- let mode = this.mode;
- let menuMode = this.menuMode;
- let fullscreen = this.fullscreen;
-
- api.doAction(api.Action.SET_CONTENT_PAUSED, {'paused': menuMode});
-
- this.contentQuad.setEnabled(mode == api.Mode.STANDARD);
- this.contentQuad.setFullscreen(fullscreen);
- this.contentQuad.setMenuMode(menuMode);
- // TODO(crbug/643815): Set aspect ratio on content quad when available.
- this.controls.setEnabled(menuMode);
- this.omnibox.setEnabled(menuMode);
- this.urlIndicator.setEnabled(mode == api.Mode.STANDARD && !menuMode);
- this.urlIndicator.setVisibilityTimeout(
- URL_INDICATOR_VISIBILITY_TIMEOUT_MS);
- this.secureOriginWarnings.setEnabled(
- mode == api.Mode.WEB_VR && !menuMode);
- this.background.setState(mode, menuMode, fullscreen);
- this.tabContainer.setEnabled(mode == api.Mode.STANDARD && menuMode);
-
- this.reloadUiButton.setEnabled(mode == api.Mode.STANDARD);
- this.keyboard.setEnabled(mode == api.Mode.STANDARD);
-
- api.setUiCssSize(
- uiRootElement.clientWidth, uiRootElement.clientHeight, UI_DPR);
- }
-
- setSecurityLevel(level) {
- this.urlIndicator.setSecurityLevel(level);
- }
-
- setWebVRSecureOrigin(secure) {
- this.secureOriginWarnings.setSecure(secure);
- }
- };
-
- function initialize() {
- uiManager = new UiManager();
- nativeCommandHandler = new UiCommandHandler(uiManager);
- ui.flush();
-
- api.domLoaded();
- }
-
- class UiCommandHandler extends api.NativeCommandHandler {
- constructor(uiManager) {
- super();
- this.manager = uiManager;
- }
-
- /** @override */
- onSetMode(mode) {
- this.manager.setMode(mode);
- }
-
- /** @override */
- onSetFullscreen(fullscreen) {
- this.manager.setFullscreen(fullscreen);
- }
-
- /** @override */
- onAppButtonClicked() {
- this.manager.handleAppButtonClicked();
- }
-
- /** @override */
- onSetSecurityLevel(level) {
- this.manager.setSecurityLevel(level);
- }
-
- /** @override */
- onSetWebVRSecureOrigin(secure) {
- this.manager.setWebVRSecureOrigin(secure);
- }
-
- /** @override */
- onSetReloadUiCapabilityEnabled(enabled) {
- this.manager.reloadUiButton.setDevMode(enabled);
- }
-
- /** @override */
- onSetUrl(host, path) {
- this.manager.urlIndicator.setURL(host, path);
- this.manager.omnibox.setURL(host, path);
- }
-
- /** @override */
- onSetLoading(loading) {
- this.manager.urlIndicator.setLoading(loading);
- }
-
- /** @override */
- onSetLoadingProgress(progress) {
- this.manager.urlIndicator.setLoadProgress(progress);
- }
-
- /** @override */
- onSetOmniboxSuggestions(suggestions) {
- this.manager.omnibox.setSuggestions(suggestions);
- }
-
- /** @override */
- onSetTabs(tabs) {
- uiManager.tabContainer.setTabs(tabs);
- }
-
- /** @override */
- onUpdateTab(tab) {
- if (uiManager.tabContainer.hasTab(tab)) {
- uiManager.tabContainer.updateTab(tab);
- } else {
- uiManager.tabContainer.addTab(tab);
- }
- }
-
- /** @override */
- onRemoveTab(tab) {
- uiManager.tabContainer.removeTab(tab);
- }
-
- /** @override */
- onCommandHandlerFinished() {
- ui.flush();
- }
- }
-
- function command(dict) {
- nativeCommandHandler.handleCommand(dict);
- }
-
- return {
- initialize: initialize,
- command: command,
- };
-})();
-
-window.addEventListener('load', vrShellUi.initialize);
diff --git a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui_api.js b/chromium/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
deleted file mode 100644
index 30f50da1dbe..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
+++ /dev/null
@@ -1,679 +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.
-
-var api = {};
-
-/**
- * Enumeration of scene update commands.
- * @enum {number}
- * @const
- */
-api.Command = {
- 'ADD_ELEMENT': 0,
- 'UPDATE_ELEMENT': 1,
- 'REMOVE_ELEMENT': 2,
- 'ADD_ANIMATION': 3,
- 'REMOVE_ANIMATION': 4,
- 'UPDATE_BACKGROUND': 5
-};
-
-/**
- * Sends one or more commands to native scene management. Commands are used
- * to add, modify or remove elements and animations. For examples of how to
- * format command parameters, refer to examples in scene.js.
- * @param {Array<Object>} commands
- */
-api.sendCommands = function(commands) {
- if (commands.length > 0) {
- chrome.send('updateScene', commands);
- }
-};
-
-/**
- * Enumeration of valid Anchroing for X axis.
- * An element can either be anchored to the left, right, or center of the main
- * content rect (or it can be absolutely positioned using NONE). Any
- * translations applied will be relative to this anchoring.
- * @enum {number}
- * @const
- */
-api.XAnchoring = {
- 'XNONE': 0,
- 'XLEFT': 1,
- 'XRIGHT': 2
-};
-
-/**
- * Enumeration of valid Anchroing for Y axis.
- * @enum {number}
- * @const
- */
-api.YAnchoring = {
- 'YNONE': 0,
- 'YTOP': 1,
- 'YBOTTOM': 2
-};
-
-/**
- * Enumeration of actions that can be triggered by the HTML UI.
- * @enum {number}
- * @const
- */
-api.Action = {
- 'HISTORY_BACK': 0,
- 'HISTORY_FORWARD': 1,
- 'RELOAD': 2,
- 'ZOOM_OUT': 3,
- 'ZOOM_IN': 4,
- 'RELOAD_UI': 5,
- 'LOAD_URL': 6,
- 'OMNIBOX_CONTENT': 7,
- 'SET_CONTENT_PAUSED': 8,
- 'SHOW_TAB': 9,
- 'OPEN_NEW_TAB': 10,
- 'KEY_EVENT': 11,
-};
-
-/**
- * Enumeration of modes that can be specified by the native side.
- * @enum {number}
- * @const
- */
-api.Mode = {
- 'UNKNOWN': -1,
- 'STANDARD': 0,
- 'WEB_VR': 1,
-};
-
-/**
- * Triggers an Action.
- * @param {api.Action} action
- * @param {Object} parameters
- */
-api.doAction = function(action, parameters) {
- chrome.send('doAction', [action, parameters]);
-};
-
-/**
- * Notify native scene management that DOM loading has completed, at the
- * specified page size.
- */
-api.domLoaded = function() {
- chrome.send('domLoaded');
-};
-
-/**
- * Sets the CSS size for the content window.
- * @param {number} width
- * @param {number} height
- * @param {number} dpr
- */
-api.setContentCssSize = function(width, height, dpr) {
- chrome.send('setContentCssSize', [width, height, dpr]);
-};
-
-/**
- * Sets the CSS size for this page.
- * @param {number} width
- * @param {number} height
- * @param {number} dpr
- */
-api.setUiCssSize = function(width, height, dpr) {
- chrome.send('setUiCssSize', [width, height, dpr]);
-};
-
-api.FillType = {
- 'NONE': 0,
- 'SPRITE': 1,
- 'OPAQUE_GRADIENT': 2,
- 'GRID_GRADIENT': 3,
- 'CONTENT': 4
-};
-
-/**
- * Abstract fill base class.
- * @abstract
- */
-api.Fill = class {
- constructor(type) {
- this.properties = {};
- this.properties['fillType'] = type;
- }
-};
-
-api.NoFill = class extends api.Fill {
- constructor() {
- super(api.FillType.NONE);
- }
-}
-
-api.Sprite = class extends api.Fill {
- constructor(pixelX, pixelY, pixelWidth, pixelHeight) {
- super(api.FillType.SPRITE);
- this.properties['copyRectX'] = pixelX;
- this.properties['copyRectY'] = pixelY;
- this.properties['copyRectWidth'] = pixelWidth;
- this.properties['copyRectHeight'] = pixelHeight;
- }
-};
-
-api.OpaqueGradient = class extends api.Fill {
- constructor(edgeColor, centerColor) {
- super(api.FillType.OPAQUE_GRADIENT);
- this.properties.edgeColor = edgeColor;
- this.properties.centerColor = centerColor;
- }
-};
-
-api.GridGradient = class extends api.Fill {
- constructor(edgeColor, centerColor, gridlineCount) {
- super(api.FillType.GRID_GRADIENT);
- this.properties.edgeColor = edgeColor;
- this.properties.centerColor = centerColor;
- this.properties.gridlineCount = gridlineCount;
- }
-};
-
-api.Content = class extends api.Fill {
- constructor() {
- super(api.FillType.CONTENT);
- }
-};
-
-/**
- * Represents updates to UI element properties. Any properties set on this
- * object are relayed to an underlying native element via scene command.
- * Properties that are not set on this object are left unchanged.
- * @struct
- */
-api.UiElementUpdate = class {
- constructor() {
- /** @private {!Object} */
- this.properties = {'id': -1};
- }
-
- /**
- * Set the id of the element to update.
- * @param {number} id
- */
- setId(id) {
- this.properties['id'] = id;
- }
-
- /**
- * Specify a parent for this element. If set, this element is positioned
- * relative to its parent element, rather than absolutely. This allows
- * elements to automatically move with a parent.
- * @param {number} id
- */
- setParentId(id) {
- this.properties['parentId'] = id;
- }
-
- /**
- * Specify the width and height (in meters) of an element.
- * @param {number} x
- * @param {number} y
- */
- setSize(x, y) {
- this.properties['sizeX'] = x;
- this.properties['sizeY'] = y;
- }
-
- /**
- * Specify optional scaling of the element, and any children.
- * @param {number} x
- * @param {number} y
- * @param {number} z
- */
- setScale(x, y, z) {
- this.properties['scaleX'] = x;
- this.properties['scaleY'] = y;
- this.properties['scaleZ'] = z;
- }
-
- /**
- * Specify rotation for the element. The rotation is specified in axis-angle
- * representation (rotate around unit vector [x, y, z] by 'a' radians).
- * @param {number} x
- * @param {number} y
- * @param {number} z
- * @param {number} a
- */
- setRotation(x, y, z, a) {
- this.properties['rotationX'] = x;
- this.properties['rotationY'] = y;
- this.properties['rotationZ'] = z;
- this.properties['rotationAngle'] = a;
- }
-
- /**
- * Specify the translation of the element. If anchoring is specified, the
- * offset is applied to the anchoring position rather than the origin.
- * Translation is applied after scaling and rotation.
- * @param {number} x
- * @param {number} y
- * @param {number} z
- */
- setTranslation(x, y, z) {
- this.properties['translationX'] = x;
- this.properties['translationY'] = y;
- this.properties['translationZ'] = z;
- }
-
- /**
- * Anchoring allows a rectangle to be positioned relative to the edge of
- * its parent, without being concerned about the size of the parent.
- * Values should be XAnchoring and YAnchoring elements.
- * Example: element.setAnchoring(XAnchoring.XNONE, YAnchoring.YBOTTOM);
- * @param {number} x
- * @param {number} y
- */
- setAnchoring(x, y) {
- this.properties['xAnchoring'] = x;
- this.properties['yAnchoring'] = y;
- }
-
- /**
- * Visibility controls whether the element is rendered.
- * @param {boolean} visible
- */
- setVisible(visible) {
- this.properties['visible'] = !!visible;
- }
-
- /**
- * Hit-testable implies that the reticle will hit the element, if visible.
- * @param {boolean} testable
- */
- setHitTestable(testable) {
- this.properties['hitTestable'] = !!testable;
- }
-
- /**
- * Causes an element to be rendered relative to the field of view, rather
- * than the scene. Elements locked in this way should not have a parent.
- * @param {boolean} locked
- */
- setLockToFieldOfView(locked) {
- this.properties['lockToFov'] = !!locked;
- }
-
- /**
- * Causes an element to be rendered with a specified opacity, between 0.0 and
- * 1.0. Opacity is inherited by children.
- * @param {number} opacity
- */
- setOpacity(opacity) {
- this.properties['opacity'] = opacity;
- }
-
- setFill(fill) {
- Object.assign(this.properties, fill.properties);
- }
-
- /**
- * Sets the draw phase. Elements with a lower draw phase are rendered before
- * elements with a higher draw phase. If elements have an equal draw phase
- * the element with the larger distance is drawn first. The default draw phase
- * is 1.
- * @param {number} drawPhase
- */
- setDrawPhase(drawPhase) {
- this.properties['drawPhase'] = drawPhase;
- }
-};
-
-/**
- * Represents a new UI element. This object builds on UiElementUpdate,
- * forcing the underlying texture coordinates to be specified.
- * @struct
- */
-api.UiElement = class extends api.UiElementUpdate {
- /**
- * Constructor of UiElement.
- * pixelX and pixelY values indicate the left upper corner; pixelWidth and
- * pixelHeight is width and height of the texture to be copied from the web
- * contents.
- * @param {number} pixelX
- * @param {number} pixelY
- * @param {number} pixelWidth
- * @param {number} pixelHeight
- */
- constructor(pixelX, pixelY, pixelWidth, pixelHeight) {
- super();
-
- // Apply defaults to new elements.
- this.setVisible(true);
- this.setHitTestable(true);
- this.setFill(new api.Sprite(pixelX, pixelY, pixelWidth, pixelHeight));
- }
-};
-
-/**
- * Enumeration of animatable properties.
- * @enum {number}
- * @const
- */
-api.Property = {
- 'COPYRECT': 0,
- 'SIZE': 1,
- 'TRANSLATION': 2,
- 'SCALE': 3,
- 'ROTATION': 4,
- 'OPACITY': 5
-};
-
-/**
- * Enumeration of easing type.
- * @enum {number}
- * @const
- */
-api.EasingType = {
- 'LINEAR': 0,
- 'CUBICBEZIER': 1,
- 'EASEIN': 2,
- 'EASEOUT': 3,
- 'EASEINOUT': 4
-};
-
-/** @const */ var DEFAULT_EASING_POW = 2;
-/** @const */ var DEFAULT_CUBIC_BEZIER_P1X = 0.25;
-/** @const */ var DEFAULT_CUBIC_BEZIER_P1Y = 0;
-/** @const */ var DEFAULT_CUBIC_BEZIER_P2X = 0.75;
-/** @const */ var DEFAULT_CUBIC_BEZIER_P2Y = 1;
-
-/**
- * Abstract easing base class.
- * @abstract
- */
-api.Easing = class {
- constructor(type) {
- this.type = type;
- }
-};
-
-api.LinearEasing = class extends api.Easing {
- constructor() {
- super(api.EasingType.LINEAR);
- }
-};
-
-api.CubicBezierEasing = class extends api.Easing {
- constructor(
- p1x = DEFAULT_CUBIC_BEZIER_P1X,
- p1y = DEFAULT_CUBIC_BEZIER_P1Y,
- p2x = DEFAULT_CUBIC_BEZIER_P2X,
- p2y = DEFAULT_CUBIC_BEZIER_P2Y) {
- super(api.EasingType.CUBICBEZIER);
- this.p1x = p1x;
- this.p1y = p1y;
- this.p2x = p2x;
- this.p2y = p2y;
- }
-};
-
-api.InEasing = class extends api.Easing {
- constructor(pow = DEFAULT_EASING_POW) {
- super(api.EasingType.EASEIN);
- this.pow = pow;
- }
-};
-
-api.OutEasing = class extends api.Easing {
- constructor(pow = DEFAULT_EASING_POW) {
- super(api.EasingType.EASEOUT);
- this.pow = pow;
- }
-};
-
-api.InOutEasing = class extends api.Easing {
- constructor(pow = DEFAULT_EASING_POW) {
- super(api.EasingType.EASEINOUT);
- this.pow = pow;
- }
-}
-
-/**
- * Base animation class. An animation can vary only one object property.
- * @struct
- */
-api.Animation = class {
- constructor(elementId, durationMs) {
- /** @private {number} */
- this.id = -1;
- /** @private {number} */
- this.meshId = elementId;
- /** @private {number} */
- this.property = -1;
- /** @private {Object} */
- this.to = {};
- /** @private {Object} */
- this.easing = new api.LinearEasing();
-
- // How many milliseconds in the future to start the animation.
- /** @private {number} */
- this.startInMillis = 0.0;
-
- // Duration of the animation (milliseconds).
- /** @private {number} */
- this.durationMillis = durationMs;
- }
-
- /**
- * Set the id of the animation.
- * @param {number} id
- */
- setId(id) {
- this.id = id;
- }
-
- /**
- * Set the animation's final element size.
- * @param {number} width
- * @param {number} height
- */
- setSize(width, height) {
- this.property = api.Property.SIZE;
- this.to.x = width;
- this.to.y = height;
- }
-
- /**
- * Set the animation's final element scale.
- * @param {number} x
- * @param {number} y
- * @param {number} z
- */
- setScale(x, y, z) {
- this.property = api.Property.SCALE;
- this.to.x = x;
- this.to.y = y;
- this.to.z = z;
- }
-
- /**
- * Set the animation's final element rotation.
- * @param {number} x
- * @param {number} y
- * @param {number} z
- * @param {number} a
- */
- setRotation(x, y, z, a) {
- this.property = api.Property.ROTATION;
- this.to.x = x;
- this.to.y = y;
- this.to.z = z;
- this.to.a = a;
- }
-
- /**
- * Set the animation's final element translation.
- * @param {number} x
- * @param {number} y
- * @param {number} z
- */
- setTranslation(x, y, z) {
- this.property = api.Property.TRANSLATION;
- this.to.x = x;
- this.to.y = y;
- this.to.z = z;
- }
-
- /**
- * Set the animation's final element opacity.
- * @param {number} opacity
- */
- setOpacity(opacity) {
- this.property = api.Property.OPACITY;
- this.to.x = opacity;
- }
-
- /**
- * Set the animation's easing.
- * @param {api.Easing} easing
- */
- setEasing(easing) {
- this.easing = easing;
- }
-};
-
-/**
- * Abstract class handling webui command calls from native. The UI must
- * subclass this and override the handlers.
- * @abstract
- */
-api.NativeCommandHandler = class {
- /**
- * @param {api.Mode} mode
- */
- onSetMode(mode) {}
-
- /**
- * Handles entering or exiting full-screen mode.
- * @param {boolean} fullscreen
- */
- onSetFullscreen(fullscreen) {}
-
- /**
- * A controller app button click has happened.
- */
- onAppButtonClicked() {}
-
- /**
- * Handles a change in the visible page's security level.
- * @param {number} level
- */
- onSetSecurityLevel(level) {}
-
- /**
- * Handles a change in the WebVR-specific secure-origin state. If |secure| is
- * false, the UI must convey appropriate security warnings.
- * @param {boolean} secure
- */
- onSetWebVRSecureOrigin(secure) {}
-
- /**
- * Handles enabling of a development-oriented control to reload the UI.
- * @param {boolean} enabled
- */
- onSetReloadUiCapabilityEnabled(enabled) {}
-
- /**
- * Handles a new URL, specifying the host and path compoments.
- * @param {string} host
- * @param {string} path
- */
- onSetUrl(host, path) {}
-
- /**
- * Handle a change in loading state (used to show a spinner or other loading
- * indicator).
- * @param {boolean} loading
- */
- onSetLoading(loading) {}
-
- /**
- * Handle a change in loading progress. Progress is supplied as a number
- * between 0.0 and 1.0.
- * @param {boolean} progress
- */
- onSetLoadingProgress(progress) {}
-
- /**
- * Handle a change in the set of omnibox suggestions.
- * @param {Array<Object>} suggestions Array of suggestions with string members
- * |description| and |url|.
- */
- onSetOmniboxSuggestions(suggestions) {}
-
- /**
- * Handle a new set of tabs, overwriting the previous state.
- * @param {Array<Object>} tabs Array of tab states.
- */
- onSetTabs(tabs) {}
-
- /**
- * Update (or add if not present) a tab.
- * @param {Object} tab
- */
- onUpdateTab(tab) {}
-
- /**
- * Remove a tab.
- * @param {Object} tab
- */
- onRemoveTab(tab) {}
-
- /**
- * This function is executed after command parsing completes.
- */
- onCommandHandlerFinished() {}
-
- /** @final */
- handleCommand(dict) {
- if ('mode' in dict) {
- this.onSetMode(dict['mode']);
- }
- if ('fullscreen' in dict) {
- this.onSetFullscreen(dict['fullscreen'])
- }
- if ('appButtonClicked' in dict) {
- this.onAppButtonClicked();
- }
- if ('securityLevel' in dict) {
- this.onSetSecurityLevel(dict['securityLevel']);
- }
- if ('webVRSecureOrigin' in dict) {
- this.onSetWebVRSecureOrigin(dict['webVRSecureOrigin']);
- }
- if ('enableReloadUi' in dict) {
- this.onSetReloadUiCapabilityEnabled(dict['enableReloadUi']);
- }
- if ('url' in dict) {
- let url = dict['url'];
- this.onSetUrl(url['host'], url['path']);
- }
- if ('loading' in dict) {
- this.onSetLoading(dict['loading']);
- }
- if ('loadProgress' in dict) {
- this.onSetLoadingProgress(dict['loadProgress']);
- }
- if ('suggestions' in dict) {
- this.onSetOmniboxSuggestions(dict['suggestions']);
- }
- if ('setTabs' in dict) {
- this.onSetTabs(dict['setTabs']);
- }
- if ('updateTab' in dict) {
- this.onUpdateTab(dict['updateTab']);
- }
- if ('removeTab' in dict) {
- this.onRemoveTab(dict['removeTab']);
- }
-
- this.onCommandHandlerFinished()
- }
-};
diff --git a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js b/chromium/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
deleted file mode 100644
index 4ed691a93cc..00000000000
--- a/chromium/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
+++ /dev/null
@@ -1,167 +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.
-
-var scene = {};
-
-/**
- * The scene class assists in managing element and animations in the UI. It
- * allows UI update API commands to be queued in batches, and manages allocation
- * of element and animation IDs.
- *
- * Examples:
- *
- * var ui = new scene.Scene();
- *
- * // Add an element.
- * var el = new api.UiElement(100, 200, 50, 50);
- * el.setSize(buttonWidth, buttonHeight);
- *
- * // Anchor it to the bottom of the content quad.
- * el.setParentId(contentQuadId);
- * el.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YBOTTOM);
- *
- * // Place it just below the content quad edge.
- * el.setTranslation(0, -0.2, 0.0);
- *
- * // Add it to the ui.
- * var buttonId = ui.addElement(el);
- * ui.flush();
- *
- * // Make the button twice as big.
- * var update = new api.UiElementUpdate();
- * update.setSize(bunttonWidth * 2, buttonHeight * 2);
- * ui.updateElement(buttonId, update);
- * ui.flush();
- *
- * // Animate the button size back to its original size, over 250 ms.
- * var resize = new api.Animation(buttonId, 250);
- * resize.setSize(buttonWidth, buttonHeight);
- * ui.addAnimation(resize);
- * ui.flush();
- *
- * @struct
- */
-scene.Scene = class {
- constructor() {
- /** @private {number} */
- this.idIndex = 1;
- /** @private {Array<Object>} */
- this.commands = [];
- /** @private {!Set<number>} */
- this.elements = new Set();
- /** @private {!Object} */
- this.animations = [];
- }
-
- /**
- * Flush all queued commands to native.
- */
- flush() {
- api.sendCommands(this.commands);
- this.commands = [];
- }
-
- /**
- * Add a new UiElementUpdate to the scene, returning the ID assigned.
- * @param {api.UiElementUpdate} element
- */
- addElement(element) {
- var id = this.idIndex++;
- element.setId(id);
- this.commands.push(
- {'type': api.Command.ADD_ELEMENT, 'data': element.properties});
- this.elements.add(id);
- return id;
- }
-
- /**
- * Update an existing element, according to a UiElementUpdate object.
- * @param {number} id
- * @param {api.UiElementUpdate} update
- */
- updateElement(id, update) {
- // To-do: Make sure ID exists.
- update.setId(id);
- this.commands.push(
- {'type': api.Command.UPDATE_ELEMENT, 'data': update.properties});
- }
-
- /**
- * Remove an element from the scene.
- * @param {number} id
- */
- removeElement(id) {
- // To-do: Make sure ID exists.
- this.commands.push(
- {'type': api.Command.REMOVE_ELEMENT, 'data': {'id': id}});
- this.elements.delete(id);
- }
-
- /**
- * Add a new Animation to the scene, returning the ID assigned.
- * @param {api.Animation} animation
- */
- addAnimation(animation) {
- var id = this.idIndex++;
- animation.setId(id);
- this.commands.push({'type': api.Command.ADD_ANIMATION, 'data': animation});
- this.animations[id] = animation.meshId;
- return id;
- }
-
- /**
- * Remove an animation from the scene.
- *
- * Note that animations are flushed when they complete and are not required
- * to be removed. Also new animations of the same type will effectively
- * override the original so there is no need to remove in that scenario
- * either.
- *
- * @param {number} id
- */
- removeAnimation(id) {
- // To-do: Make sure ID exists.
- this.commands.push({
- 'type': api.Command.REMOVE_ANIMATION,
- 'data': {'id': id, 'meshId': this.animations[id]}
- });
- delete this.animations[id];
- }
-
- /**
- * Set the background color of the scene.
- * @param {{r: number, b: number, g: number, a: number}} color
- */
- setBackgroundColor(color) {
- this.commands.push(
- {'type': api.Command.UPDATE_BACKGROUND, 'data': {'color': color}});
- }
-
- /**
- * Set the radius of background-bounding sphere.
- * @param {number} distance
- */
- setBackgroundDistance(distance) {
- this.commands.push({
- 'type': api.Command.UPDATE_BACKGROUND,
- 'data': {'distance': distance}
- });
- }
-
- /**
- * Purge all elements in the scene.
- */
- purge() {
- var ids = Object.keys(this.animations);
- for (let id_key of ids) {
- var id = parseInt(id_key, 10);
- this.removeAnimation(id);
- }
- var ids = this.elements.values();
- for (let id of ids) {
- this.removeElement(id);
- }
- this.flush();
- }
-};
diff --git a/chromium/chrome/browser/resources/vulcanize.gni b/chromium/chrome/browser/resources/vulcanize.gni
index f241c07d379..69db5294cc8 100644
--- a/chromium/chrome/browser/resources/vulcanize.gni
+++ b/chromium/chrome/browser/resources/vulcanize.gni
@@ -98,3 +98,26 @@ template("polymer_css_build") {
] + invoker.input_files + [ "--output_files" ] + invoker.output_files
}
}
+
+template("unpak") {
+ action(target_name) {
+ script = "//chrome/browser/resources/unpack_pak.py"
+
+ inputs = [
+ "//chrome/browser/resources/unpack_pak.py",
+ ]
+
+ outputs = [
+ "$target_gen_dir/${invoker.out_folder}",
+ ]
+
+ deps = invoker.deps
+
+ args = [
+ "--out_folder",
+ rebase_path("$target_gen_dir/${invoker.out_folder}", root_build_dir),
+ "--pak_file",
+ rebase_path("$target_gen_dir/${invoker.pak_file}", root_build_dir),
+ ]
+ }
+}
diff --git a/chromium/chrome/browser/resources/vulcanize_gn.py b/chromium/chrome/browser/resources/vulcanize_gn.py
index 0cfca6e4118..309ab32be4b 100755
--- a/chromium/chrome/browser/resources/vulcanize_gn.py
+++ b/chromium/chrome/browser/resources/vulcanize_gn.py
@@ -70,9 +70,6 @@ _VULCANIZE_REDIRECT_ARGS = list(itertools.chain.from_iterable(map(
lambda m: ['--redirect', '"%s|%s"' % (m[0], m[1])], _URL_MAPPINGS)))
-_PAK_UNPACK_FOLDER = 'flattened'
-
-
def _undo_mapping(mappings, url):
for (redirect_url, file_path) in mappings:
if url.startswith(redirect_url):
@@ -117,10 +114,10 @@ def _update_dep_file(in_folder, args):
deps = [_undo_mapping(url_mappings, u) for u in request_list]
deps = map(os.path.normpath, deps)
- # If the input was a .pak file, the generated depfile should not list files
- # already in the .pak file.
- if args.input.endswith('.pak'):
- filter_url = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER)
+ # If the input was a folder holding an unpacked .pak file, the generated
+ # depfile should not list files already in the .pak file.
+ if args.input.endswith('.unpak'):
+ filter_url = args.input
deps = [d for d in deps if not d.startswith(filter_url)]
with open(os.path.join(_CWD, args.depfile), 'w') as f:
@@ -171,6 +168,10 @@ def _vulcanize(in_folder, args):
'--html', html_out_path,
'--js', js_out_path])
+ # Create an empty JS file if crisper did not create one.
+ if not os.path.isfile(js_out_path):
+ open(js_out_path, 'w').close()
+
node.RunNode([node_modules.PathToUglifyJs(), js_out_path,
'--comments', '"/Copyright|license|LICENSE|\<\/?if/"',
'--output', js_out_path])
@@ -198,19 +199,8 @@ def main(argv):
args.input = os.path.normpath(args.input)
args.out_folder = os.path.normpath(args.out_folder)
- vulcanize_input_folder = args.input
-
- # If a .pak file was specified, unpack that file first and pass the output to
- # vulcanize.
- if args.input.endswith('.pak'):
- import unpack_pak
- output_folder = os.path.join(args.out_folder, _PAK_UNPACK_FOLDER)
- unpack_pak.unpack(args.input, output_folder)
- vulcanize_input_folder = output_folder
-
- _vulcanize(vulcanize_input_folder, args)
-
- _update_dep_file(vulcanize_input_folder, args)
+ _vulcanize(args.input, args)
+ _update_dep_file(args.input, args)
if __name__ == '__main__':
diff --git a/chromium/chrome/browser/resources/webapks/about_webapks.css b/chromium/chrome/browser/resources/webapks/about_webapks.css
index 11ceac58b61..a6cbc37a6d5 100644
--- a/chromium/chrome/browser/resources/webapks/about_webapks.css
+++ b/chromium/chrome/browser/resources/webapks/about_webapks.css
@@ -46,3 +46,9 @@ body {
text-align: start;
white-space: nowrap;
}
+
+.app-property-value {
+ font-weight: normal;
+ text-align: start;
+ white-space: nowrap;
+}
diff --git a/chromium/chrome/browser/resources/webapks/about_webapks.js b/chromium/chrome/browser/resources/webapks/about_webapks.js
index ae929d6ed4c..9d5fb8f5869 100644
--- a/chromium/chrome/browser/resources/webapks/about_webapks.js
+++ b/chromium/chrome/browser/resources/webapks/about_webapks.js
@@ -4,10 +4,19 @@
/**
* @typedef {{
+ * name: string,
* shortName: string,
* packageName: string,
* shellApkVersion: number,
- * versionCode: number
+ * versionCode: number,
+ * uri: string,
+ * scope: string,
+ * manifestUrl: string,
+ * manifestStartUrl: string,
+ * displayMode: string,
+ * orientation: string,
+ * themeColor: string,
+ * backgroundColor: string,
* }}
*/
var WebApkInfo;
@@ -17,11 +26,12 @@ var WebApkInfo;
* |className| class.
*
* @param {string} text Text to be shown in the span.
+ * @param {string} type Type of element to be added such as 'div'.
* @param {string} className Class to be assigned to the new element.
* @return {Element} The created element.
*/
-function createSpanWithTextAndClass(text, className) {
- var element = createElementWithClassName('span', className);
+function createElementWithTextAndClass(text, type, className) {
+ var element = createElementWithClassName(type, className);
element.textContent = text;
return element;
}
@@ -41,29 +51,47 @@ function returnWebApksInfo(webApkList) {
}
/**
+ * @param {HTMLElement} webApkList List of elements which contain WebAPK
+ * attributes.
+ * @param {string} label Text that identifies the new element.
+ * @param {string} value Text to set in the new element.
+ */
+function addWebApkField(webApkList, label, value) {
+ var divElement =
+ createElementWithTextAndClass(label, 'div', 'app-property-label');
+ divElement.appendChild(
+ createElementWithTextAndClass(value, 'span', 'app-property-value'));
+ webApkList.appendChild(divElement);
+}
+
+/**
* Adds a new entry to the page with the information of a WebAPK.
*
* @param {WebApkInfo} webApkInfo Information about an installed WebAPK.
*/
function addWebApk(webApkInfo) {
- var webApkList = $('webapk-list');
+ /** @type {HTMLElement} */ var webApkList = $('webapk-list');
webApkList.appendChild(
- createSpanWithTextAndClass(webApkInfo.shortName, 'app-name'));
+ createElementWithTextAndClass(webApkInfo.name, 'span', 'app-name'));
- webApkList.appendChild(
- createSpanWithTextAndClass('Package name: ', 'app-property-label'));
- webApkList.appendChild(document.createTextNode(webApkInfo.packageName));
-
- webApkList.appendChild(document.createElement('br'));
- webApkList.appendChild(createSpanWithTextAndClass(
- 'Shell APK version: ', 'app-property-label'));
- webApkList.appendChild(document.createTextNode(webApkInfo.shellApkVersion));
+ webApkList.appendChild(createElementWithTextAndClass(
+ 'Short name: ', 'span', 'app-property-label'));
+ webApkList.appendChild(document.createTextNode(webApkInfo.shortName));
- webApkList.appendChild(document.createElement('br'));
- webApkList.appendChild(
- createSpanWithTextAndClass('Version code: ', 'app-property-label'));
- webApkList.appendChild(document.createTextNode(webApkInfo.versionCode));
+ addWebApkField(webApkList, 'Package name: ', webApkInfo.packageName);
+ addWebApkField(
+ webApkList, 'Shell APK version: ', "" + webApkInfo.shellApkVersion);
+ addWebApkField(webApkList, 'Version code: ', "" + webApkInfo.versionCode);
+ addWebApkField(webApkList, 'URI: ', webApkInfo.uri);
+ addWebApkField(webApkList, 'Scope: ', webApkInfo.scope);
+ addWebApkField(webApkList, 'Manifest URL: ', webApkInfo.manifestUrl);
+ addWebApkField(
+ webApkList, 'Manifest Start URL: ', webApkInfo.manifestStartUrl);
+ addWebApkField(webApkList, 'Display Mode: ', webApkInfo.displayMode);
+ addWebApkField(webApkList, 'Orientation: ', webApkInfo.orientation);
+ addWebApkField(webApkList, 'Theme color: ', webApkInfo.themeColor);
+ addWebApkField(webApkList, 'Background color: ', webApkInfo.backgroundColor);
}
document.addEventListener('DOMContentLoaded', function() {
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_factory.cc b/chromium/chrome/browser/spellchecker/spellcheck_factory.cc
index 3857256a3d4..9d94c21c420 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_factory.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_factory.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/spellchecker/spellcheck_factory.h"
+#include "base/memory/ptr_util.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/grit/locale_settings.h"
@@ -69,7 +70,7 @@ KeyedService* SpellcheckServiceFactory::BuildServiceInstanceFor(
void SpellcheckServiceFactory::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* user_prefs) {
user_prefs->RegisterListPref(spellcheck::prefs::kSpellCheckDictionaries,
- new base::ListValue);
+ base::MakeUnique<base::ListValue>());
// Continue registering kSpellCheckDictionary for preference migration.
// TODO(estade): IDS_SPELLCHECK_DICTIONARY should be an ASCII string.
user_prefs->RegisterStringPref(
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_message_filter_platform_mac_browsertest.cc b/chromium/chrome/browser/spellchecker/spellcheck_message_filter_platform_mac_browsertest.cc
index 4045425adb3..3f9ddaefc9b 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_message_filter_platform_mac_browsertest.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_message_filter_platform_mac_browsertest.cc
@@ -4,10 +4,12 @@
#include "components/spellcheck/browser/spellcheck_message_filter_platform.h"
+#include <memory>
#include <tuple>
+#include <vector>
#include "base/command_line.h"
-#include "base/memory/scoped_vector.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
@@ -26,12 +28,12 @@ class TestingSpellCheckMessageFilter : public SpellCheckMessageFilterPlatform {
: SpellCheckMessageFilterPlatform(0), quit_closure_(quit_closure) {}
bool Send(IPC::Message* message) override {
- sent_messages_.push_back(message);
+ sent_messages_.push_back(base::WrapUnique(message));
main_thread_task_runner_->PostTask(FROM_HERE, quit_closure_);
return true;
}
- ScopedVector<IPC::Message> sent_messages_;
+ std::vector<std::unique_ptr<IPC::Message>> sent_messages_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_ =
base::ThreadTaskRunnerHandle::Get();
const base::Closure quit_closure_;
@@ -54,17 +56,16 @@ IN_PROC_BROWSER_TEST_F(SpellCheckMessageFilterPlatformMacBrowserTest,
target->OnMessageReceived(to_be_received);
run_loop.Run();
- EXPECT_EQ(1U, target->sent_messages_.size());
+ ASSERT_EQ(1U, target->sent_messages_.size());
SpellCheckMsg_RespondTextCheck::Param params;
bool ok = SpellCheckMsg_RespondTextCheck::Read(
- target->sent_messages_[0], &params);
- std::vector<SpellCheckResult> sent_results = std::get<2>(params);
-
+ target->sent_messages_[0].get(), &params);
EXPECT_TRUE(ok);
- EXPECT_EQ(1U, sent_results.size());
+
+ std::vector<SpellCheckResult> sent_results = std::get<2>(params);
+ ASSERT_EQ(1U, sent_results.size());
EXPECT_EQ(sent_results[0].location, 0);
EXPECT_EQ(sent_results[0].length, 2);
- EXPECT_EQ(sent_results[0].decoration,
- SpellCheckResult::SPELLING);
+ EXPECT_EQ(sent_results[0].decoration, SpellCheckResult::SPELLING);
}
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc b/chromium/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
index 35a367b96fa..62d445f9a7e 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_message_filter_unittest.cc
@@ -5,9 +5,12 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <tuple>
+#include <vector>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_message_filter.h"
@@ -26,7 +29,7 @@ class TestingSpellCheckMessageFilter : public SpellCheckMessageFilter {
spellcheck_(new SpellcheckService(&profile_)) {}
bool Send(IPC::Message* message) override {
- sent_messages.push_back(message);
+ sent_messages.push_back(base::WrapUnique(message));
return true;
}
@@ -45,7 +48,7 @@ class TestingSpellCheckMessageFilter : public SpellCheckMessageFilter {
}
#endif
- ScopedVector<IPC::Message> sent_messages;
+ std::vector<std::unique_ptr<IPC::Message>> sent_messages;
private:
~TestingSpellCheckMessageFilter() override {}
@@ -101,11 +104,11 @@ TEST(SpellCheckMessageFilterTest, OnTextCheckCompleteTestCustomDictionary) {
new TestingSpellCheckMessageFilter);
filter->GetSpellcheckService()->GetCustomDictionary()->AddWord(kCustomWord);
filter->OnTextCheckComplete(kRouteId, kCallbackId, kSuccess, kText, results);
- EXPECT_EQ(static_cast<size_t>(1), filter->sent_messages.size());
+ ASSERT_EQ(1U, filter->sent_messages.size());
SpellCheckMsg_RespondSpellingService::Param params;
bool ok = SpellCheckMsg_RespondSpellingService::Read(
- filter->sent_messages[0], &params);
+ filter->sent_messages[0].get(), &params);
int sent_identifier = std::get<0>(params);
bool sent_success = std::get<1>(params);
base::string16 sent_text = std::get<2>(params);
@@ -114,7 +117,7 @@ TEST(SpellCheckMessageFilterTest, OnTextCheckCompleteTestCustomDictionary) {
EXPECT_EQ(kCallbackId, sent_identifier);
EXPECT_EQ(kSuccess, sent_success);
EXPECT_EQ(kText, sent_text);
- EXPECT_EQ(static_cast<size_t>(1), sent_results.size());
+ ASSERT_EQ(1U, sent_results.size());
EXPECT_EQ(kDecoration, sent_results[0].decoration);
EXPECT_EQ(kLocation, sent_results[0].location);
EXPECT_EQ(kLength, sent_results[0].length);
@@ -132,14 +135,14 @@ TEST(SpellCheckMessageFilterTest, OnTextCheckCompleteTest) {
new TestingSpellCheckMessageFilter);
filter->OnTextCheckComplete(1, 1, true, base::ASCIIToUTF16("Helllo walrd"),
results);
- EXPECT_EQ(static_cast<size_t>(1), filter->sent_messages.size());
+ ASSERT_EQ(1U, filter->sent_messages.size());
SpellCheckMsg_RespondSpellingService::Param params;
bool ok = SpellCheckMsg_RespondSpellingService::Read(
- filter->sent_messages[0], & params);
- base::string16 sent_text = std::get<2>(params);
- std::vector<SpellCheckResult> sent_results = std::get<3>(params);
+ filter->sent_messages[0].get(), &params);
EXPECT_TRUE(ok);
- EXPECT_EQ(static_cast<size_t>(2), sent_results.size());
+
+ std::vector<SpellCheckResult> sent_results = std::get<3>(params);
+ EXPECT_EQ(2U, sent_results.size());
}
#endif
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_service.cc b/chromium/chrome/browser/spellchecker/spellcheck_service.cc
index d07712f5fec..e496d8909d5 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_service.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_service.cc
@@ -127,7 +127,7 @@ void SpellcheckService::GetDictionaries(base::SupportsUserData* browser_context,
for (const auto& value :
*prefs->GetList(spellcheck::prefs::kSpellCheckDictionaries)) {
std::string dictionary;
- if (value->GetAsString(&dictionary))
+ if (value.GetAsString(&dictionary))
spellcheck_dictionaries.insert(dictionary);
}
@@ -216,7 +216,7 @@ void SpellcheckService::LoadHunspellDictionaries() {
for (const auto& dictionary_value : *dictionary_values) {
std::string dictionary;
- dictionary_value->GetAsString(&dictionary);
+ dictionary_value.GetAsString(&dictionary);
hunspell_dictionaries_.push_back(
base::MakeUnique<SpellcheckHunspellDictionary>(
dictionary,
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
index 13deefa92cf..0c3895af3d3 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
@@ -129,10 +130,10 @@ class SpellcheckServiceBrowserTest : public InProcessBrowserTest {
std::string GetMultilingualDictionaries() {
const base::ListValue* list_value =
prefs_->GetList(spellcheck::prefs::kSpellCheckDictionaries);
- std::vector<std::string> dictionaries;
+ std::vector<base::StringPiece> dictionaries;
for (const auto& item_value : *list_value) {
- std::string dictionary;
- EXPECT_TRUE(item_value->GetAsString(&dictionary));
+ base::StringPiece dictionary;
+ EXPECT_TRUE(item_value.GetAsString(&dictionary));
dictionaries.push_back(dictionary);
}
return base::JoinString(dictionaries, ",");
@@ -235,17 +236,12 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
}
-// Flaky on Windows, see https://crbug.com/611029.
-#if defined(OS_WIN)
-#define MAYBE_StartWithoutLanguages DISABLED_StartWithoutLanguages
-#else
-#define MAYBE_StartWithoutLanguages StartWithoutLanguages
-#endif
// Starting without spellcheck languages should send the 'disable spellcheck'
// message to the renderer. Consequently adding spellchecking languages should
// enable spellcheck.
+// Flaky, see https://crbug.com/600153
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
- MAYBE_StartWithoutLanguages) {
+ DISABLED_StartWithoutLanguages) {
InitSpellcheck(true, "", "");
EXPECT_FALSE(GetFirstEnableSpellcheckMessageParam());
diff --git a/chromium/chrome/browser/ui/BUILD.gn b/chromium/chrome/browser/ui/BUILD.gn
index 300789b27fe..1bb2302efd9 100644
--- a/chromium/chrome/browser/ui/BUILD.gn
+++ b/chromium/chrome/browser/ui/BUILD.gn
@@ -25,9 +25,11 @@ config("ui_warnings") {
# Use a static library here because many test binaries depend on this but don't
# require many files from it. This makes linking more efficient.
split_static_library("ui") {
- # Split into multiple static libraries on Windows official builds, where we
- # run into a 2GB max size limit.
- if (is_win && is_official_build) {
+ # Split into multiple static libraries on Windows builds. We have hit size
+ # limits on Windows official builds and on goma builds when symbol_level = 2
+ # is selected. Always splitting on Windows builds is simpler than trying to
+ # perfectly calculate the scenarios where it is required.
+ if (is_win) {
split_count = 5
} else {
split_count = 1
@@ -66,6 +68,7 @@ split_static_library("ui") {
"autofill/password_generation_popup_observer.h",
"autofill/password_generation_popup_view.cc",
"autofill/password_generation_popup_view.h",
+ "autofill/popup_constants.h",
"autofill/popup_controller_common.cc",
"autofill/popup_controller_common.h",
"autofill/popup_view_common.cc",
@@ -88,6 +91,7 @@ split_static_library("ui") {
"browser_commands_chromeos.h",
"browser_commands_mac.cc",
"browser_commands_mac.h",
+ "browser_dialogs.cc",
"browser_dialogs.h",
"browser_mac.cc",
"browser_mac.h",
@@ -113,6 +117,10 @@ split_static_library("ui") {
"login/login_interstitial_delegate.h",
"navigation_correction_tab_observer.cc",
"navigation_correction_tab_observer.h",
+ "page_info/page_info.cc",
+ "page_info/page_info.h",
+ "page_info/page_info_ui.cc",
+ "page_info/page_info_ui.h",
"passwords/account_avatar_fetcher.cc",
"passwords/account_avatar_fetcher.h",
"passwords/manage_passwords_state.cc",
@@ -122,6 +130,7 @@ split_static_library("ui") {
"passwords/password_manager_presenter.cc",
"passwords/password_manager_presenter.h",
"passwords/password_ui_view.h",
+ "permission_bubble/permission_prompt.h",
"platform_keys_certificate_selector_chromeos.h",
"prefs/prefs_tab_helper.cc",
"prefs/prefs_tab_helper.h",
@@ -149,8 +158,6 @@ split_static_library("ui") {
"search/search_model_observer.h",
"search/search_tab_helper.cc",
"search/search_tab_helper.h",
- "search/search_tab_helper_delegate.cc",
- "search/search_tab_helper_delegate.h",
"search_engines/edit_search_engine_controller.cc",
"search_engines/edit_search_engine_controller.h",
"search_engines/keyword_editor_controller.cc",
@@ -194,11 +201,6 @@ split_static_library("ui") {
"views/platform_keys_certificate_selector_chromeos.cc",
"views/platform_keys_certificate_selector_chromeos.h",
"web_contents_sizer.h",
- "website_settings/permission_prompt.h",
- "website_settings/website_settings.cc",
- "website_settings/website_settings.h",
- "website_settings/website_settings_ui.cc",
- "website_settings/website_settings_ui.h",
"webui/about_ui.cc",
"webui/about_ui.h",
"webui/bluetooth_internals/bluetooth_internals_ui.cc",
@@ -239,6 +241,8 @@ split_static_library("ui") {
"webui/chromeos/login/auto_enrollment_check_screen_handler.h",
"webui/chromeos/login/base_screen_handler.cc",
"webui/chromeos/login/base_screen_handler.h",
+ "webui/chromeos/login/base_webui_handler.cc",
+ "webui/chromeos/login/base_webui_handler.h",
"webui/chromeos/login/controller_pairing_screen_handler.cc",
"webui/chromeos/login/controller_pairing_screen_handler.h",
"webui/chromeos/login/core_oobe_handler.cc",
@@ -247,6 +251,8 @@ split_static_library("ui") {
"webui/chromeos/login/device_disabled_screen_handler.h",
"webui/chromeos/login/enable_debugging_screen_handler.cc",
"webui/chromeos/login/enable_debugging_screen_handler.h",
+ "webui/chromeos/login/encryption_migration_screen_handler.cc",
+ "webui/chromeos/login/encryption_migration_screen_handler.h",
"webui/chromeos/login/enrollment_screen_handler.cc",
"webui/chromeos/login/enrollment_screen_handler.h",
"webui/chromeos/login/error_screen_handler.cc",
@@ -267,6 +273,7 @@ split_static_library("ui") {
"webui/chromeos/login/kiosk_enable_screen_handler.h",
"webui/chromeos/login/l10n_util.cc",
"webui/chromeos/login/l10n_util.h",
+ "webui/chromeos/login/native_window_delegate.h",
"webui/chromeos/login/network_dropdown.cc",
"webui/chromeos/login/network_dropdown.h",
"webui/chromeos/login/network_dropdown_handler.cc",
@@ -390,6 +397,8 @@ split_static_library("ui") {
"webui/predictors/predictors_handler.h",
"webui/predictors/predictors_ui.cc",
"webui/predictors/predictors_ui.h",
+ "webui/prefs_internals_source.cc",
+ "webui/prefs_internals_source.h",
"webui/profiler_ui.cc",
"webui/profiler_ui.h",
"webui/quota_internals/quota_internals_handler.cc",
@@ -474,7 +483,7 @@ split_static_library("ui") {
"//chrome/app/theme:theme_resources",
"//chrome/browser:resource_prefetch_predictor_proto",
"//chrome/browser/devtools",
- "//chrome/browser/ui/webui/engagement:mojo_bindings",
+ "//chrome/browser/engagement:mojo_bindings",
"//chrome/browser/ui/webui/omnibox:mojo_bindings",
"//chrome/browser/ui/webui/usb_internals:mojo_bindings",
"//chrome/common",
@@ -509,7 +518,7 @@ split_static_library("ui") {
"//components/google/core/browser",
"//components/guest_view/browser",
"//components/history/content/browser",
- "//components/image_fetcher",
+ "//components/image_fetcher/core",
"//components/infobars/core",
"//components/invalidation/impl",
"//components/keyed_service/content",
@@ -552,6 +561,7 @@ split_static_library("ui") {
"//components/startup_metric_utils/browser:lib",
"//components/strings",
"//components/subresource_filter/content/browser",
+ "//components/subresource_filter/core/browser:browser",
"//components/suggestions/proto",
"//components/supervised_user_error_page",
"//components/sync",
@@ -627,6 +637,7 @@ split_static_library("ui") {
deps += [
"//components/drive",
"//extensions/browser",
+ "//extensions/strings",
]
}
@@ -634,6 +645,13 @@ split_static_library("ui") {
defines += [ "USE_CRAS" ]
}
+ if (is_android || is_linux) {
+ sources += [
+ "webui/sandbox_internals_ui.cc",
+ "webui/sandbox_internals_ui.h",
+ ]
+ }
+
if (!is_android) {
sources += [
"apps/app_info_dialog.h",
@@ -681,6 +699,7 @@ split_static_library("ui") {
"browser_instant_controller.h",
"browser_list.cc",
"browser_list.h",
+ "browser_list_observer.h",
"browser_live_tab_context.cc",
"browser_live_tab_context.h",
"browser_navigator.cc",
@@ -767,6 +786,10 @@ split_static_library("ui") {
"omnibox/chrome_omnibox_navigation_observer.h",
"omnibox/clipboard_utils.cc",
"omnibox/clipboard_utils.h",
+ "page_info/page_info_infobar_delegate.cc",
+ "page_info/page_info_infobar_delegate.h",
+ "page_info/permission_menu_model.cc",
+ "page_info/permission_menu_model.h",
"passwords/manage_passwords_bubble_model.cc",
"passwords/manage_passwords_bubble_model.h",
"passwords/manage_passwords_icon_view.h",
@@ -786,6 +809,8 @@ split_static_library("ui") {
"pdf/adobe_reader_info_win.h",
"pdf/chrome_pdf_web_contents_helper_client.cc",
"pdf/chrome_pdf_web_contents_helper_client.h",
+ "permission_bubble/chooser_bubble_delegate.cc",
+ "permission_bubble/chooser_bubble_delegate.h",
"sad_tab.cc",
"sad_tab.h",
"sad_tab_helper.cc",
@@ -800,10 +825,6 @@ split_static_library("ui") {
"settings_window_manager.cc",
"settings_window_manager.h",
"settings_window_manager_observer.h",
- "signin_view_controller.cc",
- "signin_view_controller.h",
- "signin_view_controller_delegate.cc",
- "signin_view_controller_delegate.h",
"singleton_tabs.cc",
"singleton_tabs.h",
"startup/automation_infobar_delegate.cc",
@@ -886,14 +907,10 @@ split_static_library("ui") {
"uma_browsing_activity_observer.h",
"unload_controller.cc",
"unload_controller.h",
+ "unload_controller_web_contents_delegate.cc",
+ "unload_controller_web_contents_delegate.h",
"user_manager.cc",
"user_manager.h",
- "website_settings/chooser_bubble_delegate.cc",
- "website_settings/chooser_bubble_delegate.h",
- "website_settings/permission_menu_model.cc",
- "website_settings/permission_menu_model.h",
- "website_settings/website_settings_infobar_delegate.cc",
- "website_settings/website_settings_infobar_delegate.h",
"webui/app_launcher_login_handler.cc",
"webui/app_launcher_login_handler.h",
"webui/bookmarks_ui.cc",
@@ -926,6 +943,7 @@ split_static_library("ui") {
"webui/help/version_updater_mac.h",
"webui/help/version_updater_mac.mm",
"webui/help/version_updater_win.cc",
+ "webui/help/version_updater_win.h",
"webui/history_login_handler.cc",
"webui/history_login_handler.h",
"webui/identity_internals_ui.cc",
@@ -1179,6 +1197,7 @@ split_static_library("ui") {
"//components/proximity_auth/webui",
"//components/web_modal",
"//device/bluetooth",
+ "//extensions/common:mojo",
"//mash/public/interfaces",
"//ui/vector_icons",
]
@@ -1210,6 +1229,7 @@ split_static_library("ui") {
deps += [
"//chrome/browser/safe_browsing:chunk_proto",
"//chrome/common/safe_browsing:proto",
+ "//components/safe_browsing:csd_proto",
]
}
@@ -1257,8 +1277,10 @@ split_static_library("ui") {
"//components/drive:drive_chromeos",
"//components/exo",
"//components/login",
+ "//device/power_save_blocker",
"//ui/base/ime",
"//ui/chromeos",
+ "//ui/chromeos/events",
]
if (enable_rlz) {
deps += [ "//chrome/browser:rlz" ]
@@ -1269,8 +1291,6 @@ split_static_library("ui") {
}
if (use_ash) {
sources += [
- "ash/app_launcher_id.cc",
- "ash/app_launcher_id.h",
"ash/app_list/app_list_controller_ash.cc",
"ash/app_list/app_list_controller_ash.h",
"ash/app_list/app_list_presenter_delegate_mus.cc",
@@ -1347,8 +1367,6 @@ split_static_library("ui") {
"ash/launcher/launcher_extension_app_updater.h",
"ash/launcher/launcher_favicon_loader.cc",
"ash/launcher/launcher_favicon_loader.h",
- "ash/launcher/launcher_item_controller.cc",
- "ash/launcher/launcher_item_controller.h",
"ash/launcher/multi_profile_app_window_launcher_controller.cc",
"ash/launcher/multi_profile_app_window_launcher_controller.h",
"ash/launcher/multi_profile_browser_status_monitor.cc",
@@ -1399,6 +1417,7 @@ split_static_library("ui") {
deps += [
"//ash",
"//ash:ash_with_content",
+ "//ash/mus:lib",
"//ash/public/cpp:ash_public_cpp",
"//ash/resources/vector_icons",
"//ash/strings",
@@ -1411,11 +1430,13 @@ split_static_library("ui") {
"//ui/keyboard:mojom",
]
} else { # Not ash.
- sources += [ "views/touch_uma/touch_uma.cc" ]
+ sources += [
+ "views/touch_uma/touch_uma.cc",
+ "views/touch_uma/touch_uma.h",
+ ]
}
if (toolkit_views) {
sources += [
- "autofill/save_card_bubble_controller.h",
"autofill/save_card_bubble_controller_impl.cc",
"autofill/save_card_bubble_controller_impl.h",
"autofill/save_card_bubble_view.h",
@@ -1443,6 +1464,8 @@ split_static_library("ui") {
"views/apps/native_app_window_frame_view_mac.mm",
"views/autofill/card_unmask_prompt_views.cc",
"views/autofill/card_unmask_prompt_views.h",
+ "views/autofill/view_util.cc",
+ "views/autofill/view_util.h",
"views/bookmarks/bookmark_bubble_view.cc",
"views/bookmarks/bookmark_bubble_view.h",
"views/bookmarks/bookmark_editor_view.cc",
@@ -1475,18 +1498,21 @@ split_static_library("ui") {
"views/extensions/chooser_dialog_view.cc",
"views/extensions/chooser_dialog_view.h",
"views/extensions/extension_install_dialog_view.cc",
+ "views/extensions/extension_install_dialog_view.h",
"views/extensions/extension_keybinding_registry_views.cc",
"views/extensions/extension_keybinding_registry_views.h",
"views/frame/native_widget_mac_frameless_nswindow.h",
"views/frame/native_widget_mac_frameless_nswindow.mm",
"views/global_error_bubble_view.cc",
"views/global_error_bubble_view.h",
- "views/harmony/harmony_layout_delegate.cc",
- "views/harmony/harmony_layout_delegate.h",
- "views/harmony/layout_delegate.cc",
- "views/harmony/layout_delegate.h",
- "views/layout_utils.cc",
- "views/layout_utils.h",
+ "views/harmony/chrome_layout_provider.cc",
+ "views/harmony/chrome_layout_provider.h",
+ "views/harmony/chrome_typography.cc",
+ "views/harmony/chrome_typography.h",
+ "views/harmony/harmony_layout_provider.cc",
+ "views/harmony/harmony_layout_provider.h",
+ "views/harmony/harmony_typography_provider.cc",
+ "views/harmony/harmony_typography_provider.h",
"views/location_bar/location_bar_bubble_delegate_view.cc",
"views/location_bar/location_bar_bubble_delegate_view.h",
"views/login_handler_views.cc",
@@ -1494,12 +1520,24 @@ split_static_library("ui") {
"views/login_view.h",
"views/new_back_shortcut_bubble.cc",
"views/new_back_shortcut_bubble.h",
- "views/payments/contact_info_view_controller.cc",
- "views/payments/contact_info_view_controller.h",
+ "views/page_info/chosen_object_row.cc",
+ "views/page_info/chosen_object_row.h",
+ "views/page_info/chosen_object_row_observer.h",
+ "views/page_info/non_accessible_image_view.cc",
+ "views/page_info/non_accessible_image_view.h",
+ "views/page_info/page_info_bubble_view.cc",
+ "views/page_info/page_info_bubble_view.h",
+ "views/page_info/permission_selector_row.cc",
+ "views/page_info/permission_selector_row.h",
+ "views/page_info/permission_selector_row_observer.h",
"views/payments/credit_card_editor_view_controller.cc",
"views/payments/credit_card_editor_view_controller.h",
+ "views/payments/cvc_unmask_view_controller.cc",
+ "views/payments/cvc_unmask_view_controller.h",
"views/payments/editor_view_controller.cc",
"views/payments/editor_view_controller.h",
+ "views/payments/error_message_view_controller.cc",
+ "views/payments/error_message_view_controller.h",
"views/payments/order_summary_view_controller.cc",
"views/payments/order_summary_view_controller.h",
"views/payments/payment_method_view_controller.cc",
@@ -1519,8 +1557,12 @@ split_static_library("ui") {
"views/payments/payment_sheet_view_controller.h",
"views/payments/preselected_combobox_model.cc",
"views/payments/preselected_combobox_model.h",
- "views/payments/shipping_list_view_controller.cc",
- "views/payments/shipping_list_view_controller.h",
+ "views/payments/profile_list_view_controller.cc",
+ "views/payments/profile_list_view_controller.h",
+ "views/payments/shipping_address_editor_view_controller.cc",
+ "views/payments/shipping_address_editor_view_controller.h",
+ "views/payments/shipping_option_view_controller.cc",
+ "views/payments/shipping_option_view_controller.h",
"views/payments/validating_combobox.cc",
"views/payments/validating_combobox.h",
"views/payments/validating_textfield.cc",
@@ -1528,6 +1570,8 @@ split_static_library("ui") {
"views/payments/validation_delegate.h",
"views/payments/view_stack.cc",
"views/payments/view_stack.h",
+ "views/permission_bubble/permission_prompt_impl.cc",
+ "views/permission_bubble/permission_prompt_impl.h",
"views/subtle_notification_view.cc",
"views/subtle_notification_view.h",
"views/sync/bubble_sync_promo_view.cc",
@@ -1536,26 +1580,15 @@ split_static_library("ui") {
"views/sync/profile_signin_confirmation_dialog_views.h",
"views/task_manager_view.cc",
"views/task_manager_view.h",
+ "views/toolbar/toolbar_actions_bar_bubble_views.cc",
+ "views/toolbar/toolbar_actions_bar_bubble_views.h",
"views/update_recommended_message_box.cc",
"views/update_recommended_message_box.h",
- "views/website_settings/chosen_object_row.cc",
- "views/website_settings/chosen_object_row.h",
- "views/website_settings/chosen_object_row_observer.h",
- "views/website_settings/non_accessible_image_view.cc",
- "views/website_settings/non_accessible_image_view.h",
- "views/website_settings/permission_prompt_impl.cc",
- "views/website_settings/permission_prompt_impl.h",
- "views/website_settings/permission_selector_row.cc",
- "views/website_settings/permission_selector_row.h",
- "views/website_settings/permission_selector_row_observer.h",
- "views/website_settings/website_settings_popup_view.cc",
- "views/website_settings/website_settings_popup_view.h",
]
deps += [
"//chrome/browser/ui/views",
"//components/constrained_window",
- "//components/payments/content:payment_request_impl",
- "//components/payments/content:payment_validation",
+ "//components/payments/content",
"//components/payments/core",
"//services/ui/public/cpp/input_devices",
]
@@ -1774,10 +1807,6 @@ split_static_library("ui") {
"views/location_bar/location_bar_view.h",
"views/location_bar/location_icon_view.cc",
"views/location_bar/location_icon_view.h",
- "views/location_bar/page_action_image_view.cc",
- "views/location_bar/page_action_image_view.h",
- "views/location_bar/page_action_with_badge_view.cc",
- "views/location_bar/page_action_with_badge_view.h",
"views/location_bar/selected_keyword_view.cc",
"views/location_bar/selected_keyword_view.h",
"views/location_bar/star_view.cc",
@@ -1808,11 +1837,12 @@ split_static_library("ui") {
"views/passwords/manage_passwords_bubble_view.h",
"views/passwords/manage_passwords_icon_views.cc",
"views/passwords/manage_passwords_icon_views.h",
+ "views/permission_bubble/chooser_bubble_ui_view.cc",
+ "views/permission_bubble/chooser_bubble_ui_view.h",
+ "views/permission_bubble/permission_prompt_impl_views.cc",
"views/process_singleton_dialog_linux.cc",
"views/profiles/profile_indicator_icon.cc",
"views/profiles/profile_indicator_icon.h",
- "views/profiles/signin_view_controller_delegate_views.cc",
- "views/profiles/signin_view_controller_delegate_views.h",
"views/profiles/user_manager_view.cc",
"views/profiles/user_manager_view.h",
"views/proximity_auth/proximity_auth_error_bubble_view.cc",
@@ -1878,8 +1908,6 @@ split_static_library("ui") {
"views/toolbar/toolbar_action_view.cc",
"views/toolbar/toolbar_action_view.h",
"views/toolbar/toolbar_action_view_delegate_views.h",
- "views/toolbar/toolbar_actions_bar_bubble_views.cc",
- "views/toolbar/toolbar_actions_bar_bubble_views.h",
"views/toolbar/toolbar_button.cc",
"views/toolbar/toolbar_button.h",
"views/toolbar/toolbar_view.cc",
@@ -1893,9 +1921,6 @@ split_static_library("ui") {
"views/validation_message_bubble_view.h",
"views/webshare/webshare_target_picker_view.cc",
"views/webshare/webshare_target_picker_view.h",
- "views/website_settings/chooser_bubble_ui_view.cc",
- "views/website_settings/chooser_bubble_ui_view.h",
- "views/website_settings/permission_prompt_impl_views.cc",
]
if (use_aura) {
@@ -1923,6 +1948,13 @@ split_static_library("ui") {
deps += [ "//ui/views/mus" ]
}
+
+ if (!is_chromeos) {
+ sources += [
+ "views/profiles/signin_view_controller_delegate_views.cc",
+ "views/profiles/signin_view_controller_delegate_views.h",
+ ]
+ }
}
if (use_ash) {
sources += [
@@ -1964,6 +1996,10 @@ split_static_library("ui") {
"avatar_button_error_controller_delegate.h",
"external_protocol_dialog_delegate.cc",
"external_protocol_dialog_delegate.h",
+ "signin_view_controller.cc",
+ "signin_view_controller.h",
+ "signin_view_controller_delegate.cc",
+ "signin_view_controller_delegate.h",
"startup/default_browser_infobar_delegate.cc",
"startup/default_browser_infobar_delegate.h",
"startup/default_browser_prompt.cc",
@@ -2052,8 +2088,10 @@ split_static_library("ui") {
"aura/native_window_tracker_aura.h",
"aura/tab_contents/web_drag_bookmark_handler_aura.cc",
"aura/tab_contents/web_drag_bookmark_handler_aura.h",
+ "ime/ime_native_window.h",
"ime/ime_window.cc",
"ime/ime_window.h",
+ "ime/ime_window_observer.h",
"views/accelerator_utils_aura.cc",
"views/apps/app_window_desktop_native_widget_aura_win.cc",
"views/apps/app_window_desktop_native_widget_aura_win.h",
@@ -2082,7 +2120,7 @@ split_static_library("ui") {
"views/desktop_capture/desktop_media_source_view.cc",
"views/desktop_capture/desktop_media_source_view.h",
"views/dropdown_bar_host_aura.cc",
- "views/frame/browser_non_client_frame_view_factory_views.cc",
+ "views/frame/browser_non_client_frame_view_factory_chromeos.cc",
"views/ime/ime_window_frame_view.cc",
"views/ime/ime_window_frame_view.h",
"views/ime/ime_window_view.cc",
@@ -2093,8 +2131,6 @@ split_static_library("ui") {
"views/sad_tab_view.h",
"views/tab_contents/chrome_web_contents_view_delegate_views.cc",
"views/tab_contents/chrome_web_contents_view_delegate_views.h",
- "views/theme_profile_key.cc",
- "views/theme_profile_key.h",
"window_sizer/window_sizer_aura.cc",
]
deps += [
@@ -2106,6 +2142,7 @@ split_static_library("ui") {
]
if (!is_chromeos) {
sources += [
+ "views/frame/browser_non_client_frame_view_factory_views.cc",
"views/frame/desktop_browser_frame_aura.cc",
"views/frame/desktop_browser_frame_aura.h",
"views/message_center/message_center_frame_view.cc",
@@ -2115,9 +2152,6 @@ split_static_library("ui") {
]
}
}
- if (ui_compositor_image_transport) {
- deps += [ "//ui/gl" ]
- }
if (use_nss_certs) {
sources += [
"crypto_module_delegate_nss.cc",
@@ -2163,6 +2197,7 @@ split_static_library("ui") {
if (is_android) {
deps += [
"//components/navigation_interception",
+ "//components/subresource_filter/core/browser:browser",
"//crypto:platform",
"//device/usb/mojo",
"//device/usb/public/interfaces",
@@ -2223,11 +2258,14 @@ split_static_library("ui") {
"android/infobars/simple_confirm_infobar_builder.h",
"android/infobars/subresource_filter_infobar.cc",
"android/infobars/subresource_filter_infobar.h",
+ "android/infobars/translate_compact_infobar.cc",
+ "android/infobars/translate_compact_infobar.h",
"android/infobars/translate_infobar.cc",
"android/infobars/translate_infobar.h",
"android/infobars/update_password_infobar.cc",
"android/infobars/update_password_infobar.h",
"android/javascript_app_modal_dialog_android.cc",
+ "android/javascript_app_modal_dialog_android.h",
"android/login_handler_android.cc",
"android/omnibox/omnibox_url_emphasizer.cc",
"android/omnibox/omnibox_url_emphasizer.h",
@@ -2239,8 +2277,8 @@ split_static_library("ui") {
"android/page_info/certificate_viewer_android.h",
"android/page_info/connection_info_popup_android.cc",
"android/page_info/connection_info_popup_android.h",
- "android/page_info/website_settings_popup_android.cc",
- "android/page_info/website_settings_popup_android.h",
+ "android/page_info/page_info_popup_android.cc",
+ "android/page_info/page_info_popup_android.h",
"android/simple_message_box_android.cc",
"android/snackbars/auto_signin_prompt_controller.cc",
"android/snackbars/auto_signin_prompt_controller.h",
@@ -2258,8 +2296,6 @@ split_static_library("ui") {
"android/tab_model/tab_model_jni_bridge.h",
"android/tab_model/tab_model_list.cc",
"android/tab_model/tab_model_list.h",
- "android/tab_model/tab_model_selector_base.cc",
- "android/tab_model/tab_model_selector_base.h",
"android/toolbar/toolbar_model_android.cc",
"android/toolbar/toolbar_model_android.h",
"android/usb_chooser_dialog_android.cc",
@@ -2283,20 +2319,6 @@ split_static_library("ui") {
"webui/webapks_ui.cc",
"webui/webapks_ui.h",
]
- if (enable_webvr) {
- sources += [
- "webui/vr_shell/vr_shell_ui_message_handler.cc",
- "webui/vr_shell/vr_shell_ui_message_handler.h",
- "webui/vr_shell/vr_shell_ui_ui.cc",
- "webui/vr_shell/vr_shell_ui_ui.h",
- ]
- configs += [ "//third_party/gvr-android-sdk:libgvr_config" ]
- deps += [ "//chrome/browser/android/vr_shell:vr_common" ]
- }
- if (enable_vr_shell_ui_dev) {
- assert(enable_webvr)
- defines += [ "ENABLE_VR_SHELL_UI_DEV" ]
- }
deps += [
"//chrome/browser:jni_headers",
"//components/web_contents_delegate_android",
@@ -2319,6 +2341,28 @@ split_static_library("ui") {
"cocoa/accelerator_utils_cocoa.mm",
"cocoa/accelerators_cocoa.h",
"cocoa/accelerators_cocoa.mm",
+ "cocoa/applescript/apple_event_util.h",
+ "cocoa/applescript/apple_event_util.mm",
+ "cocoa/applescript/bookmark_folder_applescript.h",
+ "cocoa/applescript/bookmark_folder_applescript.mm",
+ "cocoa/applescript/bookmark_item_applescript.h",
+ "cocoa/applescript/bookmark_item_applescript.mm",
+ "cocoa/applescript/bookmark_node_applescript.h",
+ "cocoa/applescript/bookmark_node_applescript.mm",
+ "cocoa/applescript/browsercrapplication+applescript.h",
+ "cocoa/applescript/browsercrapplication+applescript.mm",
+ "cocoa/applescript/constants_applescript.h",
+ "cocoa/applescript/constants_applescript.mm",
+ "cocoa/applescript/element_applescript.h",
+ "cocoa/applescript/element_applescript.mm",
+ "cocoa/applescript/error_applescript.h",
+ "cocoa/applescript/error_applescript.mm",
+ "cocoa/applescript/metrics_applescript.h",
+ "cocoa/applescript/metrics_applescript.mm",
+ "cocoa/applescript/tab_applescript.h",
+ "cocoa/applescript/tab_applescript.mm",
+ "cocoa/applescript/window_applescript.h",
+ "cocoa/applescript/window_applescript.mm",
"cocoa/apps/app_shim_menu_controller_mac.h",
"cocoa/apps/app_shim_menu_controller_mac.mm",
"cocoa/apps/quit_with_apps_controller_mac.cc",
@@ -2449,33 +2493,13 @@ split_static_library("ui") {
"cocoa/app_menu/menu_tracked_root_view.mm",
"cocoa/app_menu/recent_tabs_menu_model_delegate.h",
"cocoa/app_menu/recent_tabs_menu_model_delegate.mm",
- "cocoa/applescript/apple_event_util.h",
- "cocoa/applescript/apple_event_util.mm",
- "cocoa/applescript/bookmark_folder_applescript.h",
- "cocoa/applescript/bookmark_folder_applescript.mm",
- "cocoa/applescript/bookmark_item_applescript.h",
- "cocoa/applescript/bookmark_item_applescript.mm",
- "cocoa/applescript/bookmark_node_applescript.h",
- "cocoa/applescript/bookmark_node_applescript.mm",
- "cocoa/applescript/browsercrapplication+applescript.h",
- "cocoa/applescript/browsercrapplication+applescript.mm",
- "cocoa/applescript/constants_applescript.h",
- "cocoa/applescript/constants_applescript.mm",
- "cocoa/applescript/element_applescript.h",
- "cocoa/applescript/element_applescript.mm",
- "cocoa/applescript/error_applescript.h",
- "cocoa/applescript/error_applescript.mm",
- "cocoa/applescript/metrics_applescript.h",
- "cocoa/applescript/metrics_applescript.mm",
- "cocoa/applescript/tab_applescript.h",
- "cocoa/applescript/tab_applescript.mm",
- "cocoa/applescript/window_applescript.h",
- "cocoa/applescript/window_applescript.mm",
"cocoa/apps/chrome_app_window_client_views_cocoa.mm",
"cocoa/apps/native_app_window_cocoa.h",
"cocoa/apps/native_app_window_cocoa.mm",
"cocoa/autofill/autofill_bubble_controller.h",
"cocoa/autofill/autofill_bubble_controller.mm",
+ "cocoa/autofill/autofill_dialog_constants.h",
+ "cocoa/autofill/autofill_input_field.h",
"cocoa/autofill/autofill_layout.h",
"cocoa/autofill/autofill_pop_up_button.h",
"cocoa/autofill/autofill_pop_up_button.mm",
@@ -2692,6 +2716,8 @@ split_static_library("ui") {
"cocoa/extensions/media_gallery_list_entry_view.mm",
"cocoa/extensions/toolbar_actions_bar_bubble_mac.h",
"cocoa/extensions/toolbar_actions_bar_bubble_mac.mm",
+ "cocoa/extensions/toolbar_actions_bar_bubble_views_presenter.h",
+ "cocoa/extensions/toolbar_actions_bar_bubble_views_presenter.mm",
"cocoa/extensions/windowed_install_dialog_controller.h",
"cocoa/extensions/windowed_install_dialog_controller.mm",
"cocoa/external_protocol_dialog.h",
@@ -2798,8 +2824,6 @@ split_static_library("ui") {
"cocoa/location_bar/location_icon_decoration.mm",
"cocoa/location_bar/manage_passwords_decoration.h",
"cocoa/location_bar/manage_passwords_decoration.mm",
- "cocoa/location_bar/page_action_decoration.h",
- "cocoa/location_bar/page_action_decoration.mm",
"cocoa/location_bar/save_credit_card_decoration.h",
"cocoa/location_bar/save_credit_card_decoration.mm",
"cocoa/location_bar/security_state_bubble_decoration.h",
@@ -2837,6 +2861,14 @@ split_static_library("ui") {
"cocoa/one_click_signin_dialog_controller.mm",
"cocoa/one_click_signin_view_controller.h",
"cocoa/one_click_signin_view_controller.mm",
+ "cocoa/page_info/page_info_bubble_controller.h",
+ "cocoa/page_info/page_info_bubble_controller.mm",
+ "cocoa/page_info/page_info_utils_cocoa.h",
+ "cocoa/page_info/page_info_utils_cocoa.mm",
+ "cocoa/page_info/permission_selector_button.h",
+ "cocoa/page_info/permission_selector_button.mm",
+ "cocoa/page_info/split_block_button.h",
+ "cocoa/page_info/split_block_button.mm",
"cocoa/passwords/account_avatar_fetcher_manager.h",
"cocoa/passwords/account_avatar_fetcher_manager.mm",
"cocoa/passwords/account_chooser_view_controller.h",
@@ -2856,6 +2888,7 @@ split_static_library("ui") {
"cocoa/passwords/manage_passwords_view_controller.h",
"cocoa/passwords/manage_passwords_view_controller.mm",
"cocoa/passwords/password_item_views.h",
+ "cocoa/passwords/password_prompt_bridge_interface.h",
"cocoa/passwords/password_prompt_view_bridge.h",
"cocoa/passwords/password_prompt_view_bridge.mm",
"cocoa/passwords/passwords_bubble_cocoa.h",
@@ -2874,6 +2907,13 @@ split_static_library("ui") {
"cocoa/passwords/signin_promo_view_controller.mm",
"cocoa/passwords/update_pending_password_view_controller.h",
"cocoa/passwords/update_pending_password_view_controller.mm",
+ "cocoa/permission_bubble/chooser_bubble_ui_cocoa.h",
+ "cocoa/permission_bubble/chooser_bubble_ui_cocoa.mm",
+ "cocoa/permission_bubble/permission_bubble_cocoa.h",
+ "cocoa/permission_bubble/permission_bubble_cocoa.mm",
+ "cocoa/permission_bubble/permission_bubble_controller.h",
+ "cocoa/permission_bubble/permission_bubble_controller.mm",
+ "cocoa/permission_bubble/permission_prompt_impl_views_mac.mm",
"cocoa/profiles/avatar_base_controller.h",
"cocoa/profiles/avatar_base_controller.mm",
"cocoa/profiles/avatar_button.h",
@@ -2930,6 +2970,7 @@ split_static_library("ui") {
"cocoa/tabs/alert_indicator_button_cocoa.mm",
"cocoa/tabs/tab_controller.h",
"cocoa/tabs/tab_controller.mm",
+ "cocoa/tabs/tab_controller_target.h",
"cocoa/tabs/tab_strip_background_view.h",
"cocoa/tabs/tab_strip_background_view.mm",
"cocoa/tabs/tab_strip_controller.h",
@@ -2978,21 +3019,6 @@ split_static_library("ui") {
"cocoa/view_resizer.h",
"cocoa/web_contents_modal_dialog_manager_views_mac.h",
"cocoa/web_contents_modal_dialog_manager_views_mac.mm",
- "cocoa/website_settings/chooser_bubble_ui_cocoa.h",
- "cocoa/website_settings/chooser_bubble_ui_cocoa.mm",
- "cocoa/website_settings/permission_bubble_cocoa.h",
- "cocoa/website_settings/permission_bubble_cocoa.mm",
- "cocoa/website_settings/permission_bubble_controller.h",
- "cocoa/website_settings/permission_bubble_controller.mm",
- "cocoa/website_settings/permission_prompt_impl_views_mac.mm",
- "cocoa/website_settings/permission_selector_button.h",
- "cocoa/website_settings/permission_selector_button.mm",
- "cocoa/website_settings/split_block_button.h",
- "cocoa/website_settings/split_block_button.mm",
- "cocoa/website_settings/website_settings_bubble_controller.h",
- "cocoa/website_settings/website_settings_bubble_controller.mm",
- "cocoa/website_settings/website_settings_utils_cocoa.h",
- "cocoa/website_settings/website_settings_utils_cocoa.mm",
"cocoa/window_size_autosaver.h",
"cocoa/window_size_autosaver.mm",
@@ -3049,8 +3075,14 @@ split_static_library("ui") {
"views/network_profile_bubble_view.cc",
"views/settings_reset_prompt_dialog.cc",
"views/settings_reset_prompt_dialog.h",
+ "views/srt_prompt_dialog.cc",
+ "views/srt_prompt_dialog.h",
"views/uninstall_view.cc",
"views/uninstall_view.h",
+ "webui/cleanup_tool/cleanup_action_handler.cc",
+ "webui/cleanup_tool/cleanup_action_handler.h",
+ "webui/cleanup_tool/cleanup_tool_ui.cc",
+ "webui/cleanup_tool/cleanup_tool_ui.h",
"webui/conflicts_ui.cc",
"webui/conflicts_ui.h",
"webui/welcome_win10_handler.cc",
@@ -3074,7 +3106,10 @@ split_static_library("ui") {
]
if (!is_chrome_branded) {
deps -= [ "//google_update" ]
- sources -= [ "webui/help/version_updater_win.cc" ]
+ sources -= [
+ "webui/help/version_updater_win.cc",
+ "webui/help/version_updater_win.h",
+ ]
sources += [
"webui/help/version_updater_basic.cc",
"webui/help/version_updater_basic.h",
@@ -3180,8 +3215,6 @@ split_static_library("ui") {
"app_list/app_context_menu_delegate.h",
"app_list/app_list_controller_delegate.cc",
"app_list/app_list_controller_delegate.h",
- "app_list/app_list_controller_delegate_impl.cc",
- "app_list/app_list_controller_delegate_impl.h",
"app_list/app_list_model_builder.cc",
"app_list/app_list_model_builder.h",
"app_list/app_list_service.cc",
@@ -3270,6 +3303,7 @@ split_static_library("ui") {
]
if (is_chromeos) {
sources += [
+ "app_icon_loader_delegate.h",
"app_list/arc/arc_app_context_menu.cc",
"app_list/arc/arc_app_context_menu.h",
"app_list/arc/arc_app_dialog.h",
@@ -3333,11 +3367,15 @@ split_static_library("ui") {
}
if (enable_extensions) {
deps += [
+ "//chrome/browser/apps",
"//chrome/browser/extensions",
"//chrome/common/extensions/api",
"//chrome/common/extensions/api:api_registration",
]
- allow_circular_includes_from += [ "//chrome/browser/extensions" ]
+ allow_circular_includes_from += [
+ "//chrome/browser/apps",
+ "//chrome/browser/extensions",
+ ]
sources += [
"extensions/accelerator_priority.cc",
"extensions/accelerator_priority.h",
diff --git a/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn b/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn
index 4fb22a78839..4ea320fcae0 100644
--- a/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn
+++ b/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn
@@ -25,6 +25,7 @@ mac_app_bundle("alert_notification_xpc_service") {
deps = [
":common",
"//base:base",
+ "//third_party/crashpad/crashpad/client",
]
libs = [
@@ -53,6 +54,8 @@ static_library("common") {
"notification_delivery.h",
"notification_response_builder_mac.h",
"notification_response_builder_mac.mm",
+ "xpc_mach_port.h",
+ "xpc_mach_port.mm",
]
deps = [
diff --git a/chromium/chrome/browser/ui/libgtkui/BUILD.gn b/chromium/chrome/browser/ui/libgtkui/BUILD.gn
index aa48833fb9c..4911b889027 100644
--- a/chromium/chrome/browser/ui/libgtkui/BUILD.gn
+++ b/chromium/chrome/browser/ui/libgtkui/BUILD.gn
@@ -53,6 +53,7 @@ template("libgtkui") {
"gtk_event_loop.h",
"gtk_key_bindings_handler.cc",
"gtk_key_bindings_handler.h",
+ "gtk_signal.h",
"gtk_status_icon.cc",
"gtk_status_icon.h",
"gtk_ui.cc",
diff --git a/chromium/chrome/browser/ui/webui/engagement/site_engagement.mojom b/chromium/chrome/browser/ui/webui/engagement/site_engagement.mojom
deleted file mode 100644
index a1ccb2ef8fe..00000000000
--- a/chromium/chrome/browser/ui/webui/engagement/site_engagement.mojom
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module mojom;
-
-import "url/mojo/url.mojom";
-
-struct SiteEngagementInfo {
- url.mojom.Url origin;
- double score;
-};
-
-interface SiteEngagementUIHandler {
- GetSiteEngagementInfo() => (array<SiteEngagementInfo> info);
- SetSiteEngagementScoreForOrigin(url.mojom.Url origin, double score);
-};