summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/resources
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-07-14 17:41:05 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-08-04 12:37:36 +0000
commit399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (patch)
tree6b06b60ff365abef0e13b3503d593a0df48d20e8 /chromium/chrome/browser/resources
parent7366110654eec46f21b6824f302356426f48cd74 (diff)
BASELINE: Update Chromium to 52.0.2743.76 and Ninja to 1.7.1
Change-Id: I382f51b959689505a60f8b707255ecb344f7d8b4 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources')
-rw-r--r--chromium/chrome/browser/resources/OWNERS8
-rw-r--r--chromium/chrome/browser/resources/PRESUBMIT.py29
-rw-r--r--chromium/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js3
-rw-r--r--chromium/chrome/browser/resources/bookmark_manager/js/compiled_resources.gyp1
-rw-r--r--chromium/chrome/browser/resources/bookmark_manager/main.html1
-rw-r--r--chromium/chrome/browser/resources/certificate_viewer.html4
-rw-r--r--chromium/chrome/browser/resources/chromeos/arc_support/manifest.json11
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json1
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/mathmaps/symbols/math_whitespace.json2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi17
-rw-r--r--chromium/chrome/browser/resources/chromeos/compiled_resources.gyp4
-rw-r--r--chromium/chrome/browser/resources/component_extension_resources.grd6
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_list.js17
-rw-r--r--chromium/chrome/browser/resources/feedback/css/feedback.css21
-rw-r--r--chromium/chrome/browser/resources/feedback/html/default.html14
-rw-r--r--chromium/chrome/browser/resources/feedback/js/feedback.js52
-rw-r--r--chromium/chrome/browser/resources/gaia_auth/OWNERS5
-rw-r--r--chromium/chrome/browser/resources/gaia_auth/saml_injected.js18
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/OWNERS3
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/authenticator.js61
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js20
-rw-r--r--chromium/chrome/browser/resources/hangout_services/manifest.json2
-rw-r--r--chromium/chrome/browser/resources/hangout_services/thunk.js10
-rw-r--r--chromium/chrome/browser/resources/help/help_content.html4
-rw-r--r--chromium/chrome/browser/resources/help/help_page.js16
-rw-r--r--chromium/chrome/browser/resources/help_app/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/history/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/history/history.html1
-rw-r--r--chromium/chrome/browser/resources/history/history.js2
-rw-r--r--chromium/chrome/browser/resources/history/other_devices.js2
-rw-r--r--chromium/chrome/browser/resources/inline_login/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/local_discovery/local_discovery.js9
-rw-r--r--chromium/chrome/browser/resources/local_ntp/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_single.js148
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js4
-rw-r--r--chromium/chrome/browser/resources/md_downloads/crisper.js3655
-rw-r--r--chromium/chrome/browser/resources/md_downloads/downloads.html11
-rw-r--r--chromium/chrome/browser/resources/md_downloads/icons.html14
-rw-r--r--chromium/chrome/browser/resources/md_downloads/item.css4
-rw-r--r--chromium/chrome/browser/resources/md_downloads/item.html42
-rw-r--r--chromium/chrome/browser/resources/md_downloads/item.js31
-rw-r--r--chromium/chrome/browser/resources/md_downloads/manager.html6
-rw-r--r--chromium/chrome/browser/resources/md_downloads/toolbar.css2
-rw-r--r--chromium/chrome/browser/resources/md_downloads/toolbar.html31
-rw-r--r--chromium/chrome/browser/resources/md_downloads/vulcanized.html1020
-rw-r--r--chromium/chrome/browser/resources/md_extensions/compiled_resources.gyp32
-rw-r--r--chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp97
-rw-r--r--chromium/chrome/browser/resources/md_extensions/detail_view.html144
-rw-r--r--chromium/chrome/browser/resources/md_extensions/detail_view.js114
-rw-r--r--chromium/chrome/browser/resources/md_extensions/extensions.html4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/extensions.js12
-rw-r--r--chromium/chrome/browser/resources/md_extensions/icons.html67
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item.css149
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item.html108
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item.js113
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_list.css15
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_list.html6
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_list.js30
-rw-r--r--chromium/chrome/browser/resources/md_extensions/manager.css6
-rw-r--r--chromium/chrome/browser/resources/md_extensions/manager.html34
-rw-r--r--chromium/chrome/browser/resources/md_extensions/manager.js84
-rw-r--r--chromium/chrome/browser/resources/md_extensions/service.js47
-rw-r--r--chromium/chrome/browser/resources/md_extensions/sidebar.css36
-rw-r--r--chromium/chrome/browser/resources/md_extensions/sidebar.html64
-rw-r--r--chromium/chrome/browser/resources/md_extensions/sidebar.js64
-rw-r--r--chromium/chrome/browser/resources/md_feedback/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/md_history/app.html61
-rw-r--r--chromium/chrome/browser/resources/md_history/app.js151
-rw-r--r--chromium/chrome/browser/resources/md_history/browser_service.html3
-rw-r--r--chromium/chrome/browser/resources/md_history/browser_service.js83
-rw-r--r--chromium/chrome/browser/resources/md_history/compiled_resources2.gyp25
-rw-r--r--chromium/chrome/browser/resources/md_history/elements.html4
-rw-r--r--chromium/chrome/browser/resources/md_history/history.html72
-rw-r--r--chromium/chrome/browser/resources/md_history/history.js95
-rw-r--r--chromium/chrome/browser/resources/md_history/history_item.html14
-rw-r--r--chromium/chrome/browser/resources/md_history/history_item.js22
-rw-r--r--chromium/chrome/browser/resources/md_history/history_list.html27
-rw-r--r--chromium/chrome/browser/resources/md_history/history_list.js284
-rw-r--r--chromium/chrome/browser/resources/md_history/history_toolbar.html192
-rw-r--r--chromium/chrome/browser/resources/md_history/history_toolbar.js48
-rw-r--r--chromium/chrome/browser/resources/md_history/shared_style.html4
-rw-r--r--chromium/chrome/browser/resources/md_history/side_bar.html27
-rw-r--r--chromium/chrome/browser/resources/md_history/side_bar.js17
-rw-r--r--chromium/chrome/browser/resources/md_history/synced_device_card.html11
-rw-r--r--chromium/chrome/browser/resources/md_history/synced_device_card.js4
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/compiled_resources2.gyp21
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/control_bar.css37
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/control_bar.html30
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/create_profile.css159
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/create_profile.html219
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/create_profile.js175
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/icons.html14
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/import_supervised_user.html148
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/import_supervised_user.js130
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/profile_browser_proxy.js55
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/shared_styles.html58
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.html71
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.js144
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.css56
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html53
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.js32
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager.html10
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager.js30
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager_pages.css12
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager_pages.html56
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager_pages.js10
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager_styles.html286
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.css160
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.html196
-rw-r--r--chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.js4
-rw-r--r--chromium/chrome/browser/resources/media_router/OWNERS7
-rw-r--r--chromium/chrome/browser/resources/media_router/compiled_resources.gyp57
-rw-r--r--chromium/chrome/browser/resources/media_router/compiled_resources2.gyp38
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/issue_banner/compiled_resources2.gyp15
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css5
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html5
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js31
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_container/compiled_resources2.gyp27
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css36
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html200
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js1317
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_container/pseudo_sink_search_state.js73
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_header/compiled_resources2.gyp16
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css52
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html52
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js74
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/compiled_resources2.gyp14
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/media_router_search_highlighter.js7
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_details/compiled_resources2.gyp16
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_details/route_details.css4
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_details/route_details.html7
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_details/route_details.js106
-rw-r--r--chromium/chrome/browser/resources/media_router/externs.js44
-rw-r--r--chromium/chrome/browser/resources/media_router/icons/media_router_icons.html24
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router.css3
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router.js45
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_data.js25
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_ui_interface.js49
-rw-r--r--chromium/chrome/browser/resources/net_internals/alt_svc_view.html4
-rw-r--r--chromium/chrome/browser/resources/net_internals/index.html5
-rw-r--r--chromium/chrome/browser/resources/net_internals/log_util.js2
-rw-r--r--chromium/chrome/browser/resources/net_internals/main.css28
-rw-r--r--chromium/chrome/browser/resources/net_internals/main.js8
-rw-r--r--chromium/chrome/browser/resources/net_internals/status_view.html2
-rw-r--r--chromium/chrome/browser/resources/net_internals/tab_switcher_view.js94
-rw-r--r--chromium/chrome/browser/resources/net_internals/top_bar_view.html40
-rw-r--r--chromium/chrome/browser/resources/net_internals/top_bar_view.js1
-rw-r--r--chromium/chrome/browser/resources/ntp4/incognito_and_guest_tab.css2
-rw-r--r--chromium/chrome/browser/resources/options/browser_options.html24
-rw-r--r--chromium/chrome/browser/resources/options/browser_options.js18
-rw-r--r--chromium/chrome/browser/resources/options/browser_options_profile_list.js3
-rw-r--r--chromium/chrome/browser/resources/options/browser_options_startup_page_list.js3
-rw-r--r--chromium/chrome/browser/resources/options/compiled_resources.gyp1
-rw-r--r--chromium/chrome/browser/resources/options/home_page_overlay.js3
-rw-r--r--chromium/chrome/browser/resources/options/language_options.css9
-rw-r--r--chromium/chrome/browser/resources/options/language_options.html13
-rw-r--r--chromium/chrome/browser/resources/options/manage_profile_overlay.js2
-rw-r--r--chromium/chrome/browser/resources/options/options.html1
-rw-r--r--chromium/chrome/browser/resources/options/password_manager.css2
-rw-r--r--chromium/chrome/browser/resources/options/password_manager.html73
-rw-r--r--chromium/chrome/browser/resources/options/password_manager.js33
-rw-r--r--chromium/chrome/browser/resources/options/password_manager_list.js2
-rw-r--r--chromium/chrome/browser/resources/options/profiles_icon_grid.js2
-rw-r--r--chromium/chrome/browser/resources/options/search_engine_manager_engine_list.js6
-rw-r--r--chromium/chrome/browser/resources/options/supervised_user_list.js3
-rw-r--r--chromium/chrome/browser/resources/options/sync_setup_overlay.html7
-rw-r--r--chromium/chrome/browser/resources/options/sync_setup_overlay.js59
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/icons.html19
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html3
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html14
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html3
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html1
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html11
-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/plugins.js9
-rw-r--r--chromium/chrome/browser/resources/popular_sites_internals.html10
-rw-r--r--chromium/chrome/browser/resources/popular_sites_internals.js16
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/BUILD.gn62
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/README.md105
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb2514
-rwxr-xr-xchromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py200
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html61
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.html76
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.js64
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.html2
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js168
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp32
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html80
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/detailed_build_info.js64
-rw-r--r--chromium/chrome/browser/resources/settings/advanced_page/advanced_page.html20
-rw-r--r--chromium/chrome/browser/resources/settings/advanced_page/advanced_page.js11
-rw-r--r--chromium/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp2
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.html2
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js53
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.html49
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.js38
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html60
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js21
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_shared.css12
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp13
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js18
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.html16
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.js12
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp2
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.html50
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.js68
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html171
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.js (renamed from chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_pair_device_dialog.js)141
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.css35
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html47
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_dialog.css91
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.css32
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html111
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js10
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_pair_device_dialog.html69
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp18
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_entry.html2
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_manager_page.js2
-rw-r--r--chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.html7
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html2
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js46
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html107
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js91
-rw-r--r--chromium/chrome/browser/resources/settings/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_checkbox.html12
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html9
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js1
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_radio_group.css11
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_radio_group.html11
-rw-r--r--chromium/chrome/browser/resources/settings/date_time_page/date_time_page.html7
-rw-r--r--chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.html10
-rw-r--r--chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.js12
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp20
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page.html17
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.html2
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js56
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display.html66
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display.js220
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/keyboard.html64
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/keyboard.js127
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/touchpad.html22
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/touchpad.js9
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html10
-rw-r--r--chromium/chrome/browser/resources/settings/icons.html103
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.css53
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html55
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js2
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.css22
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html24
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.html5
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.js12
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_apnlist.css20
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html19
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_ip_config.css11
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_ip_config.html10
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_nameservers.css15
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html14
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_property_list.css29
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_property_list.html28
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy.css32
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy.html31
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.css18
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html22
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.css15
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.html14
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_siminfo.css47
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html54
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.css33
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html56
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp21
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html16
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/language_detail_page.html23
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/language_detail_page.js18
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages.html1
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages.js503
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages_page.html77
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages_page.js96
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages_types.js91
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html33
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js197
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.html57
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.js89
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/compiled_resources2.gyp13
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/on_startup_page.html3
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html30
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.js76
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html46
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js49
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.html52
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page.js124
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.js38
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html78
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js69
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp9
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html24
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html22
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js45
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html141
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js9
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html40
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/camera.html15
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/camera.js5
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/change_picture.html38
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/change_picture.js119
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp24
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.html1
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.html152
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.js109
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/pin_keyboard.html1
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/pin_keyboard.js5
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.html2
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.js50
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.html3
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js216
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.css19
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.html252
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.js271
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_private_api.html1
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_private_api.js265
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/user_list.css26
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/user_list.html29
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/users_page.css19
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/users_page.html44
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html66
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js26
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html16
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_browser_proxy.js20
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_page.html8
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_profile_banner.html14
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.html34
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/reset_profile_dialog.js20
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html40
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js9
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.html13
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.css8
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html50
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js10
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engines_page.html11
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.html10
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.js4
-rw-r--r--chromium/chrome/browser/resources/settings/settings.html9
-rw-r--r--chromium/chrome/browser/resources/settings/settings_dialog.html45
-rw-r--r--chromium/chrome/browser/resources/settings/settings_main/settings_main.html7
-rw-r--r--chromium/chrome/browser/resources/settings/settings_main/settings_main.js22
-rw-r--r--chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html168
-rw-r--r--chromium/chrome/browser/resources/settings/settings_menu/settings_menu.js26
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page.css4
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.html10
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.js42
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js18
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_router.js150
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_section.css49
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_section.html48
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html12
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources.grd199
-rw-r--r--chromium/chrome/browser/resources/settings/settings_shared_css.html85
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html213
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js23
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.html30
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.js65
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/constants.js29
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.css18
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.html22
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.js3
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html23
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js21
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.css20
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.html88
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.js99
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.html4
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.js135
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_category.css12
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_category.html30
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_category.js29
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js28
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.css13
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html90
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js83
-rw-r--r--chromium/chrome/browser/resources/settings/system_page/system_page.html7
-rw-r--r--chromium/chrome/browser/resources/snippets_internals.css84
-rw-r--r--chromium/chrome/browser/resources/snippets_internals.html149
-rw-r--r--chromium/chrome/browser/resources/snippets_internals.js130
-rw-r--r--chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.css1
-rw-r--r--chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.html4
-rw-r--r--chromium/chrome/browser/resources/translate_internals/OWNERS3
-rw-r--r--chromium/chrome/browser/resources/translate_internals/prefs.html4
-rw-r--r--chromium/chrome/browser/resources/translate_internals/translate_internals.js54
-rw-r--r--chromium/chrome/browser/resources/user_manager/user_manager.css20
-rw-r--r--chromium/chrome/browser/resources/user_manager/user_manager.js1
395 files changed, 17596 insertions, 7998 deletions
diff --git a/chromium/chrome/browser/resources/OWNERS b/chromium/chrome/browser/resources/OWNERS
index dae8b0021ee..f3b7a27e5ec 100644
--- a/chromium/chrome/browser/resources/OWNERS
+++ b/chromium/chrome/browser/resources/OWNERS
@@ -1,9 +1,13 @@
bauerb@chromium.org
dbeam@chromium.org
-estade@chromium.org
-nkostylev@chromium.org
+dpapad@chromium.org
+michaelpg@chromium.org
pam@chromium.org
xiyuan@chromium.org
+# Emeritus
+estade@chromium.org
+
per-file component_extension_resources.grd=dgozman@chromium.org
+per-file profile_signin_confirmation*=achuith@chromium.org
per-file sync_file_system_internals_resources.*=tzik@chromium.org
diff --git a/chromium/chrome/browser/resources/PRESUBMIT.py b/chromium/chrome/browser/resources/PRESUBMIT.py
index 502d47a88d2..6d60a3a9228 100644
--- a/chromium/chrome/browser/resources/PRESUBMIT.py
+++ b/chromium/chrome/browser/resources/PRESUBMIT.py
@@ -2,14 +2,18 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""Presubmit script for HTML files in chrome/browser/resources.
+"""Presubmit script for files in chrome/browser/resources.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into depot_tools.
"""
+import re
+
+
ACTION_XML_PATH = '../../../tools/metrics/actions/actions.xml'
+
def CheckUserActionUpdate(input_api, output_api, action_xml_path):
"""Checks if any new user action has been added."""
if any('actions.xml' == input_api.os_path.basename(f) for f in
@@ -93,3 +97,26 @@ def CheckChangeOnUpload(input_api, output_api):
def CheckChangeOnCommit(input_api, output_api):
return CheckUserActionUpdate(input_api, output_api, ACTION_XML_PATH)
+
+
+def PostUploadHook(cl, change, output_api):
+ rietveld_obj = cl.RpcServer()
+ description = rietveld_obj.get_description(cl.issue)
+
+ existing_bots = (change.CQ_INCLUDE_TRYBOTS or '').split(';')
+ clean_bots = set(filter(None, map(lambda s: s.strip(), existing_bots)))
+ new_bots = clean_bots | set(['tryserver.chromium.linux:closure_compilation'])
+ new_tag = 'CQ_INCLUDE_TRYBOTS=%s' % ';'.join(new_bots)
+
+ if clean_bots:
+ tag_reg = '^CQ_INCLUDE_TRYBOTS=.*$'
+ new_description = re.sub(tag_reg, new_tag, description, flags=re.M | re.I)
+ else:
+ new_description = description + '\n' + new_tag
+
+ if new_description == description:
+ return []
+
+ rietveld_obj.update_description(cl.issue, new_description)
+ return [output_api.PresubmitNotifyResult(
+ 'Automatically added optional Closure bots to run on CQ.')]
diff --git a/chromium/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js b/chromium/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js
index 718762ef417..2f4d00eb67f 100644
--- a/chromium/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js
+++ b/chromium/chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js
@@ -431,7 +431,8 @@ cr.define('bmm', function() {
if (bmm.isFolder(bookmarkNode)) {
this.className = 'folder';
} else {
- labelEl.style.backgroundImage = getFaviconImageSet(bookmarkNode.url);
+ labelEl.style.backgroundImage = cr.icon.getFaviconImageSet(
+ bookmarkNode.url);
labelEl.style.backgroundSize = '16px';
urlEl.textContent = bookmarkNode.url;
}
diff --git a/chromium/chrome/browser/resources/bookmark_manager/js/compiled_resources.gyp b/chromium/chrome/browser/resources/bookmark_manager/js/compiled_resources.gyp
index 32334374f53..9a719335db7 100644
--- a/chromium/chrome/browser/resources/bookmark_manager/js/compiled_resources.gyp
+++ b/chromium/chrome/browser/resources/bookmark_manager/js/compiled_resources.gyp
@@ -33,6 +33,7 @@
'../../../../../ui/webui/resources/js/load_time_data.js',
'../../../../../ui/webui/resources/js/promise_resolver.js',
'../../../../../ui/webui/resources/js/util.js',
+ '../../../../../ui/webui/resources/js/icon.js',
'../../../../../chrome/browser/resources/bookmark_manager/js/bmm.js',
'../../../../../chrome/browser/resources/bookmark_manager/js/bmm/bookmark_list.js',
'../../../../../chrome/browser/resources/bookmark_manager/js/bmm/bookmark_tree.js',
diff --git a/chromium/chrome/browser/resources/bookmark_manager/main.html b/chromium/chrome/browser/resources/bookmark_manager/main.html
index a96a1ccbec6..8a5e831309d 100644
--- a/chromium/chrome/browser/resources/bookmark_manager/main.html
+++ b/chromium/chrome/browser/resources/bookmark_manager/main.html
@@ -45,6 +45,7 @@ found in the LICENSE file.
<script src="chrome://resources/js/cr/ui/splitter.js"></script>
<script src="chrome://resources/js/i18n_template_no_process.js"></script>
+<script src="chrome://resources/js/icon.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/util.js"></script>
diff --git a/chromium/chrome/browser/resources/certificate_viewer.html b/chromium/chrome/browser/resources/certificate_viewer.html
index 83672ab57af..e6c3b14c09f 100644
--- a/chromium/chrome/browser/resources/certificate_viewer.html
+++ b/chromium/chrome/browser/resources/certificate_viewer.html
@@ -47,10 +47,6 @@
<div class="attribute" i18n-content="ou"></div>
<div id="issued-ou" class="value"></div>
</div>
- <div>
- <div class="attribute" i18n-content="sn"></div>
- <div id="issued-sn" class="value"></div>
- </div>
<!-- Issued by -->
<div>
diff --git a/chromium/chrome/browser/resources/chromeos/arc_support/manifest.json b/chromium/chrome/browser/resources/chromeos/arc_support/manifest.json
index e78f738b865..a925c9e597c 100644
--- a/chromium/chrome/browser/resources/chromeos/arc_support/manifest.json
+++ b/chromium/chrome/browser/resources/chromeos/arc_support/manifest.json
@@ -5,15 +5,18 @@
},
"content_security_policy": "default-src 'self'; style-src 'self' chrome://resources/ 'unsafe-inline'; font-src 'self' chrome://resources/; img-src 'self'; script-src chrome://resources/ 'self'"
},
- "description": "ARC Support",
+ "description": "Play Store",
"display_in_launcher": false,
// cnbgggchhmkkdmeppjobngjoejnihlei
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnYsWobpgYLBvlN3PIFXyDwcCqRKcL+1swMf4f1Dnqn1+TYqbGW51ZNQbRo8xgE7y+0D8cz8fE0kZsQXhE7gzDKEyUgePNU75GQ3I9xdqsoNYWHGPegf2p6azj0kzJKCE+aaO4Ys7tSvvIniHfVGFuaqaS1m1JYP0Mlhv+pkwbrbVV3Ymdzb4tYP2y8jrISmyhrzlX9E2p9RU2ObSgZCUgZofMkwWZd1tyZN089sjxcPlN/RGHsB0NtpgFFhSAs9tSrRcvUUcoUTDQYeDB4qBioCJ0QUtjRj21xqsotjUQM4GFOkAxmNbijghvKoMwSulvEbgrb0x3dQl+y+ecr0ybwIDAQAB",
"manifest_version": 2,
- "name": "ARC Support",
+ "name": "Play Store",
"icons": {
"48": "icon/48.png"
},
- "permissions": [ "webview", "nativeMessaging", "chrome://resources/" ],
- "version": "0.1.1.0"
+ "permissions": [ "webview",
+ "browser",
+ "nativeMessaging",
+ "chrome://resources/" ],
+ "version": "0.2.0.0"
} \ No newline at end of file
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 6066a0f5fee..f72b3cab18a 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
@@ -330,6 +330,7 @@
{
"command": "toggleStickyMode",
"sequence": {
+ "skipStripping": false,
"doubleTap": true,
"keys": {
"keyCode": [
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/mathmaps/symbols/math_whitespace.json b/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/mathmaps/symbols/math_whitespace.json
index acacc3637fd..85537d08e8f 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/mathmaps/symbols/math_whitespace.json
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/mathmaps/symbols/math_whitespace.json
@@ -13,7 +13,7 @@
"default": {
"default": "no break space",
"alternative": "non breaking space",
- "short": ""
+ "short": "space"
}
},
"key": "00A0"
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi b/chromium/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi
index 63b56bcf829..77938712752 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/chromevox_tests.gypi
@@ -110,16 +110,11 @@
'<(DEPTH)/content/content_shell_and_tests.gyp:content_browser_test_base',
'<(DEPTH)/testing/gmock.gyp:gmock',
'<(DEPTH)/testing/gtest.gyp:gtest',
- '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
+ '<(DEPTH)/third_party/cld_2/cld_2.gyp:cld2_platform_impl',
+ '<(DEPTH)/v8/src/v8.gyp:v8',
'chromevox_test_deps_js',
],
'conditions': [
- [ 'cld_version==0 or cld_version==2', {
- 'dependencies': [
- # Interactive tests should use whatever CLD2 data access mode that
- # the application embedder is using.
- '<(DEPTH)/third_party/cld_2/cld_2.gyp:cld2_platform_impl', ],
- }],
['disable_nacl==0 and disable_nacl_untrusted==0', {
'dependencies': [
'<(DEPTH)/components/nacl.gyp:nacl_helper',
@@ -154,7 +149,7 @@
},
'inputs': [
'<(gypv8sh)',
- '<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
+ '<(PRODUCT_DIR)/v8_shell<(EXECUTABLE_SUFFIX)',
'<(mock_js)',
'<(test_api_js)',
'<(js2gtest)',
@@ -169,7 +164,7 @@
'action': [
'python',
'<(gypv8sh)',
- '<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
+ '<(PRODUCT_DIR)/v8_shell<(EXECUTABLE_SUFFIX)',
'--deps_js', '<(chromevox_test_deps_js_file)',
'--external', '<(external_v8)',
'<(mock_js)',
@@ -198,7 +193,7 @@
},
'inputs': [
'<(gypv8sh)',
- '<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
+ '<(PRODUCT_DIR)/v8_shell<(EXECUTABLE_SUFFIX)',
'<(mock_js)',
'<(test_api_js)',
'<(js2gtest)',
@@ -212,7 +207,7 @@
'action': [
'python',
'<(gypv8sh)',
- '<(PRODUCT_DIR)/d8<(EXECUTABLE_SUFFIX)',
+ '<(PRODUCT_DIR)/v8_shell<(EXECUTABLE_SUFFIX)',
'--external', '<(external_v8)',
'<(mock_js)',
'<(test_api_js)',
diff --git a/chromium/chrome/browser/resources/chromeos/compiled_resources.gyp b/chromium/chrome/browser/resources/chromeos/compiled_resources.gyp
index ed72f939aa1..3038cb9fa92 100644
--- a/chromium/chrome/browser/resources/chromeos/compiled_resources.gyp
+++ b/chromium/chrome/browser/resources/chromeos/compiled_resources.gyp
@@ -22,6 +22,10 @@
'externs': ['<(EXTERNS_DIR)/chrome_send.js'],
},
'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
+ },
+ {
+ 'target_name': 'quick_unlock/pin_keyboard',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
}
],
}
diff --git a/chromium/chrome/browser/resources/component_extension_resources.grd b/chromium/chrome/browser/resources/component_extension_resources.grd
index 6a84d8e4b9b..84d0f8a1623 100644
--- a/chromium/chrome/browser/resources/component_extension_resources.grd
+++ b/chromium/chrome/browser/resources/component_extension_resources.grd
@@ -146,10 +146,11 @@
<include name="IDR_FIRST_RUN_DIALOG_ICON_256" file="chromeos/first_run/app/icon/256.png" type="BINDATA" />
<include name="IDR_ARC_SUPPORT_BACKGROUND_JS" file="chromeos/arc_support/background.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_ARC_SUPPORT_MAIN_CSS" file="chromeos/arc_support/main.css" type="BINDATA" />
+ <include name="IDR_ARC_SUPPORT_PLAYSTORE_CSS" file="chromeos/arc_support/playstore.css" type="BINDATA" />
+ <include name="IDR_ARC_SUPPORT_PLAYSTORE_JS" file="chromeos/arc_support/playstore.js" type="BINDATA" />
<include name="IDR_ARC_SUPPORT_MAIN" file="chromeos/arc_support/main.html" allowexternalscript="true" type="BINDATA" />
<include name="IDR_ARC_SUPPORT_ICON" file="chromeos/arc_support/icon/48.png" type="BINDATA" />
- <include name="IDR_ARC_SUPPORT_ICON_PLAYSTORE" file="chromeos/arc_support/images/play_store_96dp.png" type="BINDATA" />
- <include name="IDR_ARC_SUPPORT_ICON_CHROME" file="chromeos/arc_support/images/chrome_96dp.png" type="BINDATA" />
+ <include name="IDR_ARC_SUPPORT_ICON_HEADER" file="chromeos/arc_support/images/header.png" type="BINDATA" />
</if>
<if expr="enable_settings_app">
<include name="IDR_SETTINGS_APP_JS" file="settings_app/settings_app.js" type="BINDATA" />
@@ -170,6 +171,7 @@
<include name="IDR_PDF_CONTENT_SCRIPT_JS" file="pdf/content_script.js" type="BINDATA" />
<include name="IDR_PDF_SHARED_ICON_STYLE_CSS" file="pdf/elements/shared-icon-style.css" type="BINDATA" />
+ <include name="IDR_PDF_ICONS_HTML" file="pdf/elements/icons.html" type="BINDATA" />
<include name="IDR_PDF_VIEWER_BOOKMARK_CSS" file="pdf/elements/viewer-bookmark/viewer-bookmark.css" type="BINDATA" />
<include name="IDR_PDF_VIEWER_BOOKMARK_HTML" file="pdf/elements/viewer-bookmark/viewer-bookmark.html" type="BINDATA" />
<include name="IDR_PDF_VIEWER_BOOKMARK_JS" file="pdf/elements/viewer-bookmark/viewer-bookmark.js" type="BINDATA" />
diff --git a/chromium/chrome/browser/resources/extensions/extension_list.js b/chromium/chrome/browser/resources/extensions/extension_list.js
index 7adab1e3d30..65283a6d7cb 100644
--- a/chromium/chrome/browser/resources/extensions/extension_list.js
+++ b/chromium/chrome/browser/resources/extensions/extension_list.js
@@ -547,10 +547,11 @@ cr.define('extensions', function() {
});
// The 'Enabled' checkbox.
- wrapper.setupColumn('enabled', '.enable-checkbox input', 'change',
+ wrapper.setupColumn('enabled', '.enable-checkbox input', 'click',
function(e) {
var checked = e.target.checked;
- // TODO(devlin): What should we do if this fails?
+ // TODO(devlin): What should we do if this fails? Ideally we want to
+ // show some kind of error or feedback to the user if this fails.
chrome.management.setEnabled(extension.id, checked);
// This may seem counter-intuitive (to not set/clear the checkmark)
@@ -835,17 +836,7 @@ cr.define('extensions', function() {
hasDependents, function(item) {
var dependentList = item.querySelector('ul');
dependentList.textContent = '';
- extension.dependentExtensions.forEach(function(dependentId) {
- var dependentExtension = null;
- for (var i = 0; i < this.extensions_.length; ++i) {
- if (this.extensions_[i].id == dependentId) {
- dependentExtension = this.extensions_[i];
- break;
- }
- }
- if (!dependentExtension)
- return;
-
+ extension.dependentExtensions.forEach(function(dependentExtension) {
var depNode = cloneTemplate('dependent-list-item');
depNode.querySelector('.dep-extension-title').textContent =
dependentExtension.name;
diff --git a/chromium/chrome/browser/resources/feedback/css/feedback.css b/chromium/chrome/browser/resources/feedback/css/feedback.css
index 7270cf6d879..19ee53cb91d 100644
--- a/chromium/chrome/browser/resources/feedback/css/feedback.css
+++ b/chromium/chrome/browser/resources/feedback/css/feedback.css
@@ -126,8 +126,12 @@ body {
}
.content .buttons-pane {
+ bottom: 20px;
display: -webkit-flex;
- justify-content: flex-end
+ justify-content: flex-end;
+ left: 20px;
+ position: absolute;
+ right: 20px;
}
.content .remove-file-button {
@@ -176,3 +180,18 @@ button.blue-button {
color: #fff;
text-shadow: 1px sharp drop shadow rgb(45, 106, 218);
}
+
+.srt-image {
+ -webkit-margin-end: auto;
+ -webkit-margin-start: 40px;
+ display: block;
+ height: 50px;
+ margin-bottom: 20px;
+ margin-top: 120px;
+}
+
+.srt-body {
+ font-size: 14px;
+ line-height: 24px;
+ margin: 0 40px;
+}
diff --git a/chromium/chrome/browser/resources/feedback/html/default.html b/chromium/chrome/browser/resources/feedback/html/default.html
index 204850a3659..17168966a11 100644
--- a/chromium/chrome/browser/resources/feedback/html/default.html
+++ b/chromium/chrome/browser/resources/feedback/html/default.html
@@ -24,6 +24,18 @@
</button>
</span>
</div>
+ <div id="srt-prompt" class="content">
+ <img src="../../../../../components/resources/sadtab.svg" class="srt-image">
+ <p i18n-content="srtPromptBody" class="srt-body"></p>
+ <div class="buttons-pane">
+ <button id="srt-decline-button" class="white-button"
+ i18n-content="srtPromptDeclineButton">
+ </button>
+ <button id="srt-accept-button" class="blue-button"
+ i18n-content="srtPromptAcceptButton">
+ </button>
+ </div>
+ </div>
<div id="content-pane" class="content">
<textarea id="description-text" aria-labelledby="title-bar"></textarea>
<div id="page-url" class="text-field-container">
@@ -67,7 +79,7 @@
</a>
</div>
</if>
- <!-- Privacy node -->
+ <!-- Privacy note -->
<div id="privacy-note" i18n-values=".innerHTML:privacy-note"></div>
<!-- Buttons -->
<div class="buttons-pane">
diff --git a/chromium/chrome/browser/resources/feedback/js/feedback.js b/chromium/chrome/browser/resources/feedback/js/feedback.js
index 065081e1da1..0b929ac2a4a 100644
--- a/chromium/chrome/browser/resources/feedback/js/feedback.js
+++ b/chromium/chrome/browser/resources/feedback/js/feedback.js
@@ -8,6 +8,12 @@
var FEEDBACK_LANDING_PAGE =
'https://support.google.com/chrome/go/feedback_confirmation';
+/**
+ * @type {string}
+ * @const
+ */
+var SRT_DOWNLOAD_PAGE = 'https://www.google.com/chrome/cleanup-tool/';
+
/** @type {number}
* @const
*/
@@ -57,7 +63,18 @@ var STATS_WINDOW_ID = 'stats_window';
*/
var FeedbackFlow = {
REGULAR: 'regular', // Flow in a regular user session.
- LOGIN: 'login' // Flow on the login screen.
+ LOGIN: 'login', // Flow on the login screen.
+ SHOW_SRT_PROMPT: 'showSrtPrompt' // Prompt user to try Software Removal Tool
+};
+
+/**
+ * SRT Prompt Result defined in feedback_private.idl.
+ * @enum {string}
+ */
+var SrtPromptResult = {
+ ACCEPTED: 'accepted', // User accepted prompt.
+ DECLINED: 'declined', // User declined prompt.
+ CLOSED: 'closed', // User closed window without responding to prompt.
};
var attachedFileBlob = null;
@@ -71,6 +88,12 @@ var lastReader = null;
var isSystemInfoReady = false;
/**
+ * Indicates whether the SRT Prompt is currently being displayed.
+ * @type {boolean}
+ */
+var isShowingSrtPrompt = false;
+
+/**
* The callback used by the sys_info_page to receive the event that the system
* information is ready.
* @type {function(sysInfo)}
@@ -284,6 +307,32 @@ function initialize() {
if (!feedbackInfo.flow)
feedbackInfo.flow = FeedbackFlow.REGULAR;
+ if (feedbackInfo.flow == FeedbackFlow.SHOW_SRT_PROMPT) {
+ isShowingSrtPrompt = true;
+ $('content-pane').hidden = true;
+
+ $('srt-decline-button').onclick = function() {
+ isShowingSrtPrompt = false;
+ chrome.feedbackPrivate.logSrtPromptResult(SrtPromptResult.DECLINED);
+ $('srt-prompt').hidden = true;
+ $('content-pane').hidden = false;
+ };
+
+ $('srt-accept-button').onclick = function() {
+ chrome.feedbackPrivate.logSrtPromptResult(SrtPromptResult.ACCEPTED);
+ window.open(SRT_DOWNLOAD_PAGE, '_blank');
+ window.close();
+ };
+
+ $('close-button').addEventListener('click', function() {
+ if (isShowingSrtPrompt) {
+ chrome.feedbackPrivate.logSrtPromptResult(SrtPromptResult.CLOSED);
+ }
+ });
+ } else {
+ $('srt-prompt').hidden = true;
+ }
+
$('description-text').textContent = feedbackInfo.description;
if (feedbackInfo.pageUrl)
$('page-url-text').value = feedbackInfo.pageUrl;
@@ -335,7 +384,6 @@ function initialize() {
$('performance-info-link').onclick = openSlowTraceWindow;
}
</if>
-
chrome.feedbackPrivate.getStrings(function(strings) {
loadTimeData.data = strings;
i18nTemplate.process(document, loadTimeData);
diff --git a/chromium/chrome/browser/resources/gaia_auth/OWNERS b/chromium/chrome/browser/resources/gaia_auth/OWNERS
index 9e6ea7e5d7d..52882cc6e6c 100644
--- a/chromium/chrome/browser/resources/gaia_auth/OWNERS
+++ b/chromium/chrome/browser/resources/gaia_auth/OWNERS
@@ -1,5 +1,4 @@
-nkostylev@chromium.org
+achuith@chromium.org
+guohui@chromium.org
xiyuan@chromium.org
zelidrag@chromium.org
-guohui@chromium.org
-achuith@chromium.org
diff --git a/chromium/chrome/browser/resources/gaia_auth/saml_injected.js b/chromium/chrome/browser/resources/gaia_auth/saml_injected.js
index ae56f5cc537..f79c6264929 100644
--- a/chromium/chrome/browser/resources/gaia_auth/saml_injected.js
+++ b/chromium/chrome/browser/resources/gaia_auth/saml_injected.js
@@ -143,8 +143,9 @@
return;
var index = this.passwordFields_.length;
+ var fieldId = passwordField.id || passwordField.name || '';
passwordField.addEventListener(
- 'input', this.onPasswordChanged_.bind(this, index));
+ 'input', this.onPasswordChanged_.bind(this, index, fieldId));
this.passwordFields_.push(passwordField);
this.passwordValues_.push(passwordField.value);
},
@@ -153,16 +154,18 @@
* Check if the password field at |index| has changed. If so, sends back
* the updated value.
*/
- maybeSendUpdatedPassword: function(index) {
+ maybeSendUpdatedPassword: function(index, fieldId) {
var newValue = this.passwordFields_[index].value;
if (newValue == this.passwordValues_[index])
return;
this.passwordValues_[index] = newValue;
- // Use an invalid char for URL as delimiter to concatenate page url and
- // password field index to construct a unique ID for the password field.
- var passwordId = this.pageURL_.split('#')[0].split('?')[0] + '|' + index;
+ // Use an invalid char for URL as delimiter to concatenate page url,
+ // password field index and id to construct a unique ID for the password
+ // field.
+ var passwordId = this.pageURL_.split('#')[0].split('?')[0] +
+ '|' + index + '|' + fieldId;
this.channel_.send({
name: 'updatePassword',
id: passwordId,
@@ -174,9 +177,10 @@
* Handles 'change' event in the scraped password fields.
* @param {number} index The index of the password fields in
* |passwordFields_|.
+ * @param {string} fieldId The id or name of the password field or blank.
*/
- onPasswordChanged_: function(index) {
- this.maybeSendUpdatedPassword(index);
+ onPasswordChanged_: function(index, fieldId) {
+ this.maybeSendUpdatedPassword(index, fieldId);
}
};
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/OWNERS b/chromium/chrome/browser/resources/gaia_auth_host/OWNERS
index 210e4ec0dc7..15b905591ec 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/OWNERS
+++ b/chromium/chrome/browser/resources/gaia_auth_host/OWNERS
@@ -1,4 +1,3 @@
-nkostylev@chromium.org
+achuith@chromium.org
xiyuan@chromium.org
zelidrag@chromium.org
-achuith@chromium.org
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
index 4159df30217..1cc7b9ff11e 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -32,6 +32,7 @@ cr.define('cr.login', function() {
var SERVICE_ID = 'chromeoslogin';
var EMBEDDED_SETUP_CHROMEOS_ENDPOINT = 'embedded/setup/chromeos';
var SAML_REDIRECTION_PATH = 'samlredirect';
+ var BLANK_PAGE_URL = 'about:blank';
/**
* The source URL parameter for the constrained signin flow.
@@ -121,6 +122,7 @@ cr.define('cr.login', function() {
this.webview_ = typeof webview == 'string' ? $(webview) : webview;
assert(this.webview_);
+ this.isLoaded_ = false;
this.email_ = null;
this.password_ = null;
this.gaiaId_ = null,
@@ -129,6 +131,7 @@ cr.define('cr.login', function() {
this.skipForNow_ = false;
this.authFlow = AuthFlow.DEFAULT;
this.authDomain = '';
+ this.videoEnabled = false;
this.idpOrigin_ = null;
this.continueUrl_ = null;
this.continueUrlWithoutParams_ = null;
@@ -157,6 +160,9 @@ cr.define('cr.login', function() {
this.samlHandler_.addEventListener(
'authPageLoaded',
this.onAuthPageLoaded_.bind(this));
+ this.samlHandler_.addEventListener(
+ 'videoEnabled',
+ this.onVideoEnabled_.bind(this));
this.webview_.addEventListener('droplink', this.onDropLink_.bind(this));
this.webview_.addEventListener(
@@ -191,7 +197,8 @@ cr.define('cr.login', function() {
* Reinitializes authentication parameters so that a failed login attempt
* would not result in an infinite loop.
*/
- Authenticator.prototype.resetStates_ = function() {
+ Authenticator.prototype.resetStates = function() {
+ this.isLoaded_ = false;
this.email_ = null;
this.gaiaId_ = null;
this.password_ = null;
@@ -206,6 +213,15 @@ cr.define('cr.login', function() {
this.trusted_ = true;
this.authFlow = AuthFlow.DEFAULT;
this.samlHandler_.reset();
+ this.videoEnabled = false;
+ };
+
+ /**
+ * Resets the webview to the blank page.
+ */
+ Authenticator.prototype.resetWebview = function() {
+ if (this.webview_.src && this.webview_.src != BLANK_PAGE_URL)
+ this.webview_.src = BLANK_PAGE_URL;
};
/**
@@ -215,7 +231,7 @@ cr.define('cr.login', function() {
*/
Authenticator.prototype.load = function(authMode, data) {
this.authMode = authMode;
- this.resetStates_();
+ this.resetStates();
// gaiaUrl parameter is used for testing. Once defined, it is never changed.
this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN;
this.continueUrl_ = data.continueUrl || CONTINUE_URL;
@@ -256,14 +272,16 @@ cr.define('cr.login', function() {
}
this.webview_.src = this.reloadUrl_;
+ this.isLoaded_ = true;
};
/**
* Reloads the authenticator component.
*/
Authenticator.prototype.reload = function() {
- this.resetStates_();
+ this.resetStates();
this.webview_.src = this.reloadUrl_;
+ this.isLoaded_ = true;
};
Authenticator.prototype.constructInitialFrameUrl_ = function(data) {
@@ -650,6 +668,14 @@ cr.define('cr.login', function() {
// password when it is available but not a mandatory requirement.
console.warn('Authenticator: No password scraped for SAML.');
} else if (this.needPassword) {
+ if (this.samlHandler_.scrapedPasswordCount == 1) {
+ // If we scraped exactly one password, we complete the authentication
+ // right away.
+ this.password_ = this.samlHandler_.firstScrapedPassword;
+ this.onAuthCompleted_();
+ return;
+ }
+
if (this.confirmPasswordCallback) {
// Confirm scraped password. The flow follows in
// verifyConfirmedPassword.
@@ -686,7 +712,7 @@ cr.define('cr.login', function() {
gapsCookie: this.newGapsCookie_ || this.gapsCookie_ || '',
}
}));
- this.resetStates_();
+ this.resetStates();
};
/**
@@ -694,11 +720,13 @@ cr.define('cr.login', function() {
* @private
*/
Authenticator.prototype.onInsecureContentBlocked_ = function(e) {
- if (this.insecureContentBlockedCallback) {
+ if (!this.isLoaded_)
+ return;
+
+ if (this.insecureContentBlockedCallback)
this.insecureContentBlockedCallback(e.detail.url);
- } else {
+ else
console.error('Authenticator: Insecure content blocked.');
- }
};
/**
@@ -706,6 +734,9 @@ cr.define('cr.login', function() {
* @private
*/
Authenticator.prototype.onAuthPageLoaded_ = function(e) {
+ if (!this.isLoaded_)
+ return;
+
if (!e.detail.isSAMLPage)
return;
@@ -716,6 +747,14 @@ cr.define('cr.login', function() {
};
/**
+ * Invoked when |samlHandler_| fires 'videoEnabled' event.
+ * @private
+ */
+ Authenticator.prototype.onVideoEnabled_ = function(e) {
+ this.videoEnabled = true;
+ };
+
+ /**
* Invoked when a link is dropped on the webview.
* @private
*/
@@ -756,6 +795,8 @@ cr.define('cr.login', function() {
this.fireReadyEvent_();
// Focus webview after dispatching event when webview is already visible.
this.webview_.focus();
+ } else if (currentUrl == BLANK_PAGE_URL) {
+ this.fireReadyEvent_();
}
};
@@ -823,6 +864,12 @@ cr.define('cr.login', function() {
*/
cr.defineProperty(Authenticator, 'authDomain');
+ /**
+ * True if the page has requested media access.
+ * @type {boolean}
+ */
+ cr.defineProperty(Authenticator, 'videoEnabled');
+
Authenticator.AuthFlow = AuthFlow;
Authenticator.AuthMode = AuthMode;
Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS;
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js b/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js
index 9b6ceb94c00..cf7075b7d46 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js
@@ -147,6 +147,8 @@ cr.define('cr.login', function() {
'loadabort', this.onLoadAbort_.bind(this));
this.webview_.addEventListener(
'loadcommit', this.onLoadCommit_.bind(this));
+ this.webview_.addEventListener(
+ 'permissionrequest', this.onPermissionRequest_.bind(this));
this.webview_.request.onBeforeRequest.addListener(
this.onInsecureRequest.bind(this),
@@ -190,6 +192,15 @@ cr.define('cr.login', function() {
},
/**
+ * Returns the first scraped password if any, or an empty string otherwise.
+ * @return {string}
+ */
+ get firstScrapedPassword() {
+ var scraped = this.getConsolidatedScrapedPasswords_();
+ return scraped.length ? scraped[0] : '';
+ },
+
+ /**
* Returns the number of scraped passwords.
* @return {number}
*/
@@ -442,6 +453,15 @@ cr.define('cr.login', function() {
domain: this.authDomain}}));
},
+ onPermissionRequest_: function(permissionEvent) {
+ if (permissionEvent.permission === 'media') {
+ // The actual permission check happens in
+ // WebUILoginView::RequestMediaAccessPermission().
+ this.dispatchEvent(new CustomEvent('videoEnabled'));
+ permissionEvent.request.allow();
+ }
+ },
+
onGetSAMLFlag_: function(channel, msg) {
return this.isSamlPage_;
},
diff --git a/chromium/chrome/browser/resources/hangout_services/manifest.json b/chromium/chrome/browser/resources/hangout_services/manifest.json
index 92255eb9237..f495820f2b5 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.2.0",
+ "version": "1.3.0",
"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 db150069907..ef44a26863d 100644
--- a/chromium/chrome/browser/resources/hangout_services/thunk.js
+++ b/chromium/chrome/browser/resources/hangout_services/thunk.js
@@ -172,7 +172,17 @@ chrome.runtime.onMessageExternal.addListener(
chrome.webrtcLoggingPrivate.stopAudioDebugRecordings(
requestInfo, origin, doSendResponse);
return true;
+ } else if (method == 'logging.startWebRtcEventLogging') {
+ var seconds = message['seconds'] || 0;
+ chrome.webrtcLoggingPrivate.startWebRtcEventLogging(
+ requestInfo, origin, seconds, doSendResponse);
+ return true;
+ } else if (method == 'logging.stopWebRtcEventLogging') {
+ chrome.webrtcLoggingPrivate.stopWebRtcEventLogging(
+ requestInfo, origin, doSendResponse);
+ return true;
}
+
throw new Error('Unknown method: ' + method);
} catch (e) {
doSendResponse(null, e.name + ': ' + e.message);
diff --git a/chromium/chrome/browser/resources/help/help_content.html b/chromium/chrome/browser/resources/help/help_content.html
index 79b90935de7..3f7f911c159 100644
--- a/chromium/chrome/browser/resources/help/help_content.html
+++ b/chromium/chrome/browser/resources/help/help_content.html
@@ -21,6 +21,10 @@
<span i18n-content="platform"></span>&nbsp;<span id="os-version"></span>
</div>
<div>
+ <span i18n-content="arcVersion">
+ </span>&nbsp;<span id="arc-version"></span>
+ </div>
+ <div>
<span i18n-content="firmware"></span>&nbsp;<span id="firmware"></span>
</div>
</if>
diff --git a/chromium/chrome/browser/resources/help/help_page.js b/chromium/chrome/browser/resources/help/help_page.js
index e4a6afa23af..c2eb0d5a9fe 100644
--- a/chromium/chrome/browser/resources/help/help_page.js
+++ b/chromium/chrome/browser/resources/help/help_page.js
@@ -505,6 +505,18 @@ cr.define('help', function() {
},
/**
+ * @param {string} version Version of ARC.
+ * @private
+ */
+ setARCVersion_: function(version) {
+ if (!cr.isChromeOS)
+ console.error('ARC version unsupported on non-CrOS');
+
+ $('arc-version').parentNode.hidden = (version == '');
+ $('arc-version').textContent = version;
+ },
+
+ /**
* @param {string} firmware Firmware on Chrome OS.
* @private
*/
@@ -670,6 +682,10 @@ cr.define('help', function() {
HelpPage.getInstance().setOSVersion_(version);
};
+ HelpPage.setARCVersion = function(version) {
+ HelpPage.getInstance().setARCVersion_(version);
+ };
+
HelpPage.setOSFirmware = function(firmware) {
HelpPage.getInstance().setOSFirmware_(firmware);
};
diff --git a/chromium/chrome/browser/resources/help_app/OWNERS b/chromium/chrome/browser/resources/help_app/OWNERS
index 5f0f5fd6500..925462999cb 100644
--- a/chromium/chrome/browser/resources/help_app/OWNERS
+++ b/chromium/chrome/browser/resources/help_app/OWNERS
@@ -1,4 +1,4 @@
-nkostylev@chromium.org
+achuith@chromium.org
cnwan@chromium.org
cylee@chromium.org
davidyu@chromium.org
diff --git a/chromium/chrome/browser/resources/history/compiled_resources2.gyp b/chromium/chrome/browser/resources/history/compiled_resources2.gyp
index 6efe6a888b7..43b35c934cd 100644
--- a/chromium/chrome/browser/resources/history/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/history/compiled_resources2.gyp
@@ -23,6 +23,7 @@
'<(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:event_tracker',
+ '<(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:util',
'<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:ui',
diff --git a/chromium/chrome/browser/resources/history/history.html b/chromium/chrome/browser/resources/history/history.html
index f8ea179f815..e49624d7503 100644
--- a/chromium/chrome/browser/resources/history/history.html
+++ b/chromium/chrome/browser/resources/history/history.html
@@ -50,6 +50,7 @@
<script src="chrome://resources/js/cr/event_target.js"></script>
<script src="chrome://resources/js/cr/ui/context_menu_handler.js"></script>
+<script src="chrome://resources/js/icon.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/util.js"></script>
diff --git a/chromium/chrome/browser/resources/history/history.js b/chromium/chrome/browser/resources/history/history.js
index 1fac5042896..64458dbeeff 100644
--- a/chromium/chrome/browser/resources/history/history.js
+++ b/chromium/chrome/browser/resources/history/history.js
@@ -462,7 +462,7 @@ Visit.prototype.loadFavicon_ = function(faviconDiv) {
img.onload = this.onLargeFaviconLoadedAndroid_.bind(this, faviconDiv);
img.src = 'chrome://large-icon/' + desiredPixelSize + '/' + this.url_;
} else {
- faviconDiv.style.backgroundImage = getFaviconImageSet(this.url_);
+ faviconDiv.style.backgroundImage = cr.icon.getFaviconImageSet(this.url_);
}
};
diff --git a/chromium/chrome/browser/resources/history/other_devices.js b/chromium/chrome/browser/resources/history/other_devices.js
index 8f46192d61f..6dca06be86f 100644
--- a/chromium/chrome/browser/resources/history/other_devices.js
+++ b/chromium/chrome/browser/resources/history/other_devices.js
@@ -263,7 +263,7 @@ Device.prototype.createSessionContents_ = function(maxNumTabs) {
numTabsShown++;
var a = createElementWithClassName('a', 'device-tab-entry');
a.href = tab.url;
- a.style.backgroundImage = getFaviconImageSet(tab.url);
+ a.style.backgroundImage = cr.icon.getFaviconImageSet(tab.url);
this.addHighlightedText_(a, tab.title);
// Add a tooltip, since it might be ellipsized. The ones that are not
// necessary will be removed once added to the document, so we can
diff --git a/chromium/chrome/browser/resources/inline_login/OWNERS b/chromium/chrome/browser/resources/inline_login/OWNERS
new file mode 100644
index 00000000000..408e7263ff1
--- /dev/null
+++ b/chromium/chrome/browser/resources/inline_login/OWNERS
@@ -0,0 +1 @@
+achuith@chromium.org
diff --git a/chromium/chrome/browser/resources/local_discovery/local_discovery.js b/chromium/chrome/browser/resources/local_discovery/local_discovery.js
index 3e2fb1b8ad5..cdad0b5ab1c 100644
--- a/chromium/chrome/browser/resources/local_discovery/local_discovery.js
+++ b/chromium/chrome/browser/resources/local_discovery/local_discovery.js
@@ -607,14 +607,6 @@ cr.define('local_discovery', function() {
}
}
- function removeCloudPrintConnectorSection() {
- if (!cr.isChromeOS) {
- var connectorSectionElm = $('cloud-print-connector-section');
- if (connectorSectionElm)
- connectorSectionElm.parentNode.removeChild(connectorSectionElm);
- }
- }
-
function getOverlayIDFromPath() {
if (document.location.pathname == '/register') {
var params = parseQueryParams(document.location);
@@ -693,6 +685,5 @@ cr.define('local_discovery', function() {
onRegistrationTimeout: onRegistrationTimeout,
setUserLoggedIn: setUserLoggedIn,
setupCloudPrintConnectorSection: setupCloudPrintConnectorSection,
- removeCloudPrintConnectorSection: removeCloudPrintConnectorSection
};
});
diff --git a/chromium/chrome/browser/resources/local_ntp/OWNERS b/chromium/chrome/browser/resources/local_ntp/OWNERS
index 6d4196126a1..98b64ed0bde 100644
--- a/chromium/chrome/browser/resources/local_ntp/OWNERS
+++ b/chromium/chrome/browser/resources/local_ntp/OWNERS
@@ -4,3 +4,4 @@ samarth@chromium.org
mathp@chromium.org
fserb@chromium.org
huangs@chromium.org
+treib@chromium.org
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 5a7350ac7e2..a17d779578c 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_single.js
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -67,6 +67,19 @@ var USE_ICONS = false;
*/
var NUM_TITLE_LINES = 1;
+/**
+ * Type of the impression provider for a generic client-provided suggestion.
+ * @type {string}
+ * @const
+ */
+var CLIENT_PROVIDER_NAME = 'client';
+
+/**
+ * Type of the impression provider for a generic server-provided suggestion.
+ * @type {string}
+ * @const
+ */
+var SERVER_PROVIDER_NAME = 'server';
/**
* The origin of this request.
@@ -110,6 +123,27 @@ var logEvent = function(eventType) {
chrome.embeddedSearch.newTabPage.logEvent(eventType);
};
+/**
+ * Log impression of a most visited tile on the NTP.
+ * @param {number} tileIndex position of the tile, >= 0 and < NUMBER_OF_TILES
+ * @param {string} provider specifies the UMA histogram to be reported
+ * (NewTabPage.SuggestionsImpression.{provider})
+ */
+function logMostVisitedImpression(tileIndex, provider) {
+ chrome.embeddedSearch.newTabPage.logMostVisitedImpression(tileIndex,
+ provider);
+}
+
+/**
+ * Log click on a most visited tile on the NTP.
+ * @param {number} tileIndex position of the tile, >= 0 and < NUMBER_OF_TILES
+ * @param {string} provider specifies the UMA histogram to be reported
+ * (NewTabPage.SuggestionsImpression.{provider})
+ */
+function logMostVisitedNavigation(tileIndex, provider) {
+ chrome.embeddedSearch.newTabPage.logMostVisitedNavigation(tileIndex,
+ provider);
+}
/**
* Down counts the DOM elements that we are waiting for the page to load.
@@ -284,22 +318,35 @@ var showTiles = function() {
* @param {object} args Data for the tile to be rendered.
*/
var addTile = function(args) {
- if (args.rid) {
+ if (isFinite(args.rid)) {
+ // If a valid number passed in |args.rid|: a local chrome suggestion.
var data = chrome.embeddedSearch.searchBox.getMostVisitedItemData(args.rid);
+ if (!data)
+ return;
+
data.tid = data.rid;
+ data.provider = CLIENT_PROVIDER_NAME;
if (!data.faviconUrl) {
data.faviconUrl = 'chrome-search://favicon/size/16@' +
window.devicePixelRatio + 'x/' + data.renderViewId + '/' + data.tid;
}
+ logEvent(LOG_TYPE.NTP_CLIENT_SIDE_SUGGESTION);
tiles.appendChild(renderTile(data));
- } else if (args.id) {
+ } else if (args.url) {
+ // If a URL is passed: a server-side suggestion.
+ args.provider = args.provider || SERVER_PROVIDER_NAME;
+ // check sanity of the arguments
+ if (/^javascript:/i.test(args.url) ||
+ /^javascript:/i.test(args.thumbnailUrl) ||
+ !/^[a-z0-9]{0,8}$/i.test(args.provider))
+ return;
+ logEvent(LOG_TYPE.NTP_SERVER_SIDE_SUGGESTION);
tiles.appendChild(renderTile(args));
- } else {
+ } else { // an empty tile
tiles.appendChild(renderTile(null));
}
};
-
/**
* Called when the user decided to add a tile to the blacklist.
* It sets of the animation for the blacklist and sends the blacklisted id
@@ -343,6 +390,11 @@ var renderTile = function(data) {
}
logEvent(LOG_TYPE.NTP_TILE);
+ // The tile will be appended to tiles.
+ var position = tiles.children.length;
+ if (data.provider) {
+ logMostVisitedImpression(position, data.provider);
+ }
tile.className = 'mv-tile';
tile.setAttribute('data-tid', data.tid);
@@ -367,10 +419,15 @@ var renderTile = function(data) {
navigator.sendBeacon(data.pingUrl);
});
}
- // For local suggestions, we use navigateContentWindow instead of the default
- // action, since it includes support for file:// urls.
- if (data.rid) {
- tile.addEventListener('click', function(ev) {
+
+ tile.addEventListener('click', function(ev) {
+ if (data.provider) {
+ logMostVisitedNavigation(position, data.provider);
+ }
+
+ // For local suggestions, we use navigateContentWindow instead of the
+ // default action, since it includes support for file:// urls.
+ if (data.rid) {
ev.preventDefault();
var disp = chrome.embeddedSearch.newTabPage.getDispositionFromClick(
ev.button == 1, // MIDDLE BUTTON
@@ -378,8 +435,8 @@ var renderTile = function(data) {
window.chrome.embeddedSearch.newTabPage.navigateContentWindow(data.rid,
disp);
- });
- }
+ }
+ });
tile.addEventListener('keydown', function(event) {
if (event.keyCode == 46 /* DELETE */ ||
@@ -392,58 +449,31 @@ var renderTile = function(data) {
event.preventDefault();
this.click();
} else if (event.keyCode >= 37 && event.keyCode <= 40 /* ARROWS */) {
- var tiles = document.querySelectorAll('#mv-tiles .mv-tile');
+ // specify the direction of movement
+ var inArrowDirection = function(origin, target) {
+ return (event.keyCode == 37 /* LEFT */ &&
+ origin.offsetTop == target.offsetTop &&
+ origin.offsetLeft > target.offsetLeft) ||
+ (event.keyCode == 38 /* UP */ &&
+ origin.offsetTop > target.offsetTop &&
+ origin.offsetLeft == target.offsetLeft) ||
+ (event.keyCode == 39 /* RIGHT */ &&
+ origin.offsetTop == target.offsetTop &&
+ origin.offsetLeft < target.offsetLeft) ||
+ (event.keyCode == 40 /* DOWN */ &&
+ origin.offsetTop < target.offsetTop &&
+ origin.offsetLeft == target.offsetLeft);
+ };
+
+ var nonEmptyTiles = document.querySelectorAll('#mv-tiles .mv-tile');
var nextTile = null;
- // Use the location of the tile to find the next one in the
- // appropriate direction.
- // For LEFT and UP we keep iterating until we find the last element
- // that fulfills the conditions.
- // For RIGHT and DOWN we accept the first element that works.
- if (event.keyCode == 37 /* LEFT */) {
- for (var i = 0; i < tiles.length; i++) {
- var tile = tiles[i];
- if (tile.offsetTop == this.offsetTop &&
- tile.offsetLeft < this.offsetLeft) {
- if (!nextTile || tile.offsetLeft > nextTile.offsetLeft) {
- nextTile = tile;
- }
- }
- }
- }
- if (event.keyCode == 38 /* UP */) {
- for (var i = 0; i < tiles.length; i++) {
- var tile = tiles[i];
- if (tile.offsetTop < this.offsetTop &&
- tile.offsetLeft == this.offsetLeft) {
- if (!nextTile || tile.offsetTop > nextTile.offsetTop) {
- nextTile = tile;
- }
- }
- }
- }
- if (event.keyCode == 39 /* RIGHT */) {
- for (var i = 0; i < tiles.length; i++) {
- var tile = tiles[i];
- if (tile.offsetTop == this.offsetTop &&
- tile.offsetLeft > this.offsetLeft) {
- if (!nextTile || tile.offsetLeft < nextTile.offsetLeft) {
- nextTile = tile;
- }
- }
- }
- }
- if (event.keyCode == 40 /* DOWN */) {
- for (var i = 0; i < tiles.length; i++) {
- var tile = tiles[i];
- if (tile.offsetTop > this.offsetTop &&
- tile.offsetLeft == this.offsetLeft) {
- if (!nextTile || tile.offsetTop < nextTile.offsetTop) {
- nextTile = tile;
- }
- }
+ // Find the closest tile in the appropriate direction.
+ for (var i = 0; i < nonEmptyTiles.length; i++) {
+ if (inArrowDirection(this, nonEmptyTiles[i]) &&
+ (!nextTile || inArrowDirection(nonEmptyTiles[i], nextTile))) {
+ nextTile = nonEmptyTiles[i];
}
}
-
if (nextTile) {
nextTile.focus();
}
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 3bdfd612e36..33baada73da 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_thumbnail.js
@@ -78,8 +78,8 @@ window.addEventListener('DOMContentLoaded', function() {
} else if (useIcons && data.largeIconUrl) {
createThumbnail(data.largeIconUrl, 'large-icon');
// TODO(huangs): Log event for large icons.
- } else if (!useIcons && data.thumbnailUrl) {
- createThumbnail(data.thumbnailUrl, 'thumbnail');
+ } else if (!useIcons && data.thumbnailUrls && data.thumbnailUrls.length) {
+ createThumbnail(data.thumbnailUrls[0], 'thumbnail');
logEvent(NTP_LOGGING_EVENT_TYPE.NTP_THUMBNAIL_TILE);
} else if (data.domain) {
showDomainElement();
diff --git a/chromium/chrome/browser/resources/md_downloads/crisper.js b/chromium/chrome/browser/resources/md_downloads/crisper.js
index efa2abf0e12..9dd82fbfb55 100644
--- a/chromium/chrome/browser/resources/md_downloads/crisper.js
+++ b/chromium/chrome/browser/resources/md_downloads/crisper.js
@@ -1,3 +1,75 @@
+// 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.
+
+/**
+ * @fileoverview Assertion support.
+ */
+
+/**
+ * Verify |condition| is truthy and return |condition| if so.
+ * @template T
+ * @param {T} condition A condition to check for truthiness. Note that this
+ * may be used to test whether a value is defined or not, and we don't want
+ * to force a cast to Boolean.
+ * @param {string=} opt_message A message to show on failure.
+ * @return {T} A non-null |condition|.
+ */
+function assert(condition, opt_message) {
+ if (!condition) {
+ var message = 'Assertion failed';
+ if (opt_message)
+ message = message + ': ' + opt_message;
+ var error = new Error(message);
+ var global = function() { return this; }();
+ if (global.traceAssertionsForTesting)
+ console.warn(error.stack);
+ throw error;
+ }
+ return condition;
+}
+
+/**
+ * Call this from places in the code that should never be reached.
+ *
+ * For example, handling all the values of enum with a switch() like this:
+ *
+ * function getValueFromEnum(enum) {
+ * switch (enum) {
+ * case ENUM_FIRST_OF_TWO:
+ * return first
+ * case ENUM_LAST_OF_TWO:
+ * return last;
+ * }
+ * assertNotReached();
+ * return document;
+ * }
+ *
+ * This code should only be hit in the case of serious programmer error or
+ * unexpected input.
+ *
+ * @param {string=} opt_message A message to show when this is hit.
+ */
+function assertNotReached(opt_message) {
+ assert(false, opt_message || 'Unreachable code hit');
+}
+
+/**
+ * @param {*} value The value to check.
+ * @param {function(new: T, ...)} type A user-defined constructor.
+ * @param {string=} opt_message A message to show when this is hit.
+ * @return {T}
+ * @template T
+ */
+function assertInstanceof(value, type, opt_message) {
+ // We don't use assert immediately here so that we avoid constructing an error
+ // message if we don't have to.
+ if (!(value instanceof type)) {
+ assertNotReached(opt_message || 'Value ' + value +
+ ' is not a[n] ' + (type.name || typeof type));
+ }
+ return value;
+};
// 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.
@@ -21,17 +93,31 @@
* @template T
*/
function PromiseResolver() {
- /** @type {function(T): void} */
- this.resolve;
+ /** @private {function(T=): void} */
+ this.resolve_;
- /** @type {function(*=): void} */
- this.reject;
+ /** @private {function(*=): void} */
+ this.reject_;
- /** @type {!Promise<T>} */
- this.promise = new Promise(function(resolve, reject) {
- this.resolve = resolve;
- this.reject = reject;
+ /** @private {!Promise<T>} */
+ this.promise_ = new Promise(function(resolve, reject) {
+ this.resolve_ = resolve;
+ this.reject_ = reject;
}.bind(this));
+}
+
+PromiseResolver.prototype = {
+ /** @return {!Promise<T>} */
+ get promise() { return this.promise_; },
+ set promise(p) { assertNotReached(); },
+
+ /** @return {function(T=): void} */
+ get resolve() { return this.resolve_; },
+ set resolve(r) { assertNotReached(); },
+
+ /** @return {function(*=): void} */
+ get reject() { return this.reject_; },
+ set reject(s) { assertNotReached(); },
};
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
@@ -1103,30 +1189,6 @@ function announceAccessibleMessage(msg) {
}
/**
- * Returns the scale factors supported by this platform for webui
- * resources.
- * @return {Array} The supported scale factors.
- */
-function getSupportedScaleFactors() {
- var supportedScaleFactors = [];
- if (cr.isMac || cr.isChromeOS || cr.isWindows || cr.isLinux) {
- // All desktop platforms support zooming which also updates the
- // renderer's device scale factors (a.k.a devicePixelRatio), and
- // these platforms has high DPI assets for 2.0x. Use 1x and 2x in
- // image-set on these platforms so that the renderer can pick the
- // closest image for the current device scale factor.
- supportedScaleFactors.push(1);
- supportedScaleFactors.push(2);
- } else {
- // For other platforms that use fixed device scale factor, use
- // the window's device pixel ratio.
- // TODO(oshima): Investigate if Android/iOS need to use image-set.
- supportedScaleFactors.push(window.devicePixelRatio);
- }
- return supportedScaleFactors;
-}
-
-/**
* Generates a CSS url string.
* @param {string} s The URL to generate the CSS url for.
* @return {string} The CSS url string.
@@ -1146,51 +1208,6 @@ function url(s) {
}
/**
- * Returns the URL of the image, or an image set of URLs for the profile avatar.
- * Default avatars have resources available for multiple scalefactors, whereas
- * the GAIA profile image only comes in one size.
- *
- * @param {string} path The path of the image.
- * @return {string} The url, or an image set of URLs of the avatar image.
- */
-function getProfileAvatarIcon(path) {
- var chromeThemePath = 'chrome://theme';
- var isDefaultAvatar =
- (path.slice(0, chromeThemePath.length) == chromeThemePath);
- return isDefaultAvatar ? imageset(path + '@scalefactorx'): url(path);
-}
-
-/**
- * Generates a CSS -webkit-image-set for a chrome:// url.
- * An entry in the image set is added for each of getSupportedScaleFactors().
- * The scale-factor-specific url is generated by replacing the first instance of
- * 'scalefactor' in |path| with the numeric scale factor.
- * @param {string} path The URL to generate an image set for.
- * 'scalefactor' should be a substring of |path|.
- * @return {string} The CSS -webkit-image-set.
- */
-function imageset(path) {
- var supportedScaleFactors = getSupportedScaleFactors();
-
- var replaceStartIndex = path.indexOf('scalefactor');
- if (replaceStartIndex < 0)
- return url(path);
-
- var s = '';
- for (var i = 0; i < supportedScaleFactors.length; ++i) {
- var scaleFactor = supportedScaleFactors[i];
- var pathWithScaleFactor = path.substr(0, replaceStartIndex) + scaleFactor +
- path.substr(replaceStartIndex + 'scalefactor'.length);
-
- s += url(pathWithScaleFactor) + ' ' + scaleFactor + 'x';
-
- if (i != supportedScaleFactors.length - 1)
- s += ', ';
- }
- return '-webkit-image-set(' + s + ')';
-}
-
-/**
* Parses query parameters from Location.
* @param {Location} location The URL to generate the CSS url for.
* @return {Object} Dictionary containing name value pairs for URL
@@ -1382,39 +1399,6 @@ function appendParam(url, key, value) {
}
/**
- * Creates a CSS -webkit-image-set for a favicon request.
- * @param {string} url The url for the favicon.
- * @param {number=} opt_size Optional preferred size of the favicon.
- * @param {string=} opt_type Optional type of favicon to request. Valid values
- * are 'favicon' and 'touch-icon'. Default is 'favicon'.
- * @return {string} -webkit-image-set for the favicon.
- */
-function getFaviconImageSet(url, opt_size, opt_type) {
- var size = opt_size || 16;
- var type = opt_type || 'favicon';
- return imageset(
- 'chrome://' + type + '/size/' + size + '@scalefactorx/' + url);
-}
-
-/**
- * Creates a new URL for a favicon request for the current device pixel ratio.
- * The URL must be updated when the user moves the browser to a screen with a
- * different device pixel ratio. Use getFaviconImageSet() for the updating to
- * occur automatically.
- * @param {string} url The url for the favicon.
- * @param {number=} opt_size Optional preferred size of the favicon.
- * @param {string=} opt_type Optional type of favicon to request. Valid values
- * are 'favicon' and 'touch-icon'. Default is 'favicon'.
- * @return {string} Updated URL for the favicon.
- */
-function getFaviconUrlForCurrentDevicePixelRatio(url, opt_size, opt_type) {
- var size = opt_size || 16;
- var type = opt_type || 'favicon';
- return 'chrome://' + type + '/size/' + size + '@' +
- window.devicePixelRatio + 'x/' + url;
-}
-
-/**
* Creates an element of a specified type with a specified class name.
* @param {string} type The node type.
* @param {string} className The class name to use.
@@ -2176,20 +2160,31 @@ function quoteString(str) {
/**
* Specifies the element that will handle the scroll event
- * on the behalf of the current element. This is typically a reference to an `Element`,
+ * on the behalf of the current element. This is typically a reference to an element,
* but there are a few more posibilities:
*
* ### Elements id
*
*```html
- * <div id="scrollable-element" style="overflow-y: auto;">
+ * <div id="scrollable-element" style="overflow: auto;">
* <x-element scroll-target="scrollable-element">
- * Content
+ * \x3c!-- Content--\x3e
* </x-element>
* </div>
*```
- * In this case, `scrollTarget` will point to the outer div element. Alternatively,
- * you can set the property programatically:
+ * In this case, the `scrollTarget` will point to the outer div element.
+ *
+ * ### Document scrolling
+ *
+ * For document scrolling, you can use the reserved word `document`:
+ *
+ *```html
+ * <x-element scroll-target="document">
+ * \x3c!-- Content --\x3e
+ * </x-element>
+ *```
+ *
+ * ### Elements reference
*
*```js
* appHeader.scrollTarget = document.querySelector('#scrollable-element');
@@ -2210,42 +2205,39 @@ function quoteString(str) {
],
_scrollTargetChanged: function(scrollTarget, isAttached) {
- // Remove lister to the current scroll target
+ var eventTarget;
+
if (this._oldScrollTarget) {
- if (this._oldScrollTarget === this._doc) {
- window.removeEventListener('scroll', this._boundScrollHandler);
- } else if (this._oldScrollTarget.removeEventListener) {
- this._oldScrollTarget.removeEventListener('scroll', this._boundScrollHandler);
- }
+ eventTarget = this._oldScrollTarget === this._doc ? window : this._oldScrollTarget;
+ eventTarget.removeEventListener('scroll', this._boundScrollHandler);
this._oldScrollTarget = null;
}
- if (isAttached) {
- // Support element id references
- if (typeof scrollTarget === 'string') {
- var host = this.domHost;
- this.scrollTarget = host && host.$ ? host.$[scrollTarget] :
- Polymer.dom(this.ownerDocument).querySelector('#' + scrollTarget);
+ if (!isAttached) {
+ return;
+ }
+ // Support element id references
+ if (scrollTarget === 'document') {
- } else if (this._scrollHandler) {
+ this.scrollTarget = this._doc;
- this._boundScrollHandler = this._boundScrollHandler || this._scrollHandler.bind(this);
- // Add a new listener
- if (scrollTarget === this._doc) {
- window.addEventListener('scroll', this._boundScrollHandler);
- if (this._scrollTop !== 0 || this._scrollLeft !== 0) {
- this._scrollHandler();
- }
- } else if (scrollTarget && scrollTarget.addEventListener) {
- scrollTarget.addEventListener('scroll', this._boundScrollHandler);
- }
- this._oldScrollTarget = scrollTarget;
- }
+ } else if (typeof scrollTarget === 'string') {
+
+ this.scrollTarget = this.domHost ? this.domHost.$[scrollTarget] :
+ Polymer.dom(this.ownerDocument).querySelector('#' + scrollTarget);
+
+ } else if (this._isValidScrollTarget()) {
+
+ eventTarget = scrollTarget === this._doc ? window : scrollTarget;
+ this._boundScrollHandler = this._boundScrollHandler || this._scrollHandler.bind(this);
+ this._oldScrollTarget = scrollTarget;
+
+ eventTarget.addEventListener('scroll', this._boundScrollHandler);
}
},
/**
- * Runs on every scroll event. Consumer of this behavior may want to override this method.
+ * Runs on every scroll event. Consumer of this behavior may override this method.
*
* @protected
*/
@@ -2374,8 +2366,8 @@ function quoteString(str) {
var IOS = navigator.userAgent.match(/iP(?:hone|ad;(?: U;)? CPU) OS (\d+)/);
var IOS_TOUCH_SCROLLING = IOS && IOS[1] >= 8;
var DEFAULT_PHYSICAL_COUNT = 3;
- var MAX_PHYSICAL_COUNT = 500;
var HIDDEN_Y = '-10000px';
+ var DEFAULT_GRID_SIZE = 200;
Polymer({
@@ -2392,6 +2384,14 @@ function quoteString(str) {
},
/**
+ * The max count of physical items the pool can extend to.
+ */
+ maxPhysicalCount: {
+ type: Number,
+ value: 500
+ },
+
+ /**
* The name of the variable to add to the binding scope for the array
* element associated with a given template instance.
*/
@@ -2419,6 +2419,24 @@ function quoteString(str) {
},
/**
+ * When true, the list is rendered as a grid. Grid items must have
+ * fixed width and height set via CSS. e.g.
+ *
+ * ```html
+ * <iron-list grid>
+ * <template>
+ * <div style="width: 100px; height: 100px;"> 100x100 </div>
+ * </template>
+ * </iron-list>
+ * ```
+ */
+ grid: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true
+ },
+
+ /**
* When true, tapping a row will select the item, placing its data model
* in the set of selected items retrievable via the selection property.
*
@@ -2472,10 +2490,6 @@ function quoteString(str) {
Polymer.IronScrollTargetBehavior
],
- listeners: {
- 'iron-resize': '_resizeHandler'
- },
-
keyBindings: {
'up': '_didMoveUp',
'down': '_didMoveDown',
@@ -2542,7 +2556,12 @@ function quoteString(str) {
/**
* The height of the list. This is referred as the viewport in the context of list.
*/
- _viewportSize: 0,
+ _viewportHeight: 0,
+
+ /**
+ * The width of the list. This is referred as the viewport in the context of list.
+ */
+ _viewportWidth: 0,
/**
* An array of DOM nodes that are currently in the tree
@@ -2615,6 +2634,21 @@ function quoteString(str) {
_focusBackfillItem: null,
/**
+ * The maximum items per row
+ */
+ _itemsPerRow: 1,
+
+ /**
+ * The width of each grid item
+ */
+ _itemWidth: 0,
+
+ /**
+ * The height of the row in grid layout.
+ */
+ _rowHeight: 0,
+
+ /**
* The bottom of the physical content.
*/
get _physicalBottom() {
@@ -2625,7 +2659,7 @@ function quoteString(str) {
* The bottom of the scroll.
*/
get _scrollBottom() {
- return this._scrollPosition + this._viewportSize;
+ return this._scrollPosition + this._viewportHeight;
},
/**
@@ -2639,14 +2673,15 @@ function quoteString(str) {
* The height of the physical content that isn't on the screen.
*/
get _hiddenContentSize() {
- return this._physicalSize - this._viewportSize;
+ var size = this.grid ? this._physicalRows * this._rowHeight : this._physicalSize;
+ return size - this._viewportHeight;
},
/**
* The maximum scroll top value.
*/
get _maxScrollTop() {
- return this._estScrollHeight - this._viewportSize + this._scrollerPaddingTop;
+ return this._estScrollHeight - this._viewportHeight + this._scrollerPaddingTop;
},
/**
@@ -2718,7 +2753,14 @@ function quoteString(str) {
* to a viewport of physical items above and below the user's viewport.
*/
get _optPhysicalSize() {
- return this._viewportSize * this._maxPages;
+ if (this.grid) {
+ return this._estRowsInView * this._rowHeight * this._maxPages;
+ }
+ return this._viewportHeight * this._maxPages;
+ },
+
+ get _optPhysicalCount() {
+ return this._estRowsInView * this._itemsPerRow * this._maxPages;
},
/**
@@ -2735,13 +2777,19 @@ function quoteString(str) {
*/
get firstVisibleIndex() {
if (this._firstVisibleIndexVal === null) {
- var physicalOffset = this._physicalTop + this._scrollerPaddingTop;
+ var physicalOffset = Math.floor(this._physicalTop + this._scrollerPaddingTop);
this._firstVisibleIndexVal = this._iterateItems(
function(pidx, vidx) {
- physicalOffset += this._physicalSizes[pidx];
+ physicalOffset += this._getPhysicalSizeIncrement(pidx);
+
if (physicalOffset > this._scrollPosition) {
- return vidx;
+ return this.grid ? vidx - (vidx % this._itemsPerRow) : vidx;
+ }
+
+ // Handle a partially rendered final row in grid mode
+ if (this.grid && this._virtualCount - 1 === vidx) {
+ return vidx - (vidx % this._itemsPerRow);
}
}) || 0;
}
@@ -2755,15 +2803,25 @@ function quoteString(str) {
*/
get lastVisibleIndex() {
if (this._lastVisibleIndexVal === null) {
- var physicalOffset = this._physicalTop;
+ if (this.grid) {
+ var lastIndex = this.firstVisibleIndex + this._estRowsInView * this._itemsPerRow - 1;
+ this._lastVisibleIndexVal = lastIndex > this._virtualCount ? this._virtualCount : lastIndex;
+ } else {
+ var physicalOffset = this._physicalTop;
- this._iterateItems(function(pidx, vidx) {
- physicalOffset += this._physicalSizes[pidx];
+ this._iterateItems(function(pidx, vidx) {
+ physicalOffset += this._getPhysicalSizeIncrement(pidx);
- if (physicalOffset <= this._scrollBottom) {
- this._lastVisibleIndexVal = vidx;
- }
- });
+ if(physicalOffset <= this._scrollBottom) {
+ if (this.grid) {
+ var lastIndex = vidx - vidx % this._itemsPerRow + this._itemsPerRow - 1;
+ this._lastVisibleIndexVal = lastIndex > this._virtualCount ? this._virtualCount : lastIndex;
+ } else {
+ this._lastVisibleIndexVal = vidx;
+ }
+ }
+ });
+ }
}
return this._lastVisibleIndexVal;
},
@@ -2771,6 +2829,17 @@ function quoteString(str) {
get _defaultScrollTarget() {
return this;
},
+ get _virtualRowCount() {
+ return Math.ceil(this._virtualCount / this._itemsPerRow);
+ },
+
+ get _estRowsInView() {
+ return Math.ceil(this._viewportHeight / this._rowHeight);
+ },
+
+ get _physicalRows() {
+ return Math.ceil(this._physicalCount / this._itemsPerRow);
+ },
ready: function() {
this.addEventListener('focus', this._didFocus.bind(this), true);
@@ -2779,10 +2848,14 @@ function quoteString(str) {
attached: function() {
this.updateViewportBoundaries();
this._render();
+ // `iron-resize` is fired when the list is attached if the event is added
+ // before attached causing unnecessary work.
+ this.listen(this, 'iron-resize', '_resizeHandler');
},
detached: function() {
this._itemsRendered = false;
+ this.unlisten(this, 'iron-resize', '_resizeHandler');
},
/**
@@ -2803,7 +2876,10 @@ function quoteString(str) {
this._scrollerPaddingTop = this.scrollTarget === this ? 0 :
parseInt(window.getComputedStyle(this)['padding-top'], 10);
- this._viewportSize = this._scrollTargetHeight;
+ this._viewportHeight = this._scrollTargetHeight;
+ if (this.grid) {
+ this._updateGridMetrics();
+ }
},
/**
@@ -2855,10 +2931,10 @@ function quoteString(str) {
// ensure that these recycled tiles are needed
virtualStart - recycledTiles > 0 &&
// ensure that the tile is not visible
- physicalBottom - this._physicalSizes[kth] > scrollBottom
+ physicalBottom - this._getPhysicalSizeIncrement(kth) > scrollBottom
) {
- tileHeight = this._physicalSizes[kth];
+ tileHeight = this._getPhysicalSizeIncrement(kth);
currentRatio += tileHeight / hiddenContentSize;
physicalBottom -= tileHeight;
recycledTileSet.push(kth);
@@ -2889,10 +2965,10 @@ function quoteString(str) {
// ensure that these recycled tiles are needed
virtualEnd + recycledTiles < lastVirtualItemIndex &&
// ensure that the tile is not visible
- this._physicalTop + this._physicalSizes[kth] < scrollTop
+ this._physicalTop + this._getPhysicalSizeIncrement(kth) < scrollTop
) {
- tileHeight = this._physicalSizes[kth];
+ tileHeight = this._getPhysicalSizeIncrement(kth);
currentRatio += tileHeight / hiddenContentSize;
this._physicalTop += tileHeight;
@@ -2903,11 +2979,9 @@ function quoteString(str) {
}
if (recycledTiles === 0) {
- // If the list ever reach this case, the physical average is not significant enough
- // to create all the items needed to cover the entire viewport.
- // e.g. A few items have a height that differs from the average by serveral order of magnitude.
+ // Try to increase the pool if the list's client height isn't filled up with physical items
if (physicalBottom < scrollBottom || this._physicalTop > scrollTop) {
- this.async(this._increasePool.bind(this, 1));
+ this._increasePoolIfNeeded();
}
} else {
this._virtualStart = this._virtualStart + recycledTiles;
@@ -2931,7 +3005,8 @@ function quoteString(str) {
// adjust offset after measuring
if (movingUp) {
while (movingUp.length) {
- this._physicalTop -= this._physicalSizes[movingUp.pop()];
+ var idx = movingUp.pop();
+ this._physicalTop -= this._getPhysicalSizeIncrement(idx);
}
}
// update the position of the items
@@ -2962,27 +3037,37 @@ function quoteString(str) {
/**
* Increases the pool of physical items only if needed.
- * This function will allocate additional physical items
- * if the physical size is shorter than `_optPhysicalSize`
+ *
+ * @return {boolean} True if the pool was increased.
*/
_increasePoolIfNeeded: function() {
- if (this._viewportSize === 0 || this._physicalSize >= this._optPhysicalSize) {
+ // Base case 1: the list has no height.
+ if (this._viewportHeight === 0) {
+ return false;
+ }
+ // Base case 2: If the physical size is optimal and the list's client height is full
+ // with physical items, don't increase the pool.
+ var isClientHeightFull = this._physicalBottom >= this._scrollBottom && this._physicalTop <= this._scrollPosition;
+ if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) {
return false;
}
- // 0 <= `currentPage` <= `_maxPages`
- var currentPage = Math.floor(this._physicalSize / this._viewportSize);
+ // this value should range between [0 <= `currentPage` <= `_maxPages`]
+ var currentPage = Math.floor(this._physicalSize / this._viewportHeight);
+
if (currentPage === 0) {
// fill the first page
this._debounceTemplate(this._increasePool.bind(this, Math.round(this._physicalCount * 0.5)));
- } else if (this._lastPage !== currentPage) {
+ } else if (this._lastPage !== currentPage && isClientHeightFull) {
// paint the page and defer the next increase
// wait 16ms which is rough enough to get paint cycle.
- Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increasePool.bind(this, 1), 16));
+ Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increasePool.bind(this, this._itemsPerRow), 16));
} else {
// fill the rest of the pages
- this._debounceTemplate(this._increasePool.bind(this, 1));
+ this._debounceTemplate(this._increasePool.bind(this, this._itemsPerRow));
}
+
this._lastPage = currentPage;
+
return true;
},
@@ -2993,7 +3078,7 @@ function quoteString(str) {
var nextPhysicalCount = Math.min(
this._physicalCount + missingItems,
this._virtualCount - this._virtualStart,
- MAX_PHYSICAL_COUNT
+ Math.max(this.maxPhysicalCount, DEFAULT_PHYSICAL_COUNT)
);
var prevPhysicalCount = this._physicalCount;
var delta = nextPhysicalCount - prevPhysicalCount;
@@ -3028,7 +3113,6 @@ function quoteString(str) {
if (this.isAttached && !this._itemsRendered && this._isVisible && requiresUpdate) {
this._lastPage = 0;
this._update();
- this._scrollHandler();
this._itemsRendered = true;
}
},
@@ -3123,7 +3207,7 @@ function quoteString(str) {
if (!el) {
return;
}
-
+
inst = el._templateInstance;
if (inst.__key__ !== key) {
@@ -3219,11 +3303,7 @@ function quoteString(str) {
if (arguments.length === 2 && itemSet) {
for (i = 0; i < itemSet.length; i++) {
pidx = itemSet[i];
- if (pidx >= this._physicalStart) {
- vidx = this._virtualStart + (pidx - this._physicalStart);
- } else {
- vidx = this._virtualStart + (this._physicalCount - this._physicalStart) + pidx;
- }
+ vidx = this._computeVidx(pidx);
if ((rtn = fn.call(this, pidx, vidx)) != null) {
return rtn;
}
@@ -3246,6 +3326,19 @@ function quoteString(str) {
},
/**
+ * Returns the virtual index for a given physical index
+ *
+ * @param {number} pidx Physical index
+ * @return {number}
+ */
+ _computeVidx: function(pidx) {
+ if (pidx >= this._physicalStart) {
+ return this._virtualStart + (pidx - this._physicalStart);
+ }
+ return this._virtualStart + (this._physicalCount - this._physicalStart) + pidx;
+ },
+
+ /**
* Assigns the data models to a given set of items.
* @param {!Array<number>=} itemSet
*/
@@ -3294,8 +3387,13 @@ function quoteString(str) {
}, itemSet);
- this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSize;
- this._viewportSize = this._scrollTargetHeight;
+ this._viewportHeight = this._scrollTargetHeight;
+ if (this.grid) {
+ this._updateGridMetrics();
+ this._physicalSize = Math.ceil(this._physicalCount / this._itemsPerRow) * this._rowHeight;
+ } else {
+ this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSize;
+ }
// update the average if we measured something
if (this._physicalAverageCount !== prevAvgCount) {
@@ -3305,6 +3403,16 @@ function quoteString(str) {
}
},
+ _updateGridMetrics: function() {
+ this._viewportWidth = this._scrollTargetWidth;
+ // Set item width to the value of the _physicalItems offsetWidth
+ this._itemWidth = this._physicalCount > 0 ? this._physicalItems[0].offsetWidth : DEFAULT_GRID_SIZE;
+ // Set row height to the value of the _physicalItems offsetHeight
+ this._rowHeight = this._physicalCount > 0 ? this._physicalItems[0].offsetHeight : DEFAULT_GRID_SIZE;
+ // If in grid mode compute how many items with exist in each row
+ this._itemsPerRow = this._itemWidth ? Math.floor(this._viewportWidth / this._itemWidth) : this._itemsPerRow;
+ },
+
/**
* Updates the position of the physical items.
*/
@@ -3313,10 +3421,52 @@ function quoteString(str) {
var y = this._physicalTop;
- this._iterateItems(function(pidx) {
- this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]);
- y += this._physicalSizes[pidx];
- });
+ if (this.grid) {
+ var totalItemWidth = this._itemsPerRow * this._itemWidth;
+ var rowOffset = (this._viewportWidth - totalItemWidth) / 2;
+
+ this._iterateItems(function(pidx, vidx) {
+
+ var modulus = vidx % this._itemsPerRow;
+ var x = Math.floor((modulus * this._itemWidth) + rowOffset);
+
+ this.translate3d(x + 'px', y + 'px', 0, this._physicalItems[pidx]);
+
+ if (this._shouldRenderNextRow(vidx)) {
+ y += this._rowHeight;
+ }
+
+ });
+ } else {
+ this._iterateItems(function(pidx, vidx) {
+
+ this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]);
+ y += this._physicalSizes[pidx];
+
+ });
+ }
+ },
+
+ _getPhysicalSizeIncrement: function(pidx) {
+ if (!this.grid) {
+ return this._physicalSizes[pidx];
+ }
+ if (this._computeVidx(pidx) % this._itemsPerRow !== this._itemsPerRow - 1) {
+ return 0;
+ }
+ return this._rowHeight;
+ },
+
+ /**
+ * Returns, based on the current index,
+ * whether or not the next index will need
+ * to be rendered on a new row.
+ *
+ * @param {number} vidx Virtual index
+ * @return {boolean}
+ */
+ _shouldRenderNextRow: function(vidx) {
+ return vidx % this._itemsPerRow === this._itemsPerRow - 1;
},
/**
@@ -3351,11 +3501,16 @@ function quoteString(str) {
* @param {boolean=} forceUpdate If true, updates the height no matter what.
*/
_updateScrollerSize: function(forceUpdate) {
- this._estScrollHeight = (this._physicalBottom +
- Math.max(this._virtualCount - this._physicalCount - this._virtualStart, 0) * this._physicalAverage);
+ if (this.grid) {
+ this._estScrollHeight = this._virtualRowCount * this._rowHeight;
+ } else {
+ this._estScrollHeight = (this._physicalBottom +
+ Math.max(this._virtualCount - this._physicalCount - this._virtualStart, 0) * this._physicalAverage);
+ }
forceUpdate = forceUpdate || this._scrollHeight === 0;
forceUpdate = forceUpdate || this._scrollPosition >= this._estScrollHeight - this._physicalSize;
+ forceUpdate = forceUpdate || this.grid && this.$.items.style.height < this._estScrollHeight;
// amortize height adjustment, so it won't trigger repaints very often
if (forceUpdate || Math.abs(this._estScrollHeight - this._scrollHeight) >= this._optPhysicalSize) {
@@ -3380,7 +3535,7 @@ function quoteString(str) {
idx = Math.min(Math.max(idx, 0), this._virtualCount-1);
// update the virtual start only when needed
if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) {
- this._virtualStart = idx - 1;
+ this._virtualStart = this.grid ? (idx - this._itemsPerRow * 2) : (idx - 1);
}
// manage focus
this._manageFocus();
@@ -3388,8 +3543,10 @@ function quoteString(str) {
this._assignModels();
// measure the new sizes
this._updateMetrics();
+
// estimate new physical offset
- this._physicalTop = this._virtualStart * this._physicalAverage;
+ var estPhysicalTop = Math.floor(this._virtualStart / this._itemsPerRow) * this._physicalAverage;
+ this._physicalTop = estPhysicalTop;
var currentTopItem = this._physicalStart;
var currentVirtualItem = this._virtualStart;
@@ -3397,8 +3554,8 @@ function quoteString(str) {
var hiddenContentSize = this._hiddenContentSize;
// scroll to the item as much as we can
- while (currentVirtualItem < idx && targetOffsetTop < hiddenContentSize) {
- targetOffsetTop = targetOffsetTop + this._physicalSizes[currentTopItem];
+ while (currentVirtualItem < idx && targetOffsetTop <= hiddenContentSize) {
+ targetOffsetTop = targetOffsetTop + this._getPhysicalSizeIncrement(currentTopItem);
currentTopItem = (currentTopItem + 1) % this._physicalCount;
currentVirtualItem++;
}
@@ -3407,7 +3564,7 @@ function quoteString(str) {
// update the position of the items
this._positionItems();
// set the new scroll position
- this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + targetOffsetTop + 1);
+ this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + targetOffsetTop);
// increase the pool of physical items if needed
this._increasePoolIfNeeded();
// clear cached visible index
@@ -3429,17 +3586,21 @@ function quoteString(str) {
*/
_resizeHandler: function() {
// iOS fires the resize event when the address bar slides up
- if (IOS && Math.abs(this._viewportSize - this._scrollTargetHeight) < 100) {
+ if (IOS && Math.abs(this._viewportHeight - this._scrollTargetHeight) < 100) {
return;
}
- this._debounceTemplate(function() {
+ // In Desktop Safari 9.0.3, if the scroll bars are always shown,
+ // changing the scroll position from a resize handler would result in
+ // the scroll position being reset. Waiting 1ms fixes the issue.
+ Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', function() {
+ this.updateViewportBoundaries();
this._render();
+
if (this._itemsRendered && this._physicalItems && this._isVisible) {
this._resetAverage();
- this.updateViewportBoundaries();
this.scrollToIndex(this.firstVisibleIndex);
}
- });
+ }.bind(this), 1));
},
_getModelFromItem: function(item) {
@@ -3750,7 +3911,9 @@ function quoteString(str) {
this._focusPhysicalItem(this._focusedIndex - 1);
},
- _didMoveDown: function() {
+ _didMoveDown: function(e) {
+ // disable scroll when pressing the down key
+ e.detail.keyboardEvent.preventDefault();
this._focusPhysicalItem(this._focusedIndex + 1);
},
@@ -3761,78 +3924,6 @@ function quoteString(str) {
});
})();
-// 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.
-
-/**
- * @fileoverview Assertion support.
- */
-
-/**
- * Verify |condition| is truthy and return |condition| if so.
- * @template T
- * @param {T} condition A condition to check for truthiness. Note that this
- * may be used to test whether a value is defined or not, and we don't want
- * to force a cast to Boolean.
- * @param {string=} opt_message A message to show on failure.
- * @return {T} A non-null |condition|.
- */
-function assert(condition, opt_message) {
- if (!condition) {
- var message = 'Assertion failed';
- if (opt_message)
- message = message + ': ' + opt_message;
- var error = new Error(message);
- var global = function() { return this; }();
- if (global.traceAssertionsForTesting)
- console.warn(error.stack);
- throw error;
- }
- return condition;
-}
-
-/**
- * Call this from places in the code that should never be reached.
- *
- * For example, handling all the values of enum with a switch() like this:
- *
- * function getValueFromEnum(enum) {
- * switch (enum) {
- * case ENUM_FIRST_OF_TWO:
- * return first
- * case ENUM_LAST_OF_TWO:
- * return last;
- * }
- * assertNotReached();
- * return document;
- * }
- *
- * This code should only be hit in the case of serious programmer error or
- * unexpected input.
- *
- * @param {string=} opt_message A message to show when this is hit.
- */
-function assertNotReached(opt_message) {
- assert(false, opt_message || 'Unreachable code hit');
-}
-
-/**
- * @param {*} value The value to check.
- * @param {function(new: T, ...)} type A user-defined constructor.
- * @param {string=} opt_message A message to show when this is hit.
- * @return {T}
- * @template T
- */
-function assertInstanceof(value, type, opt_message) {
- // We don't use assert immediately here so that we avoid constructing an error
- // message if we don't have to.
- if (!(value instanceof type)) {
- assertNotReached(opt_message || 'Value ' + value +
- ' is not a[n] ' + (type.name || typeof type));
- }
- return value;
-};
// 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.
@@ -4492,185 +4583,6 @@ Polymer({
});
/**
- * The `iron-iconset-svg` element allows users to define their own icon sets
- * that contain svg icons. The svg icon elements should be children of the
- * `iron-iconset-svg` element. Multiple icons should be given distinct id's.
- *
- * Using svg elements to create icons has a few advantages over traditional
- * bitmap graphics like jpg or png. Icons that use svg are vector based so
- * they are resolution independent and should look good on any device. They
- * are stylable via css. Icons can be themed, colorized, and even animated.
- *
- * Example:
- *
- * <iron-iconset-svg name="my-svg-icons" size="24">
- * <svg>
- * <defs>
- * <g id="shape">
- * <rect x="12" y="0" width="12" height="24" />
- * <circle cx="12" cy="12" r="12" />
- * </g>
- * </defs>
- * </svg>
- * </iron-iconset-svg>
- *
- * This will automatically register the icon set "my-svg-icons" to the iconset
- * database. To use these icons from within another element, make a
- * `iron-iconset` element and call the `byId` method
- * to retrieve a given iconset. To apply a particular icon inside an
- * element use the `applyIcon` method. For example:
- *
- * iconset.applyIcon(iconNode, 'car');
- *
- * @element iron-iconset-svg
- * @demo demo/index.html
- * @implements {Polymer.Iconset}
- */
- Polymer({
- is: 'iron-iconset-svg',
-
- properties: {
-
- /**
- * The name of the iconset.
- */
- name: {
- type: String,
- observer: '_nameChanged'
- },
-
- /**
- * The size of an individual icon. Note that icons must be square.
- */
- size: {
- type: Number,
- value: 24
- }
-
- },
-
- attached: function() {
- this.style.display = 'none';
- },
-
- /**
- * Construct an array of all icon names in this iconset.
- *
- * @return {!Array} Array of icon names.
- */
- getIconNames: function() {
- this._icons = this._createIconMap();
- return Object.keys(this._icons).map(function(n) {
- return this.name + ':' + n;
- }, this);
- },
-
- /**
- * Applies an icon to the given element.
- *
- * An svg icon is prepended to the element's shadowRoot if it exists,
- * otherwise to the element itself.
- *
- * @method applyIcon
- * @param {Element} element Element to which the icon is applied.
- * @param {string} iconName Name of the icon to apply.
- * @return {?Element} The svg element which renders the icon.
- */
- applyIcon: function(element, iconName) {
- // insert svg element into shadow root, if it exists
- element = element.root || element;
- // Remove old svg element
- this.removeIcon(element);
- // install new svg element
- var svg = this._cloneIcon(iconName);
- if (svg) {
- var pde = Polymer.dom(element);
- pde.insertBefore(svg, pde.childNodes[0]);
- return element._svgIcon = svg;
- }
- return null;
- },
-
- /**
- * Remove an icon from the given element by undoing the changes effected
- * by `applyIcon`.
- *
- * @param {Element} element The element from which the icon is removed.
- */
- removeIcon: function(element) {
- // Remove old svg element
- if (element._svgIcon) {
- Polymer.dom(element).removeChild(element._svgIcon);
- element._svgIcon = null;
- }
- },
-
- /**
- *
- * When name is changed, register iconset metadata
- *
- */
- _nameChanged: function() {
- new Polymer.IronMeta({type: 'iconset', key: this.name, value: this});
- this.async(function() {
- this.fire('iron-iconset-added', this, {node: window});
- });
- },
-
- /**
- * Create a map of child SVG elements by id.
- *
- * @return {!Object} Map of id's to SVG elements.
- */
- _createIconMap: function() {
- // Objects chained to Object.prototype (`{}`) have members. Specifically,
- // on FF there is a `watch` method that confuses the icon map, so we
- // need to use a null-based object here.
- var icons = Object.create(null);
- Polymer.dom(this).querySelectorAll('[id]')
- .forEach(function(icon) {
- icons[icon.id] = icon;
- });
- return icons;
- },
-
- /**
- * Produce installable clone of the SVG element matching `id` in this
- * iconset, or `undefined` if there is no matching element.
- *
- * @return {Element} Returns an installable clone of the SVG element
- * matching `id`.
- */
- _cloneIcon: function(id) {
- // create the icon map on-demand, since the iconset itself has no discrete
- // signal to know when it's children are fully parsed
- this._icons = this._icons || this._createIconMap();
- return this._prepareSvgClone(this._icons[id], this.size);
- },
-
- /**
- * @param {Element} sourceSvg
- * @param {number} size
- * @return {Element}
- */
- _prepareSvgClone: function(sourceSvg, size) {
- if (sourceSvg) {
- var content = sourceSvg.cloneNode(true),
- svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
- viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size;
- svg.setAttribute('viewBox', viewBox);
- svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
- // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136
- // TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root
- svg.style.cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;';
- svg.appendChild(content).removeAttribute('id');
- return svg;
- }
- return null;
- }
-
- });
-/**
* @demo demo/index.html
* @polymerBehavior
*/
@@ -4731,12 +4643,15 @@ Polymer({
if (event.target === this) {
this._setFocused(event.type === 'focus');
- } else if (!this.shadowRoot && !this.isLightDescendant(event.target)) {
- this.fire(event.type, {sourceEvent: event}, {
- node: this,
- bubbles: event.bubbles,
- cancelable: event.cancelable
- });
+ } else if (!this.shadowRoot) {
+ var target = /** @type {Node} */(Polymer.dom(event).localTarget);
+ if (!this.isLightDescendant(target)) {
+ this.fire(event.type, {sourceEvent: event}, {
+ node: this,
+ bubbles: event.bubbles,
+ cancelable: event.cancelable
+ });
+ }
}
},
@@ -4745,7 +4660,7 @@ Polymer({
this.style.pointerEvents = disabled ? 'none' : '';
if (disabled) {
this._oldTabIndex = this.tabIndex;
- this.focused = false;
+ this._setFocused(false);
this.tabIndex = -1;
this.blur();
} else if (this._oldTabIndex !== undefined) {
@@ -6064,6 +5979,185 @@ Polymer({
return secondaryRatio === 0;
}
});
+/**
+ * The `iron-iconset-svg` element allows users to define their own icon sets
+ * that contain svg icons. The svg icon elements should be children of the
+ * `iron-iconset-svg` element. Multiple icons should be given distinct id's.
+ *
+ * Using svg elements to create icons has a few advantages over traditional
+ * bitmap graphics like jpg or png. Icons that use svg are vector based so
+ * they are resolution independent and should look good on any device. They
+ * are stylable via css. Icons can be themed, colorized, and even animated.
+ *
+ * Example:
+ *
+ * <iron-iconset-svg name="my-svg-icons" size="24">
+ * <svg>
+ * <defs>
+ * <g id="shape">
+ * <rect x="12" y="0" width="12" height="24" />
+ * <circle cx="12" cy="12" r="12" />
+ * </g>
+ * </defs>
+ * </svg>
+ * </iron-iconset-svg>
+ *
+ * This will automatically register the icon set "my-svg-icons" to the iconset
+ * database. To use these icons from within another element, make a
+ * `iron-iconset` element and call the `byId` method
+ * to retrieve a given iconset. To apply a particular icon inside an
+ * element use the `applyIcon` method. For example:
+ *
+ * iconset.applyIcon(iconNode, 'car');
+ *
+ * @element iron-iconset-svg
+ * @demo demo/index.html
+ * @implements {Polymer.Iconset}
+ */
+ Polymer({
+ is: 'iron-iconset-svg',
+
+ properties: {
+
+ /**
+ * The name of the iconset.
+ */
+ name: {
+ type: String,
+ observer: '_nameChanged'
+ },
+
+ /**
+ * The size of an individual icon. Note that icons must be square.
+ */
+ size: {
+ type: Number,
+ value: 24
+ }
+
+ },
+
+ attached: function() {
+ this.style.display = 'none';
+ },
+
+ /**
+ * Construct an array of all icon names in this iconset.
+ *
+ * @return {!Array} Array of icon names.
+ */
+ getIconNames: function() {
+ this._icons = this._createIconMap();
+ return Object.keys(this._icons).map(function(n) {
+ return this.name + ':' + n;
+ }, this);
+ },
+
+ /**
+ * Applies an icon to the given element.
+ *
+ * An svg icon is prepended to the element's shadowRoot if it exists,
+ * otherwise to the element itself.
+ *
+ * @method applyIcon
+ * @param {Element} element Element to which the icon is applied.
+ * @param {string} iconName Name of the icon to apply.
+ * @return {?Element} The svg element which renders the icon.
+ */
+ applyIcon: function(element, iconName) {
+ // insert svg element into shadow root, if it exists
+ element = element.root || element;
+ // Remove old svg element
+ this.removeIcon(element);
+ // install new svg element
+ var svg = this._cloneIcon(iconName);
+ if (svg) {
+ var pde = Polymer.dom(element);
+ pde.insertBefore(svg, pde.childNodes[0]);
+ return element._svgIcon = svg;
+ }
+ return null;
+ },
+
+ /**
+ * Remove an icon from the given element by undoing the changes effected
+ * by `applyIcon`.
+ *
+ * @param {Element} element The element from which the icon is removed.
+ */
+ removeIcon: function(element) {
+ // Remove old svg element
+ if (element._svgIcon) {
+ Polymer.dom(element).removeChild(element._svgIcon);
+ element._svgIcon = null;
+ }
+ },
+
+ /**
+ *
+ * When name is changed, register iconset metadata
+ *
+ */
+ _nameChanged: function() {
+ new Polymer.IronMeta({type: 'iconset', key: this.name, value: this});
+ this.async(function() {
+ this.fire('iron-iconset-added', this, {node: window});
+ });
+ },
+
+ /**
+ * Create a map of child SVG elements by id.
+ *
+ * @return {!Object} Map of id's to SVG elements.
+ */
+ _createIconMap: function() {
+ // Objects chained to Object.prototype (`{}`) have members. Specifically,
+ // on FF there is a `watch` method that confuses the icon map, so we
+ // need to use a null-based object here.
+ var icons = Object.create(null);
+ Polymer.dom(this).querySelectorAll('[id]')
+ .forEach(function(icon) {
+ icons[icon.id] = icon;
+ });
+ return icons;
+ },
+
+ /**
+ * Produce installable clone of the SVG element matching `id` in this
+ * iconset, or `undefined` if there is no matching element.
+ *
+ * @return {Element} Returns an installable clone of the SVG element
+ * matching `id`.
+ */
+ _cloneIcon: function(id) {
+ // create the icon map on-demand, since the iconset itself has no discrete
+ // signal to know when it's children are fully parsed
+ this._icons = this._icons || this._createIconMap();
+ return this._prepareSvgClone(this._icons[id], this.size);
+ },
+
+ /**
+ * @param {Element} sourceSvg
+ * @param {number} size
+ * @return {Element}
+ */
+ _prepareSvgClone: function(sourceSvg, size) {
+ if (sourceSvg) {
+ var content = sourceSvg.cloneNode(true),
+ svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
+ viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + size;
+ svg.setAttribute('viewBox', viewBox);
+ svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
+ // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136
+ // TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root
+ svg.style.cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;';
+ svg.appendChild(content).removeAttribute('id');
+ return svg;
+ }
+ return null;
+ }
+
+ });
// 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.
@@ -6103,23 +6197,6 @@ cr.define('downloads', function() {
value: '',
},
- i18n_: {
- readOnly: true,
- type: Object,
- value: function() {
- return {
- cancel: loadTimeData.getString('controlCancel'),
- discard: loadTimeData.getString('dangerDiscard'),
- pause: loadTimeData.getString('controlPause'),
- remove: loadTimeData.getString('controlRemoveFromList'),
- resume: loadTimeData.getString('controlResume'),
- restore: loadTimeData.getString('dangerRestore'),
- retry: loadTimeData.getString('controlRetry'),
- save: loadTimeData.getString('dangerSave'),
- };
- },
- },
-
isActive_: {
computed: 'computeIsActive_(' +
'data.state, data.file_externally_removed)',
@@ -6162,7 +6239,7 @@ cr.define('downloads', function() {
// TODO(dbeam): this gets called way more when I observe data.by_ext_id
// and data.by_ext_name directly. Why?
'observeControlledBy_(controlledBy_)',
- 'observeIsDangerous_(isDangerous_, data.file_path)',
+ 'observeIsDangerous_(isDangerous_, data)',
],
ready: function() {
@@ -6212,9 +6289,9 @@ cr.define('downloads', function() {
case downloads.DangerType.DANGEROUS_URL:
case downloads.DangerType.POTENTIALLY_UNWANTED:
case downloads.DangerType.UNCOMMON_CONTENT:
- return 'remove-circle';
+ return 'downloads:remove-circle';
default:
- return 'warning';
+ return 'cr:warning';
}
},
@@ -6329,7 +6406,13 @@ cr.define('downloads', function() {
/** @private */
observeIsDangerous_: function() {
- if (this.data && !this.isDangerous_) {
+ if (!this.data)
+ return;
+
+ if (this.isDangerous_) {
+ this.$.url.removeAttribute('href');
+ } else {
+ this.$.url.href = assert(this.data.url);
var filePath = encodeURIComponent(this.data.file_path);
var scaleFactor = '?scale=' + window.devicePixelRatio + 'x';
this.$['file-icon'].src = 'chrome://fileicon/' + filePath + scaleFactor;
@@ -6557,8 +6640,14 @@ Polymer({
properties: {
/**
- * If you want to use the attribute value of an element for `selected` instead of the index,
- * set this to the name of the attribute.
+ * If you want to use an attribute value or property of an element for
+ * `selected` instead of the index, set this to the name of the attribute
+ * or property. Hyphenated values are converted to camel case when used to
+ * look up the property of a selectable element. Camel cased values are
+ * *not* converted to hyphenated values for attribute lookup. It's
+ * recommended that you provide the hyphenated form of the name so that
+ * selection works in both cases. (Use `attr-or-property-name` instead of
+ * `attrOrPropertyName`.)
*/
attrForSelected: {
type: String,
@@ -6619,6 +6708,15 @@ Polymer({
},
/**
+ * Default fallback if the selection based on selected with `attrForSelected`
+ * is not found.
+ */
+ fallbackSelection: {
+ type: String,
+ value: null
+ },
+
+ /**
* The list of items from which a selection can be made.
*/
items: {
@@ -6648,7 +6746,8 @@ Polymer({
observers: [
'_updateAttrForSelected(attrForSelected)',
- '_updateSelected(selected)'
+ '_updateSelected(selected)',
+ '_checkFallback(fallbackSelection)'
],
created: function() {
@@ -6715,6 +6814,15 @@ Polymer({
},
/**
+ * Selects the item at the given index.
+ *
+ * @method selectIndex
+ */
+ selectIndex: function(index) {
+ this.select(this._indexToValue(index));
+ },
+
+ /**
* Force a synchronous update of the `items` property.
*
* NOTE: Consider listening for the `iron-items-changed` event to respond to
@@ -6734,6 +6842,12 @@ Polymer({
return this.selected != null;
},
+ _checkFallback: function() {
+ if (this._shouldUpdateSelection) {
+ this._updateSelected();
+ }
+ },
+
_addListener: function(eventName) {
this.listen(this, eventName, '_activateHandler');
},
@@ -6755,7 +6869,7 @@ Polymer({
_updateAttrForSelected: function() {
if (this._shouldUpdateSelection) {
- this.selected = this._indexToValue(this.indexOf(this.selectedItem));
+ this.selected = this._indexToValue(this.indexOf(this.selectedItem));
}
},
@@ -6765,6 +6879,11 @@ Polymer({
_selectSelected: function(selected) {
this._selection.select(this._valueToItem(this.selected));
+ // Check for items, since this array is populated only when attached
+ // Since Number(0) is falsy, explicitly check for undefined
+ if (this.fallbackSelection && this.items.length && (this._selection.get() === undefined)) {
+ this.selected = this.fallbackSelection;
+ }
},
_filterItem: function(node) {
@@ -6799,7 +6918,7 @@ Polymer({
},
_valueForItem: function(item) {
- var propValue = item[this.attrForSelected];
+ var propValue = item[Polymer.CaseMap.dashToCamelCase(this.attrForSelected)];
return propValue != undefined ? propValue : item.getAttribute(this.attrForSelected);
},
@@ -6892,7 +7011,7 @@ Polymer({
},
observers: [
- '_updateSelected(selectedValues)'
+ '_updateSelected(selectedValues.splices)'
],
/**
@@ -6928,7 +7047,7 @@ Polymer({
Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this);
} else if (this._shouldUpdateSelection) {
this.selectedValues = this.selectedItems.map(function(selectedItem) {
- return this._indexToValue(this.indexOf(selectedItem));
+ return this._indexToValue(this.indexOf(selectedItem));
}, this).filter(function(unfilteredValue) {
return unfilteredValue != null;
}, this);
@@ -6952,6 +7071,13 @@ Polymer({
for (var i = 0; i < selectedItems.length; i++) {
this._selection.setItemSelected(selectedItems[i], true);
}
+ // Check for items, since this array is populated only when attached
+ if (this.fallbackSelection && this.items.length && !this._selection.get().length) {
+ var fallback = this._valueToItem(this.fallbackSelection);
+ if (fallback) {
+ this.selectedValues = [this.fallbackSelection];
+ }
+ }
} else {
this._selection.clear();
}
@@ -6975,7 +7101,6 @@ Polymer({
} else {
this.splice('selectedValues',i,1);
}
- this._selection.setItemSelected(this._valueToItem(value), unselected);
},
_valuesToItems: function(values) {
@@ -7053,6 +7178,8 @@ Polymer({
* @param {string|number} value the value to select.
*/
select: function(value) {
+ // Cancel automatically focusing a default item if the menu received focus
+ // through a user action selecting a particular item.
if (this._defaultFocusAsync) {
this.cancelAsync(this._defaultFocusAsync);
this._defaultFocusAsync = null;
@@ -7102,7 +7229,8 @@ Polymer({
var attr = this.attrForItemTitle || 'textContent';
var title = item[attr] || item.getAttribute(attr);
- if (title && title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.keyCode).toLowerCase()) {
+ if (!item.hasAttribute('disabled') && title &&
+ title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.keyCode).toLowerCase()) {
this._setFocusedItem(item);
break;
}
@@ -7111,21 +7239,34 @@ Polymer({
/**
* Focuses the previous item (relative to the currently focused item) in the
- * menu.
+ * menu, disabled items will be skipped.
*/
_focusPrevious: function() {
var length = this.items.length;
- var index = (Number(this.indexOf(this.focusedItem)) - 1 + length) % length;
- this._setFocusedItem(this.items[index]);
+ var curFocusIndex = Number(this.indexOf(this.focusedItem));
+ for (var i = 1; i < length; i++) {
+ var item = this.items[(curFocusIndex - i + length) % length];
+ if (!item.hasAttribute('disabled')) {
+ this._setFocusedItem(item);
+ return;
+ }
+ }
},
/**
* Focuses the next item (relative to the currently focused item) in the
- * menu.
+ * menu, disabled items will be skipped.
*/
_focusNext: function() {
- var index = (Number(this.indexOf(this.focusedItem)) + 1) % this.items.length;
- this._setFocusedItem(this.items[index]);
+ var length = this.items.length;
+ var curFocusIndex = Number(this.indexOf(this.focusedItem));
+ for (var i = 1; i < length; i++) {
+ var item = this.items[(curFocusIndex + i) % length];
+ if (!item.hasAttribute('disabled')) {
+ this._setFocusedItem(item);
+ return;
+ }
+ }
},
/**
@@ -7223,8 +7364,6 @@ Polymer({
return;
}
- this.blur();
-
// clear the cached focus item
this._defaultFocusAsync = this.async(function() {
// focus the selected item when the menu receives focus, or the first item
@@ -7235,11 +7374,11 @@ Polymer({
if (selectedItem) {
this._setFocusedItem(selectedItem);
- } else {
- this._setFocusedItem(this.items[0]);
+ } else if (this.items[0]) {
+ // We find the first none-disabled item (if one exists)
+ this._focusNext();
}
- // async 1ms to wait for `select` to get called from `_itemActivate`
- }, 1);
+ });
},
/**
@@ -7311,7 +7450,7 @@ Polymer({
});
})();
/**
-Polymer.IronFitBehavior fits an element in another element using `max-height` and `max-width`, and
+`Polymer.IronFitBehavior` fits an element in another element using `max-height` and `max-width`, and
optionally centers it in the window or another element.
The element will only be sized and/or positioned if it has not already been sized and/or positioned
@@ -7322,8 +7461,25 @@ CSS properties | Action
`position` set | Element is not centered horizontally or vertically
`top` or `bottom` set | Element is not vertically centered
`left` or `right` set | Element is not horizontally centered
-`max-height` or `height` set | Element respects `max-height` or `height`
-`max-width` or `width` set | Element respects `max-width` or `width`
+`max-height` set | Element respects `max-height`
+`max-width` set | Element respects `max-width`
+
+`Polymer.IronFitBehavior` can position an element into another element using
+`verticalAlign` and `horizontalAlign`. This will override the element's css position.
+
+ <div class="container">
+ <iron-fit-impl vertical-align="top" horizontal-align="auto">
+ Positioned into the container
+ </iron-fit-impl>
+ </div>
+
+Use `noOverlap` to position the element around another element without overlapping it.
+
+ <div class="container">
+ <iron-fit-impl no-overlap vertical-align="auto" horizontal-align="auto">
+ Positioned around the container
+ </iron-fit-impl>
+ </div>
@demo demo/index.html
@polymerBehavior
@@ -7355,6 +7511,66 @@ CSS properties | Action
},
/**
+ * Will position the element around the positionTarget without overlapping it.
+ */
+ noOverlap: {
+ type: Boolean
+ },
+
+ /**
+ * The element that should be used to position the element. If not set, it will
+ * default to the parent node.
+ * @type {!Element}
+ */
+ positionTarget: {
+ type: Element
+ },
+
+ /**
+ * The orientation against which to align the element horizontally
+ * relative to the `positionTarget`. Possible values are "left", "right", "auto".
+ */
+ horizontalAlign: {
+ type: String
+ },
+
+ /**
+ * The orientation against which to align the element vertically
+ * relative to the `positionTarget`. Possible values are "top", "bottom", "auto".
+ */
+ verticalAlign: {
+ type: String
+ },
+
+ /**
+ * If true, it will use `horizontalAlign` and `verticalAlign` values as preferred alignment
+ * and if there's not enough space, it will pick the values which minimize the cropping.
+ */
+ dynamicAlign: {
+ type: Boolean
+ },
+
+ /**
+ * The same as setting margin-left and margin-right css properties.
+ * @deprecated
+ */
+ horizontalOffset: {
+ type: Number,
+ value: 0,
+ notify: true
+ },
+
+ /**
+ * The same as setting margin-top and margin-bottom css properties.
+ * @deprecated
+ */
+ verticalOffset: {
+ type: Number,
+ value: 0,
+ notify: true
+ },
+
+ /**
* Set to true to auto-fit on attach.
*/
autoFitOnAttach: {
@@ -7366,7 +7582,6 @@ CSS properties | Action
_fitInfo: {
type: Object
}
-
},
get _fitWidth() {
@@ -7409,7 +7624,40 @@ CSS properties | Action
return fitTop;
},
+ /**
+ * The element that should be used to position the element,
+ * if no position target is configured.
+ */
+ get _defaultPositionTarget() {
+ var parent = Polymer.dom(this).parentNode;
+
+ if (parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
+ parent = parent.host;
+ }
+
+ return parent;
+ },
+
+ /**
+ * The horizontal align value, accounting for the RTL/LTR text direction.
+ */
+ get _localeHorizontalAlign() {
+ if (this._isRTL) {
+ // In RTL, "left" becomes "right".
+ if (this.horizontalAlign === 'right') {
+ return 'left';
+ }
+ if (this.horizontalAlign === 'left') {
+ return 'right';
+ }
+ }
+ return this.horizontalAlign;
+ },
+
attached: function() {
+ // Memoize this to avoid expensive calculations & relayouts.
+ this._isRTL = window.getComputedStyle(this).direction == 'rtl';
+ this.positionTarget = this.positionTarget || this._defaultPositionTarget;
if (this.autoFitOnAttach) {
if (window.getComputedStyle(this).display === 'none') {
setTimeout(function() {
@@ -7422,10 +7670,11 @@ CSS properties | Action
},
/**
- * Fits and optionally centers the element into the window, or `fitInfo` if specified.
+ * Positions and fits the element into the `fitInto` element.
*/
fit: function() {
this._discoverInfo();
+ this.position();
this.constrain();
this.center();
},
@@ -7439,21 +7688,29 @@ CSS properties | Action
}
var target = window.getComputedStyle(this);
var sizer = window.getComputedStyle(this.sizingTarget);
+
this._fitInfo = {
inlineStyle: {
top: this.style.top || '',
- left: this.style.left || ''
+ left: this.style.left || '',
+ position: this.style.position || ''
+ },
+ sizerInlineStyle: {
+ maxWidth: this.sizingTarget.style.maxWidth || '',
+ maxHeight: this.sizingTarget.style.maxHeight || '',
+ boxSizing: this.sizingTarget.style.boxSizing || ''
},
positionedBy: {
vertically: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ?
'bottom' : null),
horizontally: target.left !== 'auto' ? 'left' : (target.right !== 'auto' ?
- 'right' : null),
- css: target.position
+ 'right' : null)
},
sizedBy: {
height: sizer.maxHeight !== 'none',
- width: sizer.maxWidth !== 'none'
+ width: sizer.maxWidth !== 'none',
+ minWidth: parseInt(sizer.minWidth, 10) || 0,
+ minHeight: parseInt(sizer.minHeight, 10) || 0
},
margin: {
top: parseInt(target.marginTop, 10) || 0,
@@ -7462,6 +7719,20 @@ CSS properties | Action
left: parseInt(target.marginLeft, 10) || 0
}
};
+
+ // Support these properties until they are removed.
+ if (this.verticalOffset) {
+ this._fitInfo.margin.top = this._fitInfo.margin.bottom = this.verticalOffset;
+ this._fitInfo.inlineStyle.marginTop = this.style.marginTop || '';
+ this._fitInfo.inlineStyle.marginBottom = this.style.marginBottom || '';
+ this.style.marginTop = this.style.marginBottom = this.verticalOffset + 'px';
+ }
+ if (this.horizontalOffset) {
+ this._fitInfo.margin.left = this._fitInfo.margin.right = this.horizontalOffset;
+ this._fitInfo.inlineStyle.marginLeft = this.style.marginLeft || '';
+ this._fitInfo.inlineStyle.marginRight = this.style.marginRight || '';
+ this.style.marginLeft = this.style.marginRight = this.horizontalOffset + 'px';
+ }
},
/**
@@ -7469,23 +7740,21 @@ CSS properties | Action
* the memoized data.
*/
resetFit: function() {
- if (!this._fitInfo || !this._fitInfo.sizedBy.width) {
- this.sizingTarget.style.maxWidth = '';
+ var info = this._fitInfo || {};
+ for (var property in info.sizerInlineStyle) {
+ this.sizingTarget.style[property] = info.sizerInlineStyle[property];
}
- if (!this._fitInfo || !this._fitInfo.sizedBy.height) {
- this.sizingTarget.style.maxHeight = '';
- }
- this.style.top = this._fitInfo ? this._fitInfo.inlineStyle.top : '';
- this.style.left = this._fitInfo ? this._fitInfo.inlineStyle.left : '';
- if (this._fitInfo) {
- this.style.position = this._fitInfo.positionedBy.css;
+ for (var property in info.inlineStyle) {
+ this.style[property] = info.inlineStyle[property];
}
+
this._fitInfo = null;
},
/**
- * Equivalent to calling `resetFit()` and `fit()`. Useful to call this after the element,
- * the window, or the `fitInfo` element has been resized.
+ * Equivalent to calling `resetFit()` and `fit()`. Useful to call this after
+ * the element or the `fitInto` element has been resized, or if any of the
+ * positioning properties (e.g. `horizontalAlign, verticalAlign`) is updated.
*/
refit: function() {
this.resetFit();
@@ -7493,37 +7762,111 @@ CSS properties | Action
},
/**
- * Constrains the size of the element to the window or `fitInfo` by setting `max-height`
+ * Positions the element according to `horizontalAlign, verticalAlign`.
+ */
+ position: function() {
+ if (!this.horizontalAlign && !this.verticalAlign) {
+ // needs to be centered, and it is done after constrain.
+ return;
+ }
+
+ this.style.position = 'fixed';
+ // Need border-box for margin/padding.
+ this.sizingTarget.style.boxSizing = 'border-box';
+ // Set to 0, 0 in order to discover any offset caused by parent stacking contexts.
+ this.style.left = '0px';
+ this.style.top = '0px';
+
+ var rect = this.getBoundingClientRect();
+ var positionRect = this.__getNormalizedRect(this.positionTarget);
+ var fitRect = this.__getNormalizedRect(this.fitInto);
+
+ var margin = this._fitInfo.margin;
+
+ // Consider the margin as part of the size for position calculations.
+ var size = {
+ width: rect.width + margin.left + margin.right,
+ height: rect.height + margin.top + margin.bottom
+ };
+
+ var position = this.__getPosition(this._localeHorizontalAlign, this.verticalAlign, size, positionRect, fitRect);
+
+ var left = position.left + margin.left;
+ var top = position.top + margin.top;
+
+ // Use original size (without margin).
+ var right = Math.min(fitRect.right - margin.right, left + rect.width);
+ var bottom = Math.min(fitRect.bottom - margin.bottom, top + rect.height);
+
+ var minWidth = this._fitInfo.sizedBy.minWidth;
+ var minHeight = this._fitInfo.sizedBy.minHeight;
+ if (left < margin.left) {
+ left = margin.left;
+ if (right - left < minWidth) {
+ left = right - minWidth;
+ }
+ }
+ if (top < margin.top) {
+ top = margin.top;
+ if (bottom - top < minHeight) {
+ top = bottom - minHeight;
+ }
+ }
+
+ this.sizingTarget.style.maxWidth = (right - left) + 'px';
+ this.sizingTarget.style.maxHeight = (bottom - top) + 'px';
+
+ // Remove the offset caused by any stacking context.
+ this.style.left = (left - rect.left) + 'px';
+ this.style.top = (top - rect.top) + 'px';
+ },
+
+ /**
+ * Constrains the size of the element to `fitInto` by setting `max-height`
* and/or `max-width`.
*/
constrain: function() {
+ if (this.horizontalAlign || this.verticalAlign) {
+ return;
+ }
var info = this._fitInfo;
// position at (0px, 0px) if not already positioned, so we can measure the natural size.
- if (!this._fitInfo.positionedBy.vertically) {
+ if (!info.positionedBy.vertically) {
+ this.style.position = 'fixed';
this.style.top = '0px';
}
- if (!this._fitInfo.positionedBy.horizontally) {
- this.style.left = '0px';
- }
- if (!this._fitInfo.positionedBy.vertically || !this._fitInfo.positionedBy.horizontally) {
- // need position:fixed to properly size the element
+ if (!info.positionedBy.horizontally) {
this.style.position = 'fixed';
+ this.style.left = '0px';
}
+
// need border-box for margin/padding
this.sizingTarget.style.boxSizing = 'border-box';
// constrain the width and height if not already set
var rect = this.getBoundingClientRect();
if (!info.sizedBy.height) {
- this._sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
+ this.__sizeDimension(rect, info.positionedBy.vertically, 'top', 'bottom', 'Height');
}
if (!info.sizedBy.width) {
- this._sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right', 'Width');
+ this.__sizeDimension(rect, info.positionedBy.horizontally, 'left', 'right', 'Width');
}
},
+ /**
+ * @protected
+ * @deprecated
+ */
_sizeDimension: function(rect, positionedBy, start, end, extent) {
+ this.__sizeDimension(rect, positionedBy, start, end, extent);
+ },
+
+ /**
+ * @private
+ */
+ __sizeDimension: function(rect, positionedBy, start, end, extent) {
var info = this._fitInfo;
- var max = extent === 'Width' ? this._fitWidth : this._fitHeight;
+ var fitRect = this.__getNormalizedRect(this.fitInto);
+ var max = extent === 'Width' ? fitRect.width : fitRect.height;
var flip = (positionedBy === end);
var offset = flip ? max - rect[end] : rect[start];
var margin = info.margin[flip ? start : end];
@@ -7537,6 +7880,9 @@ CSS properties | Action
* `position:fixed`.
*/
center: function() {
+ if (this.horizontalAlign || this.verticalAlign) {
+ return;
+ }
var positionedBy = this._fitInfo.positionedBy;
if (positionedBy.vertically && positionedBy.horizontally) {
// Already positioned.
@@ -7555,300 +7901,620 @@ CSS properties | Action
}
// It will take in consideration margins and transforms
var rect = this.getBoundingClientRect();
+ var fitRect = this.__getNormalizedRect(this.fitInto);
if (!positionedBy.vertically) {
- var top = this._fitTop - rect.top + (this._fitHeight - rect.height) / 2;
+ var top = fitRect.top - rect.top + (fitRect.height - rect.height) / 2;
this.style.top = top + 'px';
}
if (!positionedBy.horizontally) {
- var left = this._fitLeft - rect.left + (this._fitWidth - rect.width) / 2;
+ var left = fitRect.left - rect.left + (fitRect.width - rect.width) / 2;
this.style.left = left + 'px';
}
+ },
+
+ __getNormalizedRect: function(target) {
+ if (target === document.documentElement || target === window) {
+ return {
+ top: 0,
+ left: 0,
+ width: window.innerWidth,
+ height: window.innerHeight,
+ right: window.innerWidth,
+ bottom: window.innerHeight
+ };
+ }
+ return target.getBoundingClientRect();
+ },
+
+ __getCroppedArea: function(position, size, fitRect) {
+ var verticalCrop = Math.min(0, position.top) + Math.min(0, fitRect.bottom - (position.top + size.height));
+ var horizontalCrop = Math.min(0, position.left) + Math.min(0, fitRect.right - (position.left + size.width));
+ return Math.abs(verticalCrop) * size.width + Math.abs(horizontalCrop) * size.height;
+ },
+
+
+ __getPosition: function(hAlign, vAlign, size, positionRect, fitRect) {
+ // All the possible configurations.
+ // Ordered as top-left, top-right, bottom-left, bottom-right.
+ var positions = [{
+ verticalAlign: 'top',
+ horizontalAlign: 'left',
+ top: positionRect.top,
+ left: positionRect.left
+ }, {
+ verticalAlign: 'top',
+ horizontalAlign: 'right',
+ top: positionRect.top,
+ left: positionRect.right - size.width
+ }, {
+ verticalAlign: 'bottom',
+ horizontalAlign: 'left',
+ top: positionRect.bottom - size.height,
+ left: positionRect.left
+ }, {
+ verticalAlign: 'bottom',
+ horizontalAlign: 'right',
+ top: positionRect.bottom - size.height,
+ left: positionRect.right - size.width
+ }];
+
+ if (this.noOverlap) {
+ // Duplicate.
+ for (var i = 0, l = positions.length; i < l; i++) {
+ var copy = {};
+ for (var key in positions[i]) {
+ copy[key] = positions[i][key];
+ }
+ positions.push(copy);
+ }
+ // Horizontal overlap only.
+ positions[0].top = positions[1].top += positionRect.height;
+ positions[2].top = positions[3].top -= positionRect.height;
+ // Vertical overlap only.
+ positions[4].left = positions[6].left += positionRect.width;
+ positions[5].left = positions[7].left -= positionRect.width;
+ }
+
+ // Consider auto as null for coding convenience.
+ vAlign = vAlign === 'auto' ? null : vAlign;
+ hAlign = hAlign === 'auto' ? null : hAlign;
+
+ var position;
+ for (var i = 0; i < positions.length; i++) {
+ var pos = positions[i];
+ // Align is ok if:
+ // - Horizontal AND vertical are required and match, or
+ // - Only vertical is required and matches, or
+ // - Only horizontal is required and matches.
+ var alignOk = (pos.verticalAlign === vAlign && pos.horizontalAlign === hAlign) ||
+ (pos.verticalAlign === vAlign && !hAlign) ||
+ (pos.horizontalAlign === hAlign && !vAlign);
+
+ // If both vAlign and hAlign are defined, return exact match.
+ // For dynamicAlign and noOverlap we'll have more than one candidate, so
+ // we'll have to check the croppedArea to make the best choice.
+ if (!this.dynamicAlign && !this.noOverlap && vAlign && hAlign && alignOk) {
+ position = pos;
+ break;
+ }
+
+ // Filter out elements that don't match the alignment (if defined).
+ // With dynamicAlign, we need to consider all the positions to find the
+ // one that minimizes the cropped area.
+ if (!this.dynamicAlign && (vAlign || hAlign) && !alignOk) {
+ continue;
+ }
+
+ position = position || pos;
+ pos.croppedArea = this.__getCroppedArea(pos, size, fitRect);
+ var diff = pos.croppedArea - position.croppedArea;
+ // Check which crops less. If it crops equally,
+ // check for alignment preferences.
+ if (diff < 0 || (diff === 0 && alignOk)) {
+ position = pos;
+ }
+ }
+
+ return position;
}
};
+(function() {
+'use strict';
+
+ Polymer({
+
+ is: 'iron-overlay-backdrop',
+
+ properties: {
+
+ /**
+ * Returns true if the backdrop is opened.
+ */
+ opened: {
+ reflectToAttribute: true,
+ type: Boolean,
+ value: false,
+ observer: '_openedChanged'
+ }
+
+ },
+
+ listeners: {
+ 'transitionend': '_onTransitionend'
+ },
+
+ created: function() {
+ // Used to cancel previous requestAnimationFrame calls when opened changes.
+ this.__openedRaf = null;
+ },
+
+ attached: function() {
+ this.opened && this._openedChanged(this.opened);
+ },
+
+ /**
+ * Appends the backdrop to document body if needed.
+ */
+ prepare: function() {
+ if (this.opened && !this.parentNode) {
+ Polymer.dom(document.body).appendChild(this);
+ }
+ },
+
+ /**
+ * Shows the backdrop.
+ */
+ open: function() {
+ this.opened = true;
+ },
+
+ /**
+ * Hides the backdrop.
+ */
+ close: function() {
+ this.opened = false;
+ },
+
+ /**
+ * Removes the backdrop from document body if needed.
+ */
+ complete: function() {
+ if (!this.opened && this.parentNode === document.body) {
+ Polymer.dom(this.parentNode).removeChild(this);
+ }
+ },
+
+ _onTransitionend: function(event) {
+ if (event && event.target === this) {
+ this.complete();
+ }
+ },
+
+ /**
+ * @param {boolean} opened
+ * @private
+ */
+ _openedChanged: function(opened) {
+ if (opened) {
+ // Auto-attach.
+ this.prepare();
+ } else {
+ // Animation might be disabled via the mixin or opacity custom property.
+ // If it is disabled in other ways, it's up to the user to call complete.
+ var cs = window.getComputedStyle(this);
+ if (cs.transitionDuration === '0s' || cs.opacity == 0) {
+ this.complete();
+ }
+ }
+
+ if (!this.isAttached) {
+ return;
+ }
+
+ // Always cancel previous requestAnimationFrame.
+ if (this.__openedRaf) {
+ window.cancelAnimationFrame(this.__openedRaf);
+ this.__openedRaf = null;
+ }
+ // Force relayout to ensure proper transitions.
+ this.scrollTop = this.scrollTop;
+ this.__openedRaf = window.requestAnimationFrame(function() {
+ this.__openedRaf = null;
+ this.toggleClass('opened', this.opened);
+ }.bind(this));
+ }
+ });
+
+})();
/**
* @struct
* @constructor
+ * @private
*/
Polymer.IronOverlayManagerClass = function() {
+ /**
+ * Used to keep track of the opened overlays.
+ * @private {Array<Element>}
+ */
this._overlays = [];
- // Used to keep track of the last focused node before an overlay gets opened.
- this._lastFocusedNodes = [];
/**
- * iframes have a default z-index of 100, so this default should be at least
- * that.
+ * iframes have a default z-index of 100,
+ * so this default should be at least that.
* @private {number}
*/
this._minimumZ = 101;
- this._backdrops = [];
-
+ /**
+ * Memoized backdrop element.
+ * @private {Element|null}
+ */
this._backdropElement = null;
- Object.defineProperty(this, 'backdropElement', {
- get: function() {
- if (!this._backdropElement) {
- this._backdropElement = document.createElement('iron-overlay-backdrop');
- }
- return this._backdropElement;
- }.bind(this)
- });
- /**
- * The deepest active element.
- * returns {?Node} element the active element
- */
- this.deepActiveElement = null;
- Object.defineProperty(this, 'deepActiveElement', {
- get: function() {
- var active = document.activeElement;
- // document.activeElement can be null
- // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
- while (active && active.root && Polymer.dom(active.root).activeElement) {
- active = Polymer.dom(active.root).activeElement;
- }
- return active;
- }.bind(this)
- });
+ // Listen to mousedown or touchstart to be sure to be the first to capture
+ // clicks outside the overlay.
+ var clickEvent = ('ontouchstart' in window) ? 'touchstart' : 'mousedown';
+ document.addEventListener(clickEvent, this._onCaptureClick.bind(this), true);
+ document.addEventListener('focus', this._onCaptureFocus.bind(this), true);
+ document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true);
};
- /**
- * If a node is contained in an overlay.
- * @private
- * @param {Node} node
- * @returns {Boolean}
- */
- Polymer.IronOverlayManagerClass.prototype._isChildOfOverlay = function(node) {
- while (node && node !== document.body) {
- // Use logical parentNode, or native ShadowRoot host.
- node = Polymer.dom(node).parentNode || node.host;
- // Check if it is an overlay.
- if (node && node.behaviors && node.behaviors.indexOf(Polymer.IronOverlayBehaviorImpl) !== -1) {
- return true;
+ Polymer.IronOverlayManagerClass.prototype = {
+
+ constructor: Polymer.IronOverlayManagerClass,
+
+ /**
+ * The shared backdrop element.
+ * @type {!Element} backdropElement
+ */
+ get backdropElement() {
+ if (!this._backdropElement) {
+ this._backdropElement = document.createElement('iron-overlay-backdrop');
}
- }
- return false;
- };
+ return this._backdropElement;
+ },
- Polymer.IronOverlayManagerClass.prototype._applyOverlayZ = function(overlay, aboveZ) {
- this._setZ(overlay, aboveZ + 2);
- };
+ /**
+ * The deepest active element.
+ * @type {!Element} activeElement the active element
+ */
+ get deepActiveElement() {
+ // document.activeElement can be null
+ // https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement
+ // In case of null, default it to document.body.
+ var active = document.activeElement || document.body;
+ while (active.root && Polymer.dom(active.root).activeElement) {
+ active = Polymer.dom(active.root).activeElement;
+ }
+ return active;
+ },
- Polymer.IronOverlayManagerClass.prototype._setZ = function(element, z) {
- element.style.zIndex = z;
- };
+ /**
+ * Brings the overlay at the specified index to the front.
+ * @param {number} i
+ * @private
+ */
+ _bringOverlayAtIndexToFront: function(i) {
+ var overlay = this._overlays[i];
+ if (!overlay) {
+ return;
+ }
+ var lastI = this._overlays.length - 1;
+ var currentOverlay = this._overlays[lastI];
+ // Ensure always-on-top overlay stays on top.
+ if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
+ lastI--;
+ }
+ // If already the top element, return.
+ if (i >= lastI) {
+ return;
+ }
+ // Update z-index to be on top.
+ var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
+ if (this._getZ(overlay) <= minimumZ) {
+ this._applyOverlayZ(overlay, minimumZ);
+ }
- /**
- * track overlays for z-index and focus managemant
- */
- Polymer.IronOverlayManagerClass.prototype.addOverlay = function(overlay) {
- var minimumZ = Math.max(this.currentOverlayZ(), this._minimumZ);
- this._overlays.push(overlay);
- var newZ = this.currentOverlayZ();
- if (newZ <= minimumZ) {
- this._applyOverlayZ(overlay, minimumZ);
- }
- var element = this.deepActiveElement;
- // If already in other overlay, don't reset focus there.
- if (this._isChildOfOverlay(element)) {
- element = null;
- }
- this._lastFocusedNodes.push(element);
- };
+ // Shift other overlays behind the new on top.
+ while (i < lastI) {
+ this._overlays[i] = this._overlays[i + 1];
+ i++;
+ }
+ this._overlays[lastI] = overlay;
+ },
- Polymer.IronOverlayManagerClass.prototype.removeOverlay = function(overlay) {
- var i = this._overlays.indexOf(overlay);
- if (i >= 0) {
- this._overlays.splice(i, 1);
- this._setZ(overlay, '');
+ /**
+ * Adds the overlay and updates its z-index if it's opened, or removes it if it's closed.
+ * Also updates the backdrop z-index.
+ * @param {!Element} overlay
+ */
+ addOrRemoveOverlay: function(overlay) {
+ if (overlay.opened) {
+ this.addOverlay(overlay);
+ } else {
+ this.removeOverlay(overlay);
+ }
+ this.trackBackdrop();
+ },
- var node = this._lastFocusedNodes[i];
- // Focus only if still contained in document.body
- if (overlay.restoreFocusOnClose && node && Polymer.dom(document.body).deepContains(node)) {
- node.focus();
+ /**
+ * Tracks overlays for z-index and focus management.
+ * Ensures the last added overlay with always-on-top remains on top.
+ * @param {!Element} overlay
+ */
+ addOverlay: function(overlay) {
+ var i = this._overlays.indexOf(overlay);
+ if (i >= 0) {
+ this._bringOverlayAtIndexToFront(i);
+ return;
}
- this._lastFocusedNodes.splice(i, 1);
- }
- };
+ var insertionIndex = this._overlays.length;
+ var currentOverlay = this._overlays[insertionIndex - 1];
+ var minimumZ = Math.max(this._getZ(currentOverlay), this._minimumZ);
+ var newZ = this._getZ(overlay);
- Polymer.IronOverlayManagerClass.prototype.currentOverlay = function() {
- var i = this._overlays.length - 1;
- while (this._overlays[i] && !this._overlays[i].opened) {
- --i;
- }
- return this._overlays[i];
- };
+ // Ensure always-on-top overlay stays on top.
+ if (currentOverlay && this._shouldBeBehindOverlay(overlay, currentOverlay)) {
+ // This bumps the z-index of +2.
+ this._applyOverlayZ(currentOverlay, minimumZ);
+ insertionIndex--;
+ // Update minimumZ to match previous overlay's z-index.
+ var previousOverlay = this._overlays[insertionIndex - 1];
+ minimumZ = Math.max(this._getZ(previousOverlay), this._minimumZ);
+ }
- Polymer.IronOverlayManagerClass.prototype.currentOverlayZ = function() {
- return this._getOverlayZ(this.currentOverlay());
- };
+ // Update z-index and insert overlay.
+ if (newZ <= minimumZ) {
+ this._applyOverlayZ(overlay, minimumZ);
+ }
+ this._overlays.splice(insertionIndex, 0, overlay);
- /**
- * Ensures that the minimum z-index of new overlays is at least `minimumZ`.
- * This does not effect the z-index of any existing overlays.
- *
- * @param {number} minimumZ
- */
- Polymer.IronOverlayManagerClass.prototype.ensureMinimumZ = function(minimumZ) {
- this._minimumZ = Math.max(this._minimumZ, minimumZ);
- };
+ // Get focused node.
+ var element = this.deepActiveElement;
+ overlay.restoreFocusNode = this._overlayParent(element) ? null : element;
+ },
- Polymer.IronOverlayManagerClass.prototype.focusOverlay = function() {
- var current = this.currentOverlay();
- // We have to be careful to focus the next overlay _after_ any current
- // transitions are complete (due to the state being toggled prior to the
- // transition). Otherwise, we risk infinite recursion when a transitioning
- // (closed) overlay becomes the current overlay.
- //
- // NOTE: We make the assumption that any overlay that completes a transition
- // will call into focusOverlay to kick the process back off. Currently:
- // transitionend -> _applyFocus -> focusOverlay.
- if (current && !current.transitioning) {
- current._applyFocus();
- }
- };
+ /**
+ * @param {!Element} overlay
+ */
+ removeOverlay: function(overlay) {
+ var i = this._overlays.indexOf(overlay);
+ if (i === -1) {
+ return;
+ }
+ this._overlays.splice(i, 1);
- Polymer.IronOverlayManagerClass.prototype.trackBackdrop = function(element) {
- // backdrops contains the overlays with a backdrop that are currently
- // visible
- var index = this._backdrops.indexOf(element);
- if (element.opened && element.withBackdrop) {
- // no duplicates
- if (index === -1) {
- this._backdrops.push(element);
- }
- } else if (index >= 0) {
- this._backdrops.splice(index, 1);
- }
- };
+ var node = overlay.restoreFocusOnClose ? overlay.restoreFocusNode : null;
+ overlay.restoreFocusNode = null;
+ // Focus back only if still contained in document.body
+ if (node && Polymer.dom(document.body).deepContains(node)) {
+ node.focus();
+ }
+ },
- Polymer.IronOverlayManagerClass.prototype.getBackdrops = function() {
- return this._backdrops;
- };
+ /**
+ * Returns the current overlay.
+ * @return {Element|undefined}
+ */
+ currentOverlay: function() {
+ var i = this._overlays.length - 1;
+ return this._overlays[i];
+ },
- /**
- * Returns the z-index for the backdrop.
- */
- Polymer.IronOverlayManagerClass.prototype.backdropZ = function() {
- return this._getOverlayZ(this._overlayWithBackdrop()) - 1;
- };
+ /**
+ * Returns the current overlay z-index.
+ * @return {number}
+ */
+ currentOverlayZ: function() {
+ return this._getZ(this.currentOverlay());
+ },
- /**
- * Returns the first opened overlay that has a backdrop.
- */
- Polymer.IronOverlayManagerClass.prototype._overlayWithBackdrop = function() {
- for (var i = 0; i < this._overlays.length; i++) {
- if (this._overlays[i].opened && this._overlays[i].withBackdrop) {
- return this._overlays[i];
- }
- }
- };
+ /**
+ * Ensures that the minimum z-index of new overlays is at least `minimumZ`.
+ * This does not effect the z-index of any existing overlays.
+ * @param {number} minimumZ
+ */
+ ensureMinimumZ: function(minimumZ) {
+ this._minimumZ = Math.max(this._minimumZ, minimumZ);
+ },
- /**
- * Calculates the minimum z-index for the overlay.
- */
- Polymer.IronOverlayManagerClass.prototype._getOverlayZ = function(overlay) {
- var z = this._minimumZ;
- if (overlay) {
- var z1 = Number(window.getComputedStyle(overlay).zIndex);
- // Check if is a number
- // Number.isNaN not supported in IE 10+
- if (z1 === z1) {
- z = z1;
+ focusOverlay: function() {
+ var current = /** @type {?} */ (this.currentOverlay());
+ // We have to be careful to focus the next overlay _after_ any current
+ // transitions are complete (due to the state being toggled prior to the
+ // transition). Otherwise, we risk infinite recursion when a transitioning
+ // (closed) overlay becomes the current overlay.
+ //
+ // NOTE: We make the assumption that any overlay that completes a transition
+ // will call into focusOverlay to kick the process back off. Currently:
+ // transitionend -> _applyFocus -> focusOverlay.
+ if (current && !current.transitioning) {
+ current._applyFocus();
}
- }
- return z;
- };
-
- Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
-(function() {
+ },
- Polymer({
+ /**
+ * Updates the backdrop z-index.
+ */
+ trackBackdrop: function() {
+ var overlay = this._overlayWithBackdrop();
+ // Avoid creating the backdrop if there is no overlay with backdrop.
+ if (!overlay && !this._backdropElement) {
+ return;
+ }
+ this.backdropElement.style.zIndex = this._getZ(overlay) - 1;
+ this.backdropElement.opened = !!overlay;
+ },
- is: 'iron-overlay-backdrop',
+ /**
+ * @return {Array<Element>}
+ */
+ getBackdrops: function() {
+ var backdrops = [];
+ for (var i = 0; i < this._overlays.length; i++) {
+ if (this._overlays[i].withBackdrop) {
+ backdrops.push(this._overlays[i]);
+ }
+ }
+ return backdrops;
+ },
- properties: {
+ /**
+ * Returns the z-index for the backdrop.
+ * @return {number}
+ */
+ backdropZ: function() {
+ return this._getZ(this._overlayWithBackdrop()) - 1;
+ },
- /**
- * Returns true if the backdrop is opened.
- */
- opened: {
- readOnly: true,
- reflectToAttribute: true,
- type: Boolean,
- value: false
- },
+ /**
+ * Returns the first opened overlay that has a backdrop.
+ * @return {Element|undefined}
+ * @private
+ */
+ _overlayWithBackdrop: function() {
+ for (var i = 0; i < this._overlays.length; i++) {
+ if (this._overlays[i].withBackdrop) {
+ return this._overlays[i];
+ }
+ }
+ },
- _manager: {
- type: Object,
- value: Polymer.IronOverlayManager
+ /**
+ * Calculates the minimum z-index for the overlay.
+ * @param {Element=} overlay
+ * @private
+ */
+ _getZ: function(overlay) {
+ var z = this._minimumZ;
+ if (overlay) {
+ var z1 = Number(overlay.style.zIndex || window.getComputedStyle(overlay).zIndex);
+ // Check if is a number
+ // Number.isNaN not supported in IE 10+
+ if (z1 === z1) {
+ z = z1;
+ }
}
+ return z;
+ },
+ /**
+ * @param {!Element} element
+ * @param {number|string} z
+ * @private
+ */
+ _setZ: function(element, z) {
+ element.style.zIndex = z;
},
- listeners: {
- 'transitionend' : '_onTransitionend'
+ /**
+ * @param {!Element} overlay
+ * @param {number} aboveZ
+ * @private
+ */
+ _applyOverlayZ: function(overlay, aboveZ) {
+ this._setZ(overlay, aboveZ + 2);
},
/**
- * Appends the backdrop to document body and sets its `z-index` to be below the latest overlay.
+ * Returns the overlay containing the provided node. If the node is an overlay,
+ * it returns the node.
+ * @param {Element=} node
+ * @return {Element|undefined}
+ * @private
*/
- prepare: function() {
- // Always update z-index
- this.style.zIndex = this._manager.backdropZ();
- if (!this.parentNode) {
- Polymer.dom(document.body).appendChild(this);
+ _overlayParent: function(node) {
+ while (node && node !== document.body) {
+ // Check if it is an overlay.
+ if (node._manager === this) {
+ return node;
+ }
+ // Use logical parentNode, or native ShadowRoot host.
+ node = Polymer.dom(node).parentNode || node.host;
}
},
/**
- * Shows the backdrop if needed.
+ * Returns the deepest overlay in the path.
+ * @param {Array<Element>=} path
+ * @return {Element|undefined}
+ * @private
*/
- open: function() {
- // only need to make the backdrop visible if this is called by the first overlay with a backdrop
- if (this._manager.getBackdrops().length < 2) {
- this._setOpened(true);
+ _overlayInPath: function(path) {
+ path = path || [];
+ for (var i = 0; i < path.length; i++) {
+ if (path[i]._manager === this) {
+ return path[i];
+ }
}
},
/**
- * Hides the backdrop if needed.
+ * Ensures the click event is delegated to the right overlay.
+ * @param {!Event} event
+ * @private
*/
- close: function() {
- // Always update z-index
- this.style.zIndex = this._manager.backdropZ();
- // close only if no element with backdrop is left
- if (this._manager.getBackdrops().length === 0) {
- // Read style before setting opened.
- var cs = getComputedStyle(this);
- var noAnimation = (cs.transitionDuration === '0s' || cs.opacity == 0);
- this._setOpened(false);
- // In case of no animations, complete
- if (noAnimation) {
- this.complete();
+ _onCaptureClick: function(event) {
+ var overlay = /** @type {?} */ (this.currentOverlay());
+ // Check if clicked outside of top overlay.
+ if (overlay && this._overlayInPath(Polymer.dom(event).path) !== overlay) {
+ if (overlay.withBackdrop) {
+ // There's no need to stop the propagation as the backdrop element
+ // already got this mousedown/touchstart event. Calling preventDefault
+ // on this event ensures that click/tap won't be triggered at all.
+ event.preventDefault();
}
+ overlay._onCaptureClick(event);
}
},
/**
- * Removes the backdrop from document body if needed.
+ * Ensures the focus event is delegated to the right overlay.
+ * @param {!Event} event
+ * @private
*/
- complete: function() {
- // only remove the backdrop if there are no more overlays with backdrops
- if (this._manager.getBackdrops().length === 0 && this.parentNode) {
- Polymer.dom(this.parentNode).removeChild(this);
+ _onCaptureFocus: function(event) {
+ var overlay = /** @type {?} */ (this.currentOverlay());
+ if (overlay) {
+ overlay._onCaptureFocus(event);
}
},
- _onTransitionend: function (event) {
- if (event && event.target === this) {
- this.complete();
+ /**
+ * Ensures TAB and ESC keyboard events are delegated to the right overlay.
+ * @param {!Event} event
+ * @private
+ */
+ _onCaptureKeyDown: function(event) {
+ var overlay = /** @type {?} */ (this.currentOverlay());
+ if (overlay) {
+ if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'esc')) {
+ overlay._onCaptureEsc(event);
+ } else if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(event, 'tab')) {
+ overlay._onCaptureTab(event);
+ }
}
+ },
+
+ /**
+ * Returns if the overlay1 should be behind overlay2.
+ * @param {!Element} overlay1
+ * @param {!Element} overlay2
+ * @return {boolean}
+ * @private
+ */
+ _shouldBeBehindOverlay: function(overlay1, overlay2) {
+ var o1 = /** @type {?} */ (overlay1);
+ var o2 = /** @type {?} */ (overlay2);
+ return !o1.alwaysOnTop && o2.alwaysOnTop;
}
+ };
- });
+ Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass();
+(function() {
+'use strict';
-})();
/**
Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden or shown, and displays
on top of other content. It includes an optional backdrop, and can be used to implement a variety
@@ -7943,7 +8609,9 @@ context. You should place this element as a child of `<body>` whenever possible.
},
/**
- * Returns the reason this dialog was last closed.
+ * Contains the reason(s) this overlay was last closed (see `iron-overlay-closed`).
+ * `IronOverlayBehavior` provides the `canceled` reason; implementers of the
+ * behavior can provide other reasons in addition to `canceled`.
*/
closingReason: {
// was a getter before, but needs to be a property so other
@@ -7952,15 +8620,6 @@ context. You should place this element as a child of `<body>` whenever possible.
},
/**
- * The HTMLElement that will be firing relevant KeyboardEvents.
- * Used for capturing esc and tab. Overridden from `IronA11yKeysBehavior`.
- */
- keyEventTarget: {
- type: Object,
- value: document
- },
-
- /**
* Set to true to enable restoring of focus when overlay is closed.
*/
restoreFocusOnClose: {
@@ -7968,25 +8627,23 @@ context. You should place this element as a child of `<body>` whenever possible.
value: false
},
+ /**
+ * Set to true to keep overlay always on top.
+ */
+ alwaysOnTop: {
+ type: Boolean
+ },
+
+ /**
+ * Shortcut to access to the overlay manager.
+ * @private
+ * @type {Polymer.IronOverlayManagerClass}
+ */
_manager: {
type: Object,
value: Polymer.IronOverlayManager
},
- _boundOnCaptureClick: {
- type: Function,
- value: function() {
- return this._onCaptureClick.bind(this);
- }
- },
-
- _boundOnCaptureFocus: {
- type: Function,
- value: function() {
- return this._onCaptureFocus.bind(this);
- }
- },
-
/**
* The node being focused.
* @type {?Node}
@@ -7997,18 +8654,13 @@ context. You should place this element as a child of `<body>` whenever possible.
},
- keyBindings: {
- 'esc': '__onEsc',
- 'tab': '__onTab'
- },
-
listeners: {
'iron-resize': '_onIronResize'
},
/**
* The backdrop element.
- * @type {Node}
+ * @type {Element}
*/
get backdropElement() {
return this._manager.backdropElement;
@@ -8029,7 +8681,7 @@ context. You should place this element as a child of `<body>` whenever possible.
*
* If you know what is your content (specifically the first and last focusable children),
* you can override this method to return only `[firstFocusable, lastFocusable];`
- * @type {[Node]}
+ * @type {Array<Node>}
* @protected
*/
get _focusableNodes() {
@@ -8075,11 +8727,17 @@ context. You should place this element as a child of `<body>` whenever possible.
},
ready: function() {
+ // Used to skip calls to notifyResize and refit while the overlay is animating.
+ this.__isAnimating = false;
// with-backdrop needs tabindex to be set in order to trap the focus.
// If it is not set, IronOverlayBehavior will set it, and remove it if with-backdrop = false.
this.__shouldRemoveTabIndex = false;
// Used for wrapping the focus on TAB / Shift+TAB.
this.__firstFocusableNode = this.__lastFocusableNode = null;
+ // Used for requestAnimationFrame when opened changes.
+ this.__openChangedAsync = null;
+ // Used for requestAnimationFrame when iron-resize is fired.
+ this.__onIronResizeAsync = null;
this._ensureSetup();
},
@@ -8095,8 +8753,6 @@ context. You should place this element as a child of `<body>` whenever possible.
Polymer.dom(this).unobserveNodes(this._observer);
this._observer = null;
this.opened = false;
- this._manager.trackBackdrop(this);
- this._manager.removeOverlay(this);
},
/**
@@ -8125,7 +8781,7 @@ context. You should place this element as a child of `<body>` whenever possible.
/**
* Cancels the overlay.
- * @param {?Event} event The original event
+ * @param {Event=} event The original event
*/
cancel: function(event) {
var cancelEvent = this.fire('iron-overlay-canceled', event, {cancelable: true});
@@ -8158,31 +8814,30 @@ context. You should place this element as a child of `<body>` whenever possible.
return;
}
- this._manager.trackBackdrop(this);
+ this._manager.addOrRemoveOverlay(this);
- if (this.opened) {
- this._prepareRenderOpened();
+ if (this.__openChangedAsync) {
+ window.cancelAnimationFrame(this.__openChangedAsync);
}
- if (this._openChangedAsync) {
- this.cancelAsync(this._openChangedAsync);
+ // Defer any animation-related code on attached
+ // (_openedChanged gets called again on attached).
+ if (!this.isAttached) {
+ return;
}
- // Async here to allow overlay layer to become visible, and to avoid
- // listeners to immediately close via a click.
- this._openChangedAsync = this.async(function() {
- // overlay becomes visible here
- this.style.display = '';
- // Force layout to ensure transition will go. Set offsetWidth to itself
- // so that compilers won't remove it.
- this.offsetWidth = this.offsetWidth;
+
+ this.__isAnimating = true;
+
+ // requestAnimationFrame for non-blocking rendering
+ this.__openChangedAsync = window.requestAnimationFrame(function() {
+ this.__openChangedAsync = null;
if (this.opened) {
+ this._prepareRenderOpened();
this._renderOpened();
} else {
this._renderClosed();
}
- this._toggleListeners();
- this._openChangedAsync = null;
- }, 1);
+ }.bind(this));
},
_canceledChanged: function() {
@@ -8200,55 +8855,22 @@ context. You should place this element as a child of `<body>` whenever possible.
this.__shouldRemoveTabIndex = false;
}
if (this.opened) {
- this._manager.trackBackdrop(this);
- if (this.withBackdrop) {
- this.backdropElement.prepare();
- // Give time to be added to document.
- this.async(function(){
- this.backdropElement.open();
- }, 1);
- } else {
- this.backdropElement.close();
- }
- }
- },
-
- _toggleListener: function(enable, node, event, boundListener, capture) {
- if (enable) {
- // enable document-wide tap recognizer
- if (event === 'tap') {
- Polymer.Gestures.add(document, 'tap', null);
- }
- node.addEventListener(event, boundListener, capture);
- } else {
- // disable document-wide tap recognizer
- if (event === 'tap') {
- Polymer.Gestures.remove(document, 'tap', null);
- }
- node.removeEventListener(event, boundListener, capture);
+ this._manager.trackBackdrop();
}
},
- _toggleListeners: function() {
- this._toggleListener(this.opened, document, 'tap', this._boundOnCaptureClick, true);
- this._toggleListener(this.opened, document, 'focus', this._boundOnCaptureFocus, true);
- },
-
- // tasks which must occur before opening; e.g. making the element visible
+ /**
+ * tasks which must occur before opening; e.g. making the element visible.
+ * @protected
+ */
_prepareRenderOpened: function() {
- this._manager.addOverlay(this);
-
// Needed to calculate the size of the overlay so that transitions on its size
// will have the correct starting points.
this._preparePositioning();
- this.fit();
+ this.refit();
this._finishPositioning();
- if (this.withBackdrop) {
- this.backdropElement.prepare();
- }
-
// Safari will apply the focus to the autofocus element when displayed for the first time,
// so we blur it. Later, _applyFocus will set the focus if necessary.
if (this.noAutoFocus && document.activeElement === this._focusNode) {
@@ -8256,41 +8878,49 @@ context. You should place this element as a child of `<body>` whenever possible.
}
},
- // tasks which cause the overlay to actually open; typically play an
- // animation
+ /**
+ * Tasks which cause the overlay to actually open; typically play an animation.
+ * @protected
+ */
_renderOpened: function() {
- if (this.withBackdrop) {
- this.backdropElement.open();
- }
this._finishRenderOpened();
},
+ /**
+ * Tasks which cause the overlay to actually close; typically play an animation.
+ * @protected
+ */
_renderClosed: function() {
- if (this.withBackdrop) {
- this.backdropElement.close();
- }
this._finishRenderClosed();
},
+ /**
+ * Tasks to be performed at the end of open action. Will fire `iron-overlay-opened`.
+ * @protected
+ */
_finishRenderOpened: function() {
- // This ensures the overlay is visible before we set the focus
- // (by calling _onIronResize -> refit).
- this.notifyResize();
// Focus the child node with [autofocus]
this._applyFocus();
+ this.notifyResize();
+ this.__isAnimating = false;
this.fire('iron-overlay-opened');
},
+ /**
+ * Tasks to be performed at the end of close action. Will fire `iron-overlay-closed`.
+ * @protected
+ */
_finishRenderClosed: function() {
// Hide the overlay and remove the backdrop.
- this.resetFit();
this.style.display = 'none';
- this._manager.removeOverlay(this);
+ // Reset z-index only at the end of the animation.
+ this.style.zIndex = '';
this._applyFocus();
- this.notifyResize();
+ this.notifyResize();
+ this.__isAnimating = false;
this.fire('iron-overlay-closed', this.closingReason);
},
@@ -8301,14 +8931,24 @@ context. You should place this element as a child of `<body>` whenever possible.
},
_finishPositioning: function() {
+ // First, make it invisible & reactivate animations.
this.style.display = 'none';
- this.style.transform = this.style.webkitTransform = '';
- // Force layout layout to avoid application of transform.
- // Set offsetWidth to itself so that compilers won't remove it.
- this.offsetWidth = this.offsetWidth;
+ // Force reflow before re-enabling animations so that they don't start.
+ // Set scrollTop to itself so that Closure Compiler doesn't remove this.
+ this.scrollTop = this.scrollTop;
this.style.transition = this.style.webkitTransition = '';
+ this.style.transform = this.style.webkitTransform = '';
+ // Now that animations are enabled, make it visible again
+ this.style.display = '';
+ // Force reflow, so that following animations are properly started.
+ // Set scrollTop to itself so that Closure Compiler doesn't remove this.
+ this.scrollTop = this.scrollTop;
},
+ /**
+ * Applies focus according to the opened state.
+ * @protected
+ */
_applyFocus: function() {
if (this.opened) {
if (!this.noAutoFocus) {
@@ -8321,191 +8961,132 @@ context. You should place this element as a child of `<body>` whenever possible.
}
},
+ /**
+ * Cancels (closes) the overlay. Call when click happens outside the overlay.
+ * @param {!Event} event
+ * @protected
+ */
_onCaptureClick: function(event) {
- if (this._manager.currentOverlay() === this &&
- Polymer.dom(event).path.indexOf(this) === -1) {
- if (this.noCancelOnOutsideClick) {
- this._applyFocus();
- } else {
- this.cancel(event);
- }
+ if (!this.noCancelOnOutsideClick) {
+ this.cancel(event);
}
},
+ /**
+ * Keeps track of the focused child. If withBackdrop, traps focus within overlay.
+ * @param {!Event} event
+ * @protected
+ */
_onCaptureFocus: function (event) {
- if (this._manager.currentOverlay() === this && this.withBackdrop) {
- var path = Polymer.dom(event).path;
- if (path.indexOf(this) === -1) {
- event.stopPropagation();
- this._applyFocus();
- } else {
- this._focusedChild = path[0];
- }
+ if (!this.withBackdrop) {
+ return;
}
- },
-
- _onIronResize: function() {
- if (this.opened) {
- this.refit();
+ var path = Polymer.dom(event).path;
+ if (path.indexOf(this) === -1) {
+ event.stopPropagation();
+ this._applyFocus();
+ } else {
+ this._focusedChild = path[0];
}
},
/**
+ * Handles the ESC key event and cancels (closes) the overlay.
+ * @param {!Event} event
* @protected
- * Will call notifyResize if overlay is opened.
- * Can be overridden in order to avoid multiple observers on the same node.
*/
- _onNodesChange: function() {
- if (this.opened) {
- this.notifyResize();
- }
- // Store it so we don't query too much.
- var focusableNodes = this._focusableNodes;
- this.__firstFocusableNode = focusableNodes[0];
- this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1];
- },
-
- __onEsc: function(event) {
- // Not opened or not on top, so return.
- if (this._manager.currentOverlay() !== this) {
- return;
- }
+ _onCaptureEsc: function(event) {
if (!this.noCancelOnEscKey) {
this.cancel(event);
}
},
- __onTab: function(event) {
- // Not opened or not on top, so return.
- if (this._manager.currentOverlay() !== this) {
- return;
- }
+ /**
+ * Handles TAB key events to track focus changes.
+ * Will wrap focus for overlays withBackdrop.
+ * @param {!Event} event
+ * @protected
+ */
+ _onCaptureTab: function(event) {
// TAB wraps from last to first focusable.
// Shift + TAB wraps from first to last focusable.
- var shift = event.detail.keyboardEvent.shiftKey;
+ var shift = event.shiftKey;
var nodeToCheck = shift ? this.__firstFocusableNode : this.__lastFocusableNode;
var nodeToSet = shift ? this.__lastFocusableNode : this.__firstFocusableNode;
if (this.withBackdrop && this._focusedChild === nodeToCheck) {
- // We set here the _focusedChild so that _onCaptureFocus will handle the
- // wrapping of the focus (the next event after tab is focus).
+ // When the overlay contains the last focusable element of the document
+ // and it's already focused, pressing TAB would move the focus outside
+ // the document (e.g. to the browser search bar). Similarly, when the
+ // overlay contains the first focusable element of the document and it's
+ // already focused, pressing Shift+TAB would move the focus outside the
+ // document (e.g. to the browser search bar).
+ // In both cases, we would not receive a focus event, but only a blur.
+ // In order to achieve focus wrapping, we prevent this TAB event and
+ // force the focus. This will also prevent the focus to temporarily move
+ // outside the overlay, which might cause scrolling.
+ event.preventDefault();
this._focusedChild = nodeToSet;
+ this._applyFocus();
}
- }
- };
-
- /** @polymerBehavior */
- Polymer.IronOverlayBehavior = [Polymer.IronA11yKeysBehavior, Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl];
-
- /**
- * Fired after the `iron-overlay` opens.
- * @event iron-overlay-opened
- */
-
- /**
- * Fired when the `iron-overlay` is canceled, but before it is closed.
- * Cancel the event to prevent the `iron-overlay` from closing.
- * @event iron-overlay-canceled
- * @param {Event} event The closing of the `iron-overlay` can be prevented
- * by calling `event.preventDefault()`. The `event.detail` is the original event that originated
- * the canceling (e.g. ESC keyboard event or click event outside the `iron-overlay`).
- */
-
- /**
- * Fired after the `iron-overlay` closes.
- * @event iron-overlay-closed
- * @param {{canceled: (boolean|undefined)}} closingReason Contains `canceled` (whether the overlay was canceled).
- */
-/**
- * Use `Polymer.NeonAnimationBehavior` to implement an animation.
- * @polymerBehavior
- */
- Polymer.NeonAnimationBehavior = {
-
- properties: {
-
- /**
- * Defines the animation timing.
- */
- animationTiming: {
- type: Object,
- value: function() {
- return {
- duration: 500,
- easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
- fill: 'both'
- }
- }
- }
-
- },
-
- registered: function() {
- new Polymer.IronMeta({type: 'animation', key: this.is, value: this.constructor});
},
/**
- * Do any animation configuration here.
- */
- // configure: function(config) {
- // },
-
- /**
- * Returns the animation timing by mixing in properties from `config` to the defaults defined
- * by the animation.
+ * Refits if the overlay is opened and not animating.
+ * @protected
*/
- timingFromConfig: function(config) {
- if (config.timing) {
- for (var property in config.timing) {
- this.animationTiming[property] = config.timing[property];
- }
+ _onIronResize: function() {
+ if (this.__onIronResizeAsync) {
+ window.cancelAnimationFrame(this.__onIronResizeAsync);
+ this.__onIronResizeAsync = null;
}
- return this.animationTiming;
- },
-
- /**
- * Sets `transform` and `transformOrigin` properties along with the prefixed versions.
- */
- setPrefixedProperty: function(node, property, value) {
- var map = {
- 'transform': ['webkitTransform'],
- 'transformOrigin': ['mozTransformOrigin', 'webkitTransformOrigin']
- };
- var prefixes = map[property];
- for (var prefix, index = 0; prefix = prefixes[index]; index++) {
- node.style[prefix] = value;
+ if (this.opened && !this.__isAnimating) {
+ this.__onIronResizeAsync = window.requestAnimationFrame(function() {
+ this.__onIronResizeAsync = null;
+ this.refit();
+ }.bind(this));
}
- node.style[property] = value;
},
/**
- * Called when the animation finishes.
+ * Will call notifyResize if overlay is opened.
+ * Can be overridden in order to avoid multiple observers on the same node.
+ * @protected
*/
- complete: function() {}
-
+ _onNodesChange: function() {
+ if (this.opened && !this.__isAnimating) {
+ this.notifyResize();
+ }
+ // Store it so we don't query too much.
+ var focusableNodes = this._focusableNodes;
+ this.__firstFocusableNode = focusableNodes[0];
+ this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1];
+ }
};
-Polymer({
- is: 'opaque-animation',
+ /** @polymerBehavior */
+ Polymer.IronOverlayBehavior = [Polymer.IronFitBehavior, Polymer.IronResizableBehavior, Polymer.IronOverlayBehaviorImpl];
- behaviors: [
- Polymer.NeonAnimationBehavior
- ],
+ /**
+ * Fired after the overlay opens.
+ * @event iron-overlay-opened
+ */
- configure: function(config) {
- var node = config.node;
- node.style.opacity = '0';
- this._effect = new KeyframeEffect(node, [
- {'opacity': '1'},
- {'opacity': '1'}
- ], this.timingFromConfig(config));
- return this._effect;
- },
+ /**
+ * Fired when the overlay is canceled, but before it is closed.
+ * @event iron-overlay-canceled
+ * @param {Event} event The closing of the overlay can be prevented
+ * by calling `event.preventDefault()`. The `event.detail` is the original event that
+ * originated the canceling (e.g. ESC keyboard event or click event outside the overlay).
+ */
- complete: function(config) {
- config.node.style.opacity = '';
- }
+ /**
+ * Fired after the overlay closes.
+ * @event iron-overlay-closed
+ * @param {Event} event The `event.detail` is the `closingReason` property
+ * (contains `canceled`, whether the overlay was canceled).
+ */
- });
+})();
/**
* `Polymer.NeonAnimatableBehavior` is implemented by elements containing animations for use with
* elements implementing `Polymer.NeonAnimationRunnerBehavior`.
@@ -8544,21 +9125,10 @@ Polymer({
_entryAnimationChanged: function() {
this.animationConfig = this.animationConfig || {};
- if (this.entryAnimation !== 'fade-in-animation') {
- // insert polyfill hack
- this.animationConfig['entry'] = [{
- name: 'opaque-animation',
- node: this
- }, {
- name: this.entryAnimation,
- node: this
- }];
- } else {
- this.animationConfig['entry'] = [{
- name: this.entryAnimation,
- node: this
- }];
- }
+ this.animationConfig['entry'] = [{
+ name: this.entryAnimation,
+ node: this
+ }];
},
_exitAnimationChanged: function() {
@@ -8660,13 +9230,6 @@ Polymer({
properties: {
- _animationMeta: {
- type: Object,
- value: function() {
- return new Polymer.IronMeta({type: 'animation'});
- }
- },
-
/** @type {?Object} */
_player: {
type: Object
@@ -8678,9 +9241,9 @@ Polymer({
var allAnimations = [];
if (allConfigs.length > 0) {
for (var config, index = 0; config = allConfigs[index]; index++) {
- var animationConstructor = this._animationMeta.byKey(config.name);
- if (animationConstructor) {
- var animation = animationConstructor && new animationConstructor();
+ var animation = document.createElement(config.name);
+ // is this element actually a neon animation?
+ if (animation.isNeonAnimation) {
var effect = animation.configure(config);
if (effect) {
allAnimations.push({
@@ -8717,27 +9280,30 @@ Polymer({
if (!allConfigs) {
return;
}
- var allAnimations = this._configureAnimationEffects(allConfigs);
- var allEffects = allAnimations.map(function(animation) {
- return animation.effect;
- });
+ try {
+ var allAnimations = this._configureAnimationEffects(allConfigs);
+ var allEffects = allAnimations.map(function(animation) {
+ return animation.effect;
+ });
- if (allEffects.length > 0) {
- this._player = this._runAnimationEffects(allEffects);
- this._player.onfinish = function() {
- this._completeAnimations(allAnimations);
+ if (allEffects.length > 0) {
+ this._player = this._runAnimationEffects(allEffects);
+ this._player.onfinish = function() {
+ this._completeAnimations(allAnimations);
- if (this._player) {
- this._player.cancel();
- this._player = null;
- }
-
- this.fire('neon-animation-finish', cookie, {bubbles: false});
- }.bind(this);
+ if (this._player) {
+ this._player.cancel();
+ this._player = null;
+ }
- } else {
- this.fire('neon-animation-finish', cookie, {bubbles: false});
+ this.fire('neon-animation-finish', cookie, {bubbles: false});
+ }.bind(this);
+ return;
+ }
+ } catch (e) {
+ console.warn('Couldnt play', '(', type, allConfigs, ').', e);
}
+ this.fire('neon-animation-finish', cookie, {bubbles: false});
},
/**
@@ -8755,6 +9321,98 @@ Polymer({
Polymer.NeonAnimatableBehavior,
Polymer.NeonAnimationRunnerBehaviorImpl
];
+/**
+ * Use `Polymer.NeonAnimationBehavior` to implement an animation.
+ * @polymerBehavior
+ */
+ Polymer.NeonAnimationBehavior = {
+
+ properties: {
+
+ /**
+ * Defines the animation timing.
+ */
+ animationTiming: {
+ type: Object,
+ value: function() {
+ return {
+ duration: 500,
+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
+ fill: 'both'
+ }
+ }
+ }
+
+ },
+
+ /**
+ * Can be used to determine that elements implement this behavior.
+ */
+ isNeonAnimation: true,
+
+ /**
+ * Do any animation configuration here.
+ */
+ // configure: function(config) {
+ // },
+
+ /**
+ * Returns the animation timing by mixing in properties from `config` to the defaults defined
+ * by the animation.
+ */
+ timingFromConfig: function(config) {
+ if (config.timing) {
+ for (var property in config.timing) {
+ this.animationTiming[property] = config.timing[property];
+ }
+ }
+ return this.animationTiming;
+ },
+
+ /**
+ * Sets `transform` and `transformOrigin` properties along with the prefixed versions.
+ */
+ setPrefixedProperty: function(node, property, value) {
+ var map = {
+ 'transform': ['webkitTransform'],
+ 'transformOrigin': ['mozTransformOrigin', 'webkitTransformOrigin']
+ };
+ var prefixes = map[property];
+ for (var prefix, index = 0; prefix = prefixes[index]; index++) {
+ node.style[prefix] = value;
+ }
+ node.style[property] = value;
+ },
+
+ /**
+ * Called when the animation finishes.
+ */
+ complete: function() {}
+
+ };
+Polymer({
+
+ is: 'opaque-animation',
+
+ behaviors: [
+ Polymer.NeonAnimationBehavior
+ ],
+
+ configure: function(config) {
+ var node = config.node;
+ this._effect = new KeyframeEffect(node, [
+ {'opacity': '1'},
+ {'opacity': '1'}
+ ], this.timingFromConfig(config));
+ node.style.opacity = '0';
+ return this._effect;
+ },
+
+ complete: function(config) {
+ config.node.style.opacity = '';
+ }
+
+ });
(function() {
'use strict';
@@ -8918,9 +9576,11 @@ Polymer({
},
_scrollInteractionHandler: function(event) {
+ var scrolledElement =
+ /** @type {HTMLElement} */(Polymer.dom(event).rootTarget);
if (Polymer
.IronDropdownScrollManager
- .elementIsScrollLocked(Polymer.dom(event).rootTarget)) {
+ .elementIsScrollLocked(scrolledElement)) {
if (event.type === 'keydown' &&
!Polymer.IronDropdownScrollManager._isScrollingKeypress(event)) {
return;
@@ -8988,6 +9648,7 @@ Polymer({
/**
* The orientation against which to align the dropdown content
* horizontally relative to the dropdown trigger.
+ * Overridden from `Polymer.IronFitBehavior`.
*/
horizontalAlign: {
type: String,
@@ -8998,6 +9659,7 @@ Polymer({
/**
* The orientation against which to align the dropdown content
* vertically relative to the dropdown trigger.
+ * Overridden from `Polymer.IronFitBehavior`.
*/
verticalAlign: {
type: String,
@@ -9006,55 +9668,6 @@ Polymer({
},
/**
- * A pixel value that will be added to the position calculated for the
- * given `horizontalAlign`, in the direction of alignment. You can think
- * of it as increasing or decreasing the distance to the side of the
- * screen given by `horizontalAlign`.
- *
- * If `horizontalAlign` is "left", this offset will increase or decrease
- * the distance to the left side of the screen: a negative offset will
- * move the dropdown to the left; a positive one, to the right.
- *
- * Conversely if `horizontalAlign` is "right", this offset will increase
- * or decrease the distance to the right side of the screen: a negative
- * offset will move the dropdown to the right; a positive one, to the left.
- */
- horizontalOffset: {
- type: Number,
- value: 0,
- notify: true
- },
-
- /**
- * A pixel value that will be added to the position calculated for the
- * given `verticalAlign`, in the direction of alignment. You can think
- * of it as increasing or decreasing the distance to the side of the
- * screen given by `verticalAlign`.
- *
- * If `verticalAlign` is "top", this offset will increase or decrease
- * the distance to the top side of the screen: a negative offset will
- * move the dropdown upwards; a positive one, downwards.
- *
- * Conversely if `verticalAlign` is "bottom", this offset will increase
- * or decrease the distance to the bottom side of the screen: a negative
- * offset will move the dropdown downwards; a positive one, upwards.
- */
- verticalOffset: {
- type: Number,
- value: 0,
- notify: true
- },
-
- /**
- * The element that should be used to position the dropdown when
- * it is opened.
- */
- positionTarget: {
- type: Object,
- observer: '_positionTargetChanged'
- },
-
- /**
* An animation config. If provided, this will be used to animate the
* opening of the dropdown.
*/
@@ -9096,15 +9709,6 @@ Polymer({
allowOutsideScroll: {
type: Boolean,
value: false
- },
-
- /**
- * We memoize the positionTarget bounding rectangle so that we can
- * limit the number of times it is queried per resize / relayout.
- * @type {?Object}
- */
- _positionRectMemo: {
- type: Object
}
},
@@ -9113,15 +9717,9 @@ Polymer({
},
observers: [
- '_updateOverlayPosition(verticalAlign, horizontalAlign, verticalOffset, horizontalOffset)'
+ '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign, verticalOffset, horizontalOffset)'
],
- attached: function() {
- if (this.positionTarget === undefined) {
- this.positionTarget = this._defaultPositionTarget;
- }
- },
-
/**
* The element that is contained by the dropdown, if any.
*/
@@ -9138,97 +9736,21 @@ Polymer({
},
/**
- * Whether the text direction is RTL
- */
- _isRTL: function() {
- return window.getComputedStyle(this).direction == 'rtl';
- },
-
- /**
- * The element that should be used to position the dropdown when
- * it opens, if no position target is configured.
- */
- get _defaultPositionTarget() {
- var parent = Polymer.dom(this).parentNode;
-
- if (parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
- parent = parent.host;
- }
-
- return parent;
- },
-
- /**
- * The bounding rect of the position target.
- */
- get _positionRect() {
- if (!this._positionRectMemo && this.positionTarget) {
- this._positionRectMemo = this.positionTarget.getBoundingClientRect();
- }
-
- return this._positionRectMemo;
- },
-
- /**
- * The horizontal offset value used to position the dropdown.
- */
- get _horizontalAlignTargetValue() {
- var target;
-
- // In RTL, the direction flips, so what is "right" in LTR becomes "left".
- var isRTL = this._isRTL();
- if ((!isRTL && this.horizontalAlign === 'right') ||
- (isRTL && this.horizontalAlign === 'left')) {
- target = document.documentElement.clientWidth - this._positionRect.right;
- } else {
- target = this._positionRect.left;
- }
-
- target += this.horizontalOffset;
-
- return Math.max(target, 0);
- },
-
- /**
- * The vertical offset value used to position the dropdown.
- */
- get _verticalAlignTargetValue() {
- var target;
-
- if (this.verticalAlign === 'bottom') {
- target = document.documentElement.clientHeight - this._positionRect.bottom;
- } else {
- target = this._positionRect.top;
- }
-
- target += this.verticalOffset;
-
- return Math.max(target, 0);
- },
-
- /**
- * The horizontal align value, accounting for the RTL/LTR text direction.
- */
- get _localeHorizontalAlign() {
- // In RTL, "left" becomes "right".
- if (this._isRTL()) {
- return this.horizontalAlign === 'right' ? 'left' : 'right';
- } else {
- return this.horizontalAlign;
- }
- },
-
- /**
* Called when the value of `opened` changes.
- *
- * @param {boolean} opened True if the dropdown is opened.
+ * Overridden from `IronOverlayBehavior`
*/
- _openedChanged: function(opened) {
- if (opened && this.disabled) {
+ _openedChanged: function() {
+ if (this.opened && this.disabled) {
this.cancel();
} else {
this.cancelAnimation();
- this._prepareDropdown();
+ this.sizingTarget = this.containedElement || this.sizingTarget;
+ this._updateAnimationConfig();
+ if (this.opened && !this.allowOutsideScroll) {
+ Polymer.IronDropdownScrollManager.pushScrollLock(this);
+ } else {
+ Polymer.IronDropdownScrollManager.removeScrollLock(this);
+ }
Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments);
}
},
@@ -9237,11 +9759,10 @@ Polymer({
* Overridden from `IronOverlayBehavior`.
*/
_renderOpened: function() {
- if (!this.allowOutsideScroll) {
- Polymer.IronDropdownScrollManager.pushScrollLock(this);
- }
-
if (!this.noAnimations && this.animationConfig && this.animationConfig.open) {
+ if (this.withBackdrop) {
+ this.backdropElement.open();
+ }
this.$.contentWrapper.classList.add('animating');
this.playAnimation('open');
} else {
@@ -9253,8 +9774,10 @@ Polymer({
* Overridden from `IronOverlayBehavior`.
*/
_renderClosed: function() {
- Polymer.IronDropdownScrollManager.removeScrollLock(this);
if (!this.noAnimations && this.animationConfig && this.animationConfig.close) {
+ if (this.withBackdrop) {
+ this.backdropElement.close();
+ }
this.$.contentWrapper.classList.add('animating');
this.playAnimation('close');
} else {
@@ -9271,45 +9794,13 @@ Polymer({
_onNeonAnimationFinish: function() {
this.$.contentWrapper.classList.remove('animating');
if (this.opened) {
- Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this);
+ Polymer.IronOverlayBehaviorImpl._finishRenderOpened.apply(this);
} else {
- Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this);
+ Polymer.IronOverlayBehaviorImpl._finishRenderClosed.apply(this);
}
},
/**
- * Called when an `iron-resize` event fires.
- */
- _onIronResize: function() {
- var containedElement = this.containedElement;
- var scrollTop;
- var scrollLeft;
-
- if (this.opened && containedElement) {
- scrollTop = containedElement.scrollTop;
- scrollLeft = containedElement.scrollLeft;
- }
-
- if (this.opened) {
- this._updateOverlayPosition();
- }
-
- Polymer.IronOverlayBehaviorImpl._onIronResize.apply(this, arguments);
-
- if (this.opened && containedElement) {
- containedElement.scrollTop = scrollTop;
- containedElement.scrollLeft = scrollLeft;
- }
- },
-
- /**
- * Called when the `positionTarget` property changes.
- */
- _positionTargetChanged: function() {
- this._updateOverlayPosition();
- },
-
- /**
* Constructs the final animation config from different properties used
* to configure specific parts of the opening and closing animations.
*/
@@ -9341,42 +9832,37 @@ Polymer({
},
/**
- * Prepares the dropdown for opening by updating measured layout
- * values.
+ * Updates the overlay position based on configured horizontal
+ * and vertical alignment.
*/
- _prepareDropdown: function() {
- this.sizingTarget = this.containedElement || this.sizingTarget;
- this._updateAnimationConfig();
- this._updateOverlayPosition();
+ _updateOverlayPosition: function() {
+ if (this.isAttached) {
+ // This triggers iron-resize, and iron-overlay-behavior will call refit if needed.
+ this.notifyResize();
+ }
},
/**
- * Updates the overlay position based on configured horizontal
- * and vertical alignment, and re-memoizes these values for the sake
- * of behavior in `IronFitBehavior`.
+ * Useful to call this after the element, the window, or the `fitInfo`
+ * element has been resized. Will maintain the scroll position.
*/
- _updateOverlayPosition: function() {
- this._positionRectMemo = null;
-
- if (!this.positionTarget) {
- return;
+ refit: function () {
+ if (!this.opened) {
+ return
}
+ var containedElement = this.containedElement;
+ var scrollTop;
+ var scrollLeft;
- this.style[this._localeHorizontalAlign] =
- this._horizontalAlignTargetValue + 'px';
-
- this.style[this.verticalAlign] =
- this._verticalAlignTargetValue + 'px';
-
- // NOTE(cdata): We re-memoize inline styles here, otherwise
- // calling `refit` from `IronFitBehavior` will reset inline styles
- // to whatever they were when the dropdown first opened.
- if (this._fitInfo) {
- this._fitInfo.inlineStyle[this.horizontalAlign] =
- this.style[this.horizontalAlign];
+ if (containedElement) {
+ scrollTop = containedElement.scrollTop;
+ scrollLeft = containedElement.scrollLeft;
+ }
+ Polymer.IronFitBehavior.refit.apply(this, arguments);
- this._fitInfo.inlineStyle[this.verticalAlign] =
- this.style[this.verticalAlign];
+ if (containedElement) {
+ containedElement.scrollTop = scrollTop;
+ containedElement.scrollLeft = scrollLeft;
}
},
@@ -9522,257 +10008,278 @@ Polymer({
}
});
(function() {
- 'use strict';
+ 'use strict';
- var PaperMenuButton = Polymer({
- is: 'paper-menu-button',
+ var PaperMenuButton = Polymer({
+ is: 'paper-menu-button',
- /**
- * Fired when the dropdown opens.
- *
- * @event paper-dropdown-open
- */
+ /**
+ * Fired when the dropdown opens.
+ *
+ * @event paper-dropdown-open
+ */
- /**
- * Fired when the dropdown closes.
- *
- * @event paper-dropdown-close
- */
+ /**
+ * Fired when the dropdown closes.
+ *
+ * @event paper-dropdown-close
+ */
- behaviors: [
- Polymer.IronA11yKeysBehavior,
- Polymer.IronControlState
- ],
+ behaviors: [
+ Polymer.IronA11yKeysBehavior,
+ Polymer.IronControlState
+ ],
- properties: {
+ properties: {
+ /**
+ * True if the content is currently displayed.
+ */
+ opened: {
+ type: Boolean,
+ value: false,
+ notify: true,
+ observer: '_openedChanged'
+ },
- /**
- * True if the content is currently displayed.
- */
- opened: {
- type: Boolean,
- value: false,
- notify: true,
- observer: '_openedChanged'
+ /**
+ * The orientation against which to align the menu dropdown
+ * horizontally relative to the dropdown trigger.
+ */
+ horizontalAlign: {
+ type: String,
+ value: 'left',
+ reflectToAttribute: true
+ },
+
+ /**
+ * The orientation against which to align the menu dropdown
+ * vertically relative to the dropdown trigger.
+ */
+ verticalAlign: {
+ type: String,
+ value: 'top',
+ reflectToAttribute: true
+ },
+
+ /**
+ * A pixel value that will be added to the position calculated for the
+ * given `horizontalAlign`. Use a negative value to offset to the
+ * left, or a positive value to offset to the right.
+ */
+ horizontalOffset: {
+ type: Number,
+ value: 0,
+ notify: true
+ },
+
+ /**
+ * A pixel value that will be added to the position calculated for the
+ * given `verticalAlign`. Use a negative value to offset towards the
+ * top, or a positive value to offset towards the bottom.
+ */
+ verticalOffset: {
+ type: Number,
+ value: 0,
+ notify: true
+ },
+
+ /**
+ * Set to true to disable animations when opening and closing the
+ * dropdown.
+ */
+ noAnimations: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * Set to true to disable automatically closing the dropdown after
+ * a selection has been made.
+ */
+ ignoreSelect: {
+ type: Boolean,
+ value: false
+ },
+
+ /**
+ * An animation config. If provided, this will be used to animate the
+ * opening of the dropdown.
+ */
+ openAnimationConfig: {
+ type: Object,
+ value: function() {
+ return [{
+ name: 'fade-in-animation',
+ timing: {
+ delay: 100,
+ duration: 200
+ }
+ }, {
+ name: 'paper-menu-grow-width-animation',
+ timing: {
+ delay: 100,
+ duration: 150,
+ easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER
+ }
+ }, {
+ name: 'paper-menu-grow-height-animation',
+ timing: {
+ delay: 100,
+ duration: 275,
+ easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER
+ }
+ }];
+ }
+ },
+
+ /**
+ * An animation config. If provided, this will be used to animate the
+ * closing of the dropdown.
+ */
+ closeAnimationConfig: {
+ type: Object,
+ value: function() {
+ return [{
+ name: 'fade-out-animation',
+ timing: {
+ duration: 150
+ }
+ }, {
+ name: 'paper-menu-shrink-width-animation',
+ timing: {
+ delay: 100,
+ duration: 50,
+ easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER
+ }
+ }, {
+ name: 'paper-menu-shrink-height-animation',
+ timing: {
+ duration: 200,
+ easing: 'ease-in'
+ }
+ }];
+ }
+ },
+
+ /**
+ * This is the element intended to be bound as the focus target
+ * for the `iron-dropdown` contained by `paper-menu-button`.
+ */
+ _dropdownContent: {
+ type: Object
+ }
},
- /**
- * The orientation against which to align the menu dropdown
- * horizontally relative to the dropdown trigger.
- */
- horizontalAlign: {
- type: String,
- value: 'left',
- reflectToAttribute: true
+ hostAttributes: {
+ role: 'group',
+ 'aria-haspopup': 'true'
},
- /**
- * The orientation against which to align the menu dropdown
- * vertically relative to the dropdown trigger.
- */
- verticalAlign: {
- type: String,
- value: 'top',
- reflectToAttribute: true
+ listeners: {
+ 'iron-select': '_onIronSelect'
},
/**
- * A pixel value that will be added to the position calculated for the
- * given `horizontalAlign`. Use a negative value to offset to the
- * left, or a positive value to offset to the right.
+ * The content element that is contained by the menu button, if any.
*/
- horizontalOffset: {
- type: Number,
- value: 0,
- notify: true
+ get contentElement() {
+ return Polymer.dom(this.$.content).getDistributedNodes()[0];
},
/**
- * A pixel value that will be added to the position calculated for the
- * given `verticalAlign`. Use a negative value to offset towards the
- * top, or a positive value to offset towards the bottom.
+ * Toggles the drowpdown content between opened and closed.
*/
- verticalOffset: {
- type: Number,
- value: 0,
- notify: true
+ toggle: function() {
+ if (this.opened) {
+ this.close();
+ } else {
+ this.open();
+ }
},
/**
- * Set to true to disable animations when opening and closing the
- * dropdown.
+ * Make the dropdown content appear as an overlay positioned relative
+ * to the dropdown trigger.
*/
- noAnimations: {
- type: Boolean,
- value: false
+ open: function() {
+ if (this.disabled) {
+ return;
+ }
+
+ this.$.dropdown.open();
},
/**
- * Set to true to disable automatically closing the dropdown after
- * a selection has been made.
+ * Hide the dropdown content.
*/
- ignoreSelect: {
- type: Boolean,
- value: false
+ close: function() {
+ this.$.dropdown.close();
},
/**
- * An animation config. If provided, this will be used to animate the
- * opening of the dropdown.
+ * When an `iron-select` event is received, the dropdown should
+ * automatically close on the assumption that a value has been chosen.
+ *
+ * @param {CustomEvent} event A CustomEvent instance with type
+ * set to `"iron-select"`.
*/
- openAnimationConfig: {
- type: Object,
- value: function() {
- return [{
- name: 'fade-in-animation',
- timing: {
- delay: 100,
- duration: 200
- }
- }, {
- name: 'paper-menu-grow-width-animation',
- timing: {
- delay: 100,
- duration: 150,
- easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER
- }
- }, {
- name: 'paper-menu-grow-height-animation',
- timing: {
- delay: 100,
- duration: 275,
- easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER
- }
- }];
+ _onIronSelect: function(event) {
+ if (!this.ignoreSelect) {
+ this.close();
}
},
/**
- * An animation config. If provided, this will be used to animate the
- * closing of the dropdown.
+ * When the dropdown opens, the `paper-menu-button` fires `paper-open`.
+ * When the dropdown closes, the `paper-menu-button` fires `paper-close`.
+ *
+ * @param {boolean} opened True if the dropdown is opened, otherwise false.
+ * @param {boolean} oldOpened The previous value of `opened`.
*/
- closeAnimationConfig: {
- type: Object,
- value: function() {
- return [{
- name: 'fade-out-animation',
- timing: {
- duration: 150
- }
- }, {
- name: 'paper-menu-shrink-width-animation',
- timing: {
- delay: 100,
- duration: 50,
- easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER
- }
- }, {
- name: 'paper-menu-shrink-height-animation',
- timing: {
- duration: 200,
- easing: 'ease-in'
- }
- }];
+ _openedChanged: function(opened, oldOpened) {
+ if (opened) {
+ // TODO(cdata): Update this when we can measure changes in distributed
+ // children in an idiomatic way.
+ // We poke this property in case the element has changed. This will
+ // cause the focus target for the `iron-dropdown` to be updated as
+ // necessary:
+ this._dropdownContent = this.contentElement;
+ this.fire('paper-dropdown-open');
+ } else if (oldOpened != null) {
+ this.fire('paper-dropdown-close');
}
},
/**
- * This is the element intended to be bound as the focus target
- * for the `iron-dropdown` contained by `paper-menu-button`.
+ * If the dropdown is open when disabled becomes true, close the
+ * dropdown.
+ *
+ * @param {boolean} disabled True if disabled, otherwise false.
*/
- _dropdownContent: {
- type: Object
- }
- },
-
- hostAttributes: {
- role: 'group',
- 'aria-haspopup': 'true'
- },
-
- listeners: {
- 'iron-select': '_onIronSelect'
- },
-
- /**
- * The content element that is contained by the menu button, if any.
- */
- get contentElement() {
- return Polymer.dom(this.$.content).getDistributedNodes()[0];
- },
-
- /**
- * Make the dropdown content appear as an overlay positioned relative
- * to the dropdown trigger.
- */
- open: function() {
- if (this.disabled) {
- return;
- }
-
- this.$.dropdown.open();
- },
-
- /**
- * Hide the dropdown content.
- */
- close: function() {
- this.$.dropdown.close();
- },
-
- /**
- * When an `iron-select` event is received, the dropdown should
- * automatically close on the assumption that a value has been chosen.
- *
- * @param {CustomEvent} event A CustomEvent instance with type
- * set to `"iron-select"`.
- */
- _onIronSelect: function(event) {
- if (!this.ignoreSelect) {
- this.close();
- }
- },
+ _disabledChanged: function(disabled) {
+ Polymer.IronControlState._disabledChanged.apply(this, arguments);
+ if (disabled && this.opened) {
+ this.close();
+ }
+ },
- /**
- * When the dropdown opens, the `paper-menu-button` fires `paper-open`.
- * When the dropdown closes, the `paper-menu-button` fires `paper-close`.
- *
- * @param {boolean} opened True if the dropdown is opened, otherwise false.
- * @param {boolean} oldOpened The previous value of `opened`.
- */
- _openedChanged: function(opened, oldOpened) {
- if (opened) {
- // TODO(cdata): Update this when we can measure changes in distributed
- // children in an idiomatic way.
- // We poke this property in case the element has changed. This will
- // cause the focus target for the `iron-dropdown` to be updated as
- // necessary:
- this._dropdownContent = this.contentElement;
- this.fire('paper-dropdown-open');
- } else if (oldOpened != null) {
- this.fire('paper-dropdown-close');
- }
- },
+ __onIronOverlayCanceled: function(event) {
+ var uiEvent = event.detail;
+ var target = Polymer.dom(uiEvent).rootTarget;
+ var trigger = this.$.trigger;
+ var path = Polymer.dom(uiEvent).path;
- /**
- * If the dropdown is open when disabled becomes true, close the
- * dropdown.
- *
- * @param {boolean} disabled True if disabled, otherwise false.
- */
- _disabledChanged: function(disabled) {
- Polymer.IronControlState._disabledChanged.apply(this, arguments);
- if (disabled && this.opened) {
- this.close();
+ if (path.indexOf(trigger) > -1) {
+ event.preventDefault();
+ }
}
- }
- });
+ });
- PaperMenuButton.ANIMATION_CUBIC_BEZIER = 'cubic-bezier(.3,.95,.5,1)';
- PaperMenuButton.MAX_ANIMATION_TIME_MS = 400;
+ PaperMenuButton.ANIMATION_CUBIC_BEZIER = 'cubic-bezier(.3,.95,.5,1)';
+ PaperMenuButton.MAX_ANIMATION_TIME_MS = 400;
- Polymer.PaperMenuButton = PaperMenuButton;
- })();
+ Polymer.PaperMenuButton = PaperMenuButton;
+ })();
Polymer({
is: 'paper-icon-button',
@@ -9821,7 +10328,73 @@ Polymer({
}
}
});
+(function() {
+ 'use strict';
+
+ Polymer.IronA11yAnnouncer = Polymer({
+ is: 'iron-a11y-announcer',
+
+ properties: {
+
+ /**
+ * The value of mode is used to set the `aria-live` attribute
+ * for the element that will be announced. Valid values are: `off`,
+ * `polite` and `assertive`.
+ */
+ mode: {
+ type: String,
+ value: 'polite'
+ },
+
+ _text: {
+ type: String,
+ value: ''
+ }
+ },
+
+ created: function() {
+ if (!Polymer.IronA11yAnnouncer.instance) {
+ Polymer.IronA11yAnnouncer.instance = this;
+ }
+
+ document.body.addEventListener('iron-announce', this._onIronAnnounce.bind(this));
+ },
+
+ /**
+ * Cause a text string to be announced by screen readers.
+ *
+ * @param {string} text The text that should be announced.
+ */
+ announce: function(text) {
+ this._text = '';
+ this.async(function() {
+ this._text = text;
+ }, 100);
+ },
+
+ _onIronAnnounce: function(event) {
+ if (event.detail && event.detail.text) {
+ this.announce(event.detail.text);
+ }
+ }
+ });
+
+ Polymer.IronA11yAnnouncer.instance = null;
+
+ Polymer.IronA11yAnnouncer.requestAvailability = function() {
+ if (!Polymer.IronA11yAnnouncer.instance) {
+ Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y-announcer');
+ }
+
+ document.body.appendChild(Polymer.IronA11yAnnouncer.instance);
+ };
+ })();
/**
+ * Singleton IronMeta instance.
+ */
+ Polymer.IronValidatableBehaviorMeta = null;
+
+ /**
* `Use Polymer.IronValidatableBehavior` to implement an element that validates user input.
* Use the related `Polymer.IronValidatorBehavior` to add custom validation logic to an iron-input.
*
@@ -9850,14 +10423,6 @@ Polymer({
properties: {
/**
- * Namespace for this validator.
- */
- validatorType: {
- type: String,
- value: 'validator'
- },
-
- /**
* Name of the validator to use.
*/
validator: {
@@ -9874,22 +10439,36 @@ Polymer({
value: false
},
+ /**
+ * This property is deprecated and should not be used. Use the global
+ * validator meta singleton, `Polymer.IronValidatableBehaviorMeta` instead.
+ */
_validatorMeta: {
type: Object
- }
+ },
+
+ /**
+ * Namespace for this validator. This property is deprecated and should
+ * not be used. For all intents and purposes, please consider it a
+ * read-only, config-time property.
+ */
+ validatorType: {
+ type: String,
+ value: 'validator'
+ },
+ _validator: {
+ type: Object,
+ computed: '__computeValidator(validator)'
+ }
},
observers: [
'_invalidChanged(invalid)'
],
- get _validator() {
- return this._validatorMeta && this._validatorMeta.byKey(this.validator);
- },
-
- ready: function() {
- this._validatorMeta = new Polymer.IronMeta({type: this.validatorType});
+ registered: function() {
+ Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({type: 'validator'});
},
_invalidChanged: function() {
@@ -9936,6 +10515,11 @@ Polymer({
return this._validator.validate(value);
}
return true;
+ },
+
+ __computeValidator: function() {
+ return Polymer.IronValidatableBehaviorMeta &&
+ Polymer.IronValidatableBehaviorMeta.byKey(this.validator);
}
};
/*
@@ -9993,18 +10577,22 @@ is separate from validation, and `allowed-pattern` does not affect how the input
},
/**
- * Set to true to prevent the user from entering invalid input. The new input characters are
- * matched with `allowedPattern` if it is set, otherwise it will use the `type` attribute (only
- * supported for `type=number`).
+ * Set to true to prevent the user from entering invalid input. If `allowedPattern` is set,
+ * any character typed by the user will be matched against that pattern, and rejected if it's not a match.
+ * Pasted input will have each character checked individually; if any character
+ * doesn't match `allowedPattern`, the entire pasted string will be rejected.
+ * If `allowedPattern` is not set, it will use the `type` attribute (only supported for `type=number`).
*/
preventInvalidInput: {
type: Boolean
},
/**
- * Regular expression expressing a set of characters to enforce the validity of input characters.
- * The recommended value should follow this format: `[a-ZA-Z0-9.+-!;:]` that list the characters
- * allowed as input.
+ * Regular expression that list the characters allowed as input.
+ * This pattern represents the allowed characters for the field; as the user inputs text,
+ * each individual character will be checked against the pattern (rather than checking
+ * the entire value as a whole). The recommended format should be a list of allowed characters;
+ * for example, `[a-zA-Z0-9.+-!;:]`
*/
allowedPattern: {
type: String,
@@ -10028,6 +10616,47 @@ is separate from validation, and `allowed-pattern` does not affect how the input
'keypress': '_onKeypress'
},
+ /** @suppress {checkTypes} */
+ registered: function() {
+ // Feature detect whether we need to patch dispatchEvent (i.e. on FF and IE).
+ if (!this._canDispatchEventOnDisabled()) {
+ this._origDispatchEvent = this.dispatchEvent;
+ this.dispatchEvent = this._dispatchEventFirefoxIE;
+ }
+ },
+
+ created: function() {
+ Polymer.IronA11yAnnouncer.requestAvailability();
+ },
+
+ _canDispatchEventOnDisabled: function() {
+ var input = document.createElement('input');
+ var canDispatch = false;
+ input.disabled = true;
+
+ input.addEventListener('feature-check-dispatch-event', function() {
+ canDispatch = true;
+ });
+
+ try {
+ input.dispatchEvent(new Event('feature-check-dispatch-event'));
+ } catch(e) {}
+
+ return canDispatch;
+ },
+
+ _dispatchEventFirefoxIE: function() {
+ // Due to Firefox bug, events fired on disabled form controls can throw
+ // errors; furthermore, neither IE nor Firefox will actually dispatch
+ // events from disabled form controls; as such, we toggle disable around
+ // the dispatch to allow notifying properties to notify
+ // See issue #47 for details
+ var disabled = this.disabled;
+ this.disabled = false;
+ this._origDispatchEvent.apply(this, arguments);
+ this.disabled = disabled;
+ },
+
get _patternRegExp() {
var pattern;
if (this.allowedPattern) {
@@ -10068,6 +10697,7 @@ is separate from validation, and `allowed-pattern` does not affect how the input
if (this.preventInvalidInput && !this._patternAlreadyChecked) {
var valid = this._checkPatternValidity();
if (!valid) {
+ this._announceInvalidCharacter('Invalid string of characters not entered.');
this.value = this._previousValidInput;
}
}
@@ -10128,6 +10758,7 @@ is separate from validation, and `allowed-pattern` does not affect how the input
var thisChar = String.fromCharCode(event.charCode);
if (this._isPrintable(event) && !regexp.test(thisChar)) {
event.preventDefault();
+ this._announceInvalidCharacter('Invalid character ' + thisChar + ' not entered.');
}
},
@@ -10150,23 +10781,29 @@ is separate from validation, and `allowed-pattern` does not affect how the input
* @return {boolean} True if the value is valid.
*/
validate: function() {
- // Empty, non-required input is valid.
- if (!this.required && this.value == '') {
- this.invalid = false;
- return true;
- }
+ // First, check what the browser thinks. Some inputs (like type=number)
+ // behave weirdly and will set the value to "" if something invalid is
+ // entered, but will set the validity correctly.
+ var valid = this.checkValidity();
- var valid;
- if (this.hasValidator()) {
- valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
- } else {
- valid = this.checkValidity();
- this.invalid = !valid;
+ // Only do extra checking if the browser thought this was valid.
+ if (valid) {
+ // Empty, required input is invalid
+ if (this.required && this.value === '') {
+ valid = false;
+ } else if (this.hasValidator()) {
+ valid = Polymer.IronValidatableBehavior.validate.call(this, this.value);
+ }
}
+
+ this.invalid = !valid;
this.fire('iron-input-validate');
return valid;
- }
+ },
+ _announceInvalidCharacter: function(message) {
+ this.fire('iron-announce', { text: message });
+ }
});
/*
@@ -10303,14 +10940,15 @@ Polymer({
}
this.addEventListener('focus', this._boundOnFocus, true);
this.addEventListener('blur', this._boundOnBlur, true);
+ },
+
+ attached: function() {
if (this.attrForValue) {
this._inputElement.addEventListener(this._valueChangedEvent, this._boundValueChanged);
} else {
this.addEventListener('input', this._onInput);
}
- },
- attached: function() {
// Only validate when attached if the input already has a value.
if (this._inputElementValue != '') {
this._handleValueAndAutoValidate(this._inputElement);
@@ -10857,13 +11495,6 @@ cr.define('downloads', function() {
return {Manager: Manager};
});
-// 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 src="../../../../ui/webui/resources/js/i18n_template_no_process.js">
-
-i18nTemplate.process(document, loadTimeData);
// 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.
diff --git a/chromium/chrome/browser/resources/md_downloads/downloads.html b/chromium/chrome/browser/resources/md_downloads/downloads.html
index 81e86789528..48e88a903bb 100644
--- a/chromium/chrome/browser/resources/md_downloads/downloads.html
+++ b/chromium/chrome/browser/resources/md_downloads/downloads.html
@@ -1,12 +1,13 @@
<!doctype html>
-<html i18n-values="dir:textdirection;lang:language">
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
- <title i18n-content="title"></title>
+ <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: rgb(236, 239, 241);
+ background: var(--md-background-color);
}
html,
@@ -34,10 +35,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://downloads/i18n_setup.html">
<link rel="import" href="chrome://downloads/manager.html">
- <!-- i18n_template.html actually does i18n-* attribute substitutions.
- It should be imported last and only once. TODO(dbeam): figure out a good
- solution for each individual element to do this as well. -->
- <link rel="import" href="chrome://resources/html/i18n_template.html">
<script src="chrome://downloads/downloads.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/md_downloads/icons.html b/chromium/chrome/browser/resources/md_downloads/icons.html
new file mode 100644
index 00000000000..f30021694be
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_downloads/icons.html
@@ -0,0 +1,14 @@
+<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 name="downloads" size="24">
+ <svg>
+ <defs>
+ <!--
+ 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="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z"></path></g>
+ </defs>
+ </svg>
+</iron-iconset-svg>
diff --git a/chromium/chrome/browser/resources/md_downloads/item.css b/chromium/chrome/browser/resources/md_downloads/item.css
index 41cc3cb4c8c..7a593c33b01 100644
--- a/chromium/chrome/browser/resources/md_downloads/item.css
+++ b/chromium/chrome/browser/resources/md_downloads/item.css
@@ -89,11 +89,11 @@
width: 32px;
}
-#danger-icon[icon='warning'] {
+#danger-icon[icon='cr:warning'] {
color: rgb(255, 193, 7);
}
-#danger-icon[icon='remove-circle'] {
+#danger-icon[icon='downloads:remove-circle'] {
color: rgb(244, 67, 54);
}
diff --git a/chromium/chrome/browser/resources/md_downloads/item.html b/chromium/chrome/browser/resources/md_downloads/item.html
index e9f2c8315c6..fe4e82c3aa0 100644
--- a/chromium/chrome/browser/resources/md_downloads/item.html
+++ b/chromium/chrome/browser/resources/md_downloads/item.html
@@ -2,13 +2,13 @@
<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-icon/iron-icon.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-behaviors/paper-inky-focus-behavior.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-progress/paper-progress.html">
<link rel="import" href="chrome://downloads/action_service.html">
<link rel="import" href="chrome://downloads/constants.html">
<link rel="import" href="chrome://downloads/i18n_setup.html">
+<link rel="import" href="chrome://downloads/icons.html">
<dom-module id="inky-text-button">
<template><content></content></template>
@@ -49,7 +49,7 @@
<span id="tag">[[computeTag_(data.state, data.last_reason_text, data.file_externally_removed)]]</span>
</div>
- <a id="url" target="_blank" href="[[data.url]]">[[data.url]]</a>
+ <a id="url" target="_blank">[[data.url]]</a>
<div id="description">[[computeDescription_(data.state, data.danger_type, data.file_name, data.progress_status_text)]]</div>
@@ -60,23 +60,27 @@
</template>
<div id="safe" class="controls" hidden="[[isDangerous_]]">
- <a is="action-link" id="show" i18n-content="controlShowInFolder"
- on-tap="onShowTap_" hidden="[[!completelyOnDisk_]]"></a>
+ <a is="action-link" id="show" on-tap="onShowTap_"
+ hidden="[[!completelyOnDisk_]]">$i18n{controlShowInFolder}</a>
<template is="dom-if" if="[[data.retry]]">
- <paper-button id="retry"
- on-tap="onRetryTap_">[[i18n_.retry]]</paper-button>
+ <paper-button id="retry" on-tap="onRetryTap_">
+ $i18n{controlRetry}
+ </paper-button>
</template>
<template is="dom-if" if="[[isInProgress_]]">
- <paper-button id="pause"
- on-tap="onPauseTap_">[[i18n_.pause]]</paper-button>
+ <paper-button id="pause" on-tap="onPauseTap_">
+ $i18n{controlPause}
+ </paper-button>
</template>
<template is="dom-if" if="[[data.resume]]">
- <paper-button id="resume"
- on-tap="onResumeTap_">[[i18n_.resume]]</paper-button>
+ <paper-button id="resume" on-tap="onResumeTap_">
+ $i18n{controlResume}
+ </paper-button>
</template>
<template is="dom-if" if="[[showCancel_]]">
- <paper-button id="cancel"
- on-tap="onCancelTap_">[[i18n_.cancel]]</paper-button>
+ <paper-button id="cancel" on-tap="onCancelTap_">
+ $i18n{controlCancel}
+ </paper-button>
</template>
<span id="controlled-by"><!-- Text populated dynamically. --></span>
</div>
@@ -86,30 +90,30 @@
<!-- Dangerous file types (e.g. .exe, .jar). -->
<template is="dom-if" if="[[!isMalware_]]">
<paper-button id="discard" on-tap="onDiscardDangerousTap_"
- class="discard">[[i18n_.discard]]</paper-button>
+ class="discard">$i18n{dangerDiscard}</paper-button>
<paper-button id="save" on-tap="onSaveDangerousTap_"
- class="keep">[[i18n_.save]]</paper-button>
+ class="keep">$i18n{dangerSave}</paper-button>
</template>
<!-- Things that safe browsing has determined to be dangerous. -->
<template is="dom-if" if="[[isMalware_]]">
<paper-button id="danger-remove" on-tap="onDiscardDangerousTap_"
- class="discard">[[i18n_.remove]]</paper-button>
+ class="discard">$i18n{controlRemoveFromList}</paper-button>
<paper-button id="restore" on-tap="onSaveDangerousTap_"
- class="keep">[[i18n_.restore]]</paper-button>
+ class="keep">$i18n{dangerRestore}</paper-button>
</template>
</div>
</template>
</div>
<div id="remove-wrapper" class="icon-wrapper">
- <inky-text-button id="remove" i18n-values="title:controlRemoveFromList"
+ <inky-text-button id="remove" title="$i18n{controlRemoveFromList}"
style$="[[computeRemoveStyle_(isDangerous_, showCancel_)]]"
on-tap="onRemoveTap_">&#x2715;</inky-text-button>
</div>
- <div id="incognito" i18n-values="title:inIncognito"
- hidden="[[!data.otr]]"></div>
+ <div id="incognito" title="$i18n{inIncognito}" hidden="[[!data.otr]]">
+ </div>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/md_downloads/item.js b/chromium/chrome/browser/resources/md_downloads/item.js
index 2838b0c82f1..5ef4430a1e0 100644
--- a/chromium/chrome/browser/resources/md_downloads/item.js
+++ b/chromium/chrome/browser/resources/md_downloads/item.js
@@ -37,23 +37,6 @@ cr.define('downloads', function() {
value: '',
},
- i18n_: {
- readOnly: true,
- type: Object,
- value: function() {
- return {
- cancel: loadTimeData.getString('controlCancel'),
- discard: loadTimeData.getString('dangerDiscard'),
- pause: loadTimeData.getString('controlPause'),
- remove: loadTimeData.getString('controlRemoveFromList'),
- resume: loadTimeData.getString('controlResume'),
- restore: loadTimeData.getString('dangerRestore'),
- retry: loadTimeData.getString('controlRetry'),
- save: loadTimeData.getString('dangerSave'),
- };
- },
- },
-
isActive_: {
computed: 'computeIsActive_(' +
'data.state, data.file_externally_removed)',
@@ -96,7 +79,7 @@ cr.define('downloads', function() {
// TODO(dbeam): this gets called way more when I observe data.by_ext_id
// and data.by_ext_name directly. Why?
'observeControlledBy_(controlledBy_)',
- 'observeIsDangerous_(isDangerous_, data.file_path)',
+ 'observeIsDangerous_(isDangerous_, data)',
],
ready: function() {
@@ -146,9 +129,9 @@ cr.define('downloads', function() {
case downloads.DangerType.DANGEROUS_URL:
case downloads.DangerType.POTENTIALLY_UNWANTED:
case downloads.DangerType.UNCOMMON_CONTENT:
- return 'remove-circle';
+ return 'downloads:remove-circle';
default:
- return 'warning';
+ return 'cr:warning';
}
},
@@ -263,7 +246,13 @@ cr.define('downloads', function() {
/** @private */
observeIsDangerous_: function() {
- if (this.data && !this.isDangerous_) {
+ if (!this.data)
+ return;
+
+ if (this.isDangerous_) {
+ this.$.url.removeAttribute('href');
+ } else {
+ this.$.url.href = assert(this.data.url);
var filePath = encodeURIComponent(this.data.file_path);
var scaleFactor = '?scale=' + window.devicePixelRatio + 'x';
this.$['file-icon'].src = 'chrome://fileicon/' + filePath + scaleFactor;
diff --git a/chromium/chrome/browser/resources/md_downloads/manager.html b/chromium/chrome/browser/resources/md_downloads/manager.html
index 9aae9aca342..c6071e5ea4c 100644
--- a/chromium/chrome/browser/resources/md_downloads/manager.html
+++ b/chromium/chrome/browser/resources/md_downloads/manager.html
@@ -9,9 +9,15 @@
<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>
+ <style no-process>
+ #toolbar {
+ background: var(--md-toolbar-color);
+ }
+ </style>
<downloads-toolbar id="toolbar"></downloads-toolbar>
<iron-list id="downloads-list" items="{{items_}}"
hidden="[[!hasDownloads_]]">
diff --git a/chromium/chrome/browser/resources/md_downloads/toolbar.css b/chromium/chrome/browser/resources/md_downloads/toolbar.css
index 3e8d151af5e..0437ef8951f 100644
--- a/chromium/chrome/browser/resources/md_downloads/toolbar.css
+++ b/chromium/chrome/browser/resources/md_downloads/toolbar.css
@@ -4,7 +4,7 @@
:host {
align-items: center;
- background: rgb(52, 73, 94);
+ background: var(--md-toolbar-color);
color: white;
content-sizing: padding-box;
display: flex;
diff --git a/chromium/chrome/browser/resources/md_downloads/toolbar.html b/chromium/chrome/browser/resources/md_downloads/toolbar.html
index fcb005be1e2..0d69c45d548 100644
--- a/chromium/chrome/browser/resources/md_downloads/toolbar.html
+++ b/chromium/chrome/browser/resources/md_downloads/toolbar.html
@@ -2,37 +2,40 @@
<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/util.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-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-menu-button/paper-menu-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/cr_elements/cr_search_field/cr_search_field.html">
-<link rel="import" href="chrome://downloads/i18n_setup.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<dom-module id="downloads-toolbar">
<template>
<div id="title">
- <h1 i18n-content="title"></h1>
+ <h1>$i18n{title}</h1>
</div>
<div id="actions">
- <paper-button class="clear-all" i18n-content="clearAll"
- on-tap="onClearAllTap_"></paper-button>
- <paper-button i18n-content="openDownloadsFolder"
- on-tap="onOpenDownloadsFolderTap_"></paper-button>
+ <paper-button class="clear-all" on-tap="onClearAllTap_">
+ $i18n{clearAll}
+ </paper-button>
+ <paper-button on-tap="onOpenDownloadsFolderTap_">
+ $i18n{openDownloadsFolder}
+ </paper-button>
</div>
<div id="search">
- <cr-search-field id="search-input"
- i18n-values="label:search;clear-label:clearSearch"></cr-search-field>
+ <cr-search-field id="search-input" label="$i18n{search}"
+ clear-label="$i18n{clearSearch}"></cr-search-field>
<paper-menu-button id="more" horizontal-align="[[overflowAlign_]]">
- <paper-icon-button icon="more-vert" i18n-values="title:moreActions"
+ <paper-icon-button icon="cr:more-vert" title="$i18n{moreActions}"
class="dropdown-trigger"></paper-icon-button>
<paper-menu class="dropdown-content">
- <paper-item class="clear-all" i18n-content="clearAll"
- on-tap="onClearAllTap_"></paper-item>
- <paper-item i18n-content="openDownloadsFolder"
- on-tap="onOpenDownloadsFolderTap_"></paper-item>
+ <paper-item class="clear-all" on-tap="onClearAllTap_">
+ $i18n{clearAll}
+ </paper-item>
+ <paper-item on-tap="onOpenDownloadsFolderTap_">
+ $i18n{openDownloadsFolder}
+ </paper-item>
</paper-menu>
</paper-menu-button>
</div>
diff --git a/chromium/chrome/browser/resources/md_downloads/vulcanized.html b/chromium/chrome/browser/resources/md_downloads/vulcanized.html
index 0cee1fff399..a4494aec6aa 100644
--- a/chromium/chrome/browser/resources/md_downloads/vulcanized.html
+++ b/chromium/chrome/browser/resources/md_downloads/vulcanized.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html><html i18n-values="dir:textdirection;lang:language"><head><!--
+<!DOCTYPE html><html dir="$i18n{textdirection}" lang="$i18n{language}"><head><!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
@@ -16,11 +16,24 @@ Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<meta charset="utf-8">
- <title i18n-content="title"></title>
+ <title>$i18n{title}</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<style>
+/* 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. */
+
+:root {
+ /* These are custom, Chrome-specific colors that don't have --paper or
+ * --google equivalents. Blame bettes@. http://crbug.com/598451 */
+ --md-background-color: rgb(236, 239, 241);
+ --md-toolbar-color: rgb(52, 73, 94);
+}
+
+</style>
+ <style>
html {
- background: rgb(236, 239, 241);
+ background: var(--md-background-color);
}
html,
@@ -55,9 +68,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
position: relative;
}
- #items > ::content > * {
+ :host(:not([grid])) #items > ::content > * {
width: 100%;
+ };
+
+ #items > ::content > * {
box-sizing: border-box;
+ margin: 0;
position: absolute;
top: 0;
will-change: transform;
@@ -246,6 +263,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
align-items: flex-end;
};
+ --layout-baseline: {
+ -ms-flex-align: baseline;
+ -webkit-align-items: baseline;
+ align-items: baseline;
+ };
+
/* alignment in main axis */
--layout-start-justified: {
@@ -309,6 +332,49 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
align-self: stretch;
};
+ --layout-self-baseline: {
+ -ms-align-self: baseline;
+ -webkit-align-self: baseline;
+ align-self: baseline;
+ };
+
+ /* multi-line alignment in main axis */
+
+ --layout-start-aligned: {
+ -ms-flex-line-pack: start; /* IE10 */
+ -ms-align-content: flex-start;
+ -webkit-align-content: flex-start;
+ align-content: flex-start;
+ };
+
+ --layout-end-aligned: {
+ -ms-flex-line-pack: end; /* IE10 */
+ -ms-align-content: flex-end;
+ -webkit-align-content: flex-end;
+ align-content: flex-end;
+ };
+
+ --layout-center-aligned: {
+ -ms-flex-line-pack: center; /* IE10 */
+ -ms-align-content: center;
+ -webkit-align-content: center;
+ align-content: center;
+ };
+
+ --layout-between-aligned: {
+ -ms-flex-line-pack: justify; /* IE10 */
+ -ms-align-content: space-between;
+ -webkit-align-content: space-between;
+ align-content: space-between;
+ };
+
+ --layout-around-aligned: {
+ -ms-flex-line-pack: distribute; /* IE10 */
+ -ms-align-content: space-around;
+ -webkit-align-content: space-around;
+ align-content: space-around;
+ };
+
/*******************************
Other Layout
*******************************/
@@ -400,309 +466,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</template>
</dom-module>
-<iron-iconset-svg name="icons" size="24">
-<svg><defs>
-<g id="3d-rotation"><path d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32zm.89-6.52c-.19 0-.37-.03-.52-.08-.16-.06-.29-.13-.4-.24-.11-.1-.2-.22-.26-.37-.06-.14-.09-.3-.09-.47h-1.3c0 .36.07.68.21.95.14.27.33.5.56.69.24.18.51.32.82.41.3.1.62.15.96.15.37 0 .72-.05 1.03-.15.32-.1.6-.25.83-.44s.42-.43.55-.72c.13-.29.2-.61.2-.97 0-.19-.02-.38-.07-.56-.05-.18-.12-.35-.23-.51-.1-.16-.24-.3-.4-.43-.17-.13-.37-.23-.61-.31.2-.09.37-.2.52-.33.15-.13.27-.27.37-.42.1-.15.17-.3.22-.46.05-.16.07-.32.07-.48 0-.36-.06-.68-.18-.96-.12-.28-.29-.51-.51-.69-.2-.19-.47-.33-.77-.43C9.1 8.05 8.76 8 8.39 8c-.36 0-.69.05-1 .16-.3.11-.57.26-.79.45-.21.19-.38.41-.51.67-.12.26-.18.54-.18.85h1.3c0-.17.03-.32.09-.45s.14-.25.25-.34c.11-.09.23-.17.38-.22.15-.05.3-.08.48-.08.4 0 .7.1.89.31.19.2.29.49.29.86 0 .18-.03.34-.08.49-.05.15-.14.27-.25.37-.11.1-.25.18-.41.24-.16.06-.36.09-.58.09H7.5v1.03h.77c.22 0 .42.02.6.07s.33.13.45.23c.12.11.22.24.29.4.07.16.1.35.1.57 0 .41-.12.72-.35.93-.23.23-.55.33-.95.33zm8.55-5.92c-.32-.33-.7-.59-1.14-.77-.43-.18-.92-.27-1.46-.27H12v8h2.3c.55 0 1.06-.09 1.51-.27.45-.18.84-.43 1.16-.76.32-.33.57-.73.74-1.19.17-.47.26-.99.26-1.57v-.4c0-.58-.09-1.1-.26-1.57-.18-.47-.43-.87-.75-1.2zm-.39 3.16c0 .42-.05.79-.14 1.13-.1.33-.24.62-.43.85-.19.23-.43.41-.71.53-.29.12-.62.18-.99.18h-.91V9.12h.97c.72 0 1.27.23 1.64.69.38.46.57 1.12.57 1.99v.4zM12 0l-.66.03 3.81 3.81 1.33-1.33c3.27 1.55 5.61 4.72 5.96 8.48h1.5C23.44 4.84 18.29 0 12 0z"></path></g>
-<g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"></path></g>
-<g id="accessible"><circle cx="12" cy="4" r="2"></circle><path d="M19 13v-2c-1.54.02-3.09-.75-4.07-1.83l-1.29-1.43c-.17-.19-.38-.34-.61-.45-.01 0-.01-.01-.02-.01H13c-.35-.2-.75-.3-1.19-.26C10.76 7.11 10 8.04 10 9.09V15c0 1.1.9 2 2 2h5v5h2v-5.5c0-1.1-.9-2-2-2h-3v-3.45c1.29 1.07 3.25 1.94 5 1.95zm-6.17 5c-.41 1.16-1.52 2-2.83 2-1.66 0-3-1.34-3-3 0-1.31.84-2.41 2-2.83V12.1c-2.28.46-4 2.48-4 4.9 0 2.76 2.24 5 5 5 2.42 0 4.44-1.72 4.9-4h-2.07z"></path></g>
-<g id="account-balance"><path d="M4 10v7h3v-7H4zm6 0v7h3v-7h-3zM2 22h19v-3H2v3zm14-12v7h3v-7h-3zm-4.5-9L2 6v2h19V6l-9.5-5z"></path></g>
-<g id="account-balance-wallet"><path d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2-2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm-9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path></g>
-<g id="account-box"><path d="M3 5v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2H5c-1.11 0-2 .9-2 2zm12 4c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 3 3zm-9 8c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6v-1z"></path></g>
-<g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"></path></g>
-<g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
-<g id="add-alert"><path d="M10.01 21.01c0 1.1.89 1.99 1.99 1.99s1.99-.89 1.99-1.99h-3.98zm8.87-4.19V11c0-3.25-2.25-5.97-5.29-6.69v-.72C13.59 2.71 12.88 2 12 2s-1.59.71-1.59 1.59v.72C7.37 5.03 5.12 7.75 5.12 11v5.82L3 18.94V20h18v-1.06l-2.12-2.12zM16 13.01h-3v3h-2v-3H8V11h3V8h2v3h3v2.01z"></path></g>
-<g id="add-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g>
-<g id="add-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g>
-<g id="add-circle-outline"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.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 8z"></path></g>
-<g id="add-shopping-cart"><path d="M11 9h2V6h3V4h-3V1h-2v3H8v2h3v3zm-4 9c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2zm-9.83-3.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.86-7.01L19.42 4h-.01l-1.1 2-2.76 5H8.53l-.13-.27L6.16 6l-.95-2-.94-2H1v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.13 0-.25-.11-.25-.25z"></path></g>
-<g id="alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"></path></g>
-<g id="alarm-add"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"></path></g>
-<g id="alarm-off"><path d="M12 6c3.87 0 7 3.13 7 7 0 .84-.16 1.65-.43 2.4l1.52 1.52c.58-1.19.91-2.51.91-3.92 0-4.97-4.03-9-9-9-1.41 0-2.73.33-3.92.91L9.6 6.43C10.35 6.16 11.16 6 12 6zm10-.28l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM2.92 2.29L1.65 3.57 2.98 4.9l-1.11.93 1.42 1.42 1.11-.94.8.8C3.83 8.69 3 10.75 3 13c0 4.97 4.02 9 9 9 2.25 0 4.31-.83 5.89-2.2l2.2 2.2 1.27-1.27L3.89 3.27l-.97-.98zm13.55 16.1C15.26 19.39 13.7 20 12 20c-3.87 0-7-3.13-7-7 0-1.7.61-3.26 1.61-4.47l9.86 9.86zM8.02 3.28L6.6 1.86l-.86.71 1.42 1.42.86-.71z"></path></g>
-<g id="alarm-on"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm-1.46-5.47L8.41 12.4l-1.06 1.06 3.18 3.18 6-6-1.06-1.06-4.93 4.95z"></path></g>
-<g id="all-out"><path d="M16.21 4.16l4 4v-4zm4 12l-4 4h4zm-12 4l-4-4v4zm-4-12l4-4h-4zm12.95-.95c-2.73-2.73-7.17-2.73-9.9 0s-2.73 7.17 0 9.9 7.17 2.73 9.9 0 2.73-7.16 0-9.9zm-1.1 8.8c-2.13 2.13-5.57 2.13-7.7 0s-2.13-5.57 0-7.7 5.57-2.13 7.7 0 2.13 5.57 0 7.7z"></path></g>
-<g id="android"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"></path></g>
-<g id="announcement"><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-7 9h-2V5h2v6zm0 4h-2v-2h2v2z"></path></g>
-<g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"></path></g>
-<g id="archive"><path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z"></path></g>
-<g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g>
-<g id="arrow-downward"><path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"></path></g>
-<g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
-<g id="arrow-drop-down-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 12l-4-4h8l-4 4z"></path></g>
-<g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g>
-<g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"></path></g>
-<g id="arrow-upward"><path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"></path></g>
-<g id="aspect-ratio"><path d="M19 12h-2v3h-3v2h5v-5zM7 9h3V7H5v5h2V9zm14-6H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"></path></g>
-<g id="assessment"><path d="M19 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-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"></path></g>
-<g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-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-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"></path></g>
-<g id="assignment-ind"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-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-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 4c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1.4c0-2 4-3.1 6-3.1s6 1.1 6 3.1V19z"></path></g>
-<g id="assignment-late"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-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-6 15h-2v-2h2v2zm0-4h-2V8h2v6zm-1-9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"></path></g>
-<g id="assignment-return"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-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-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm4 12h-4v3l-5-5 5-5v3h4v4z"></path></g>
-<g id="assignment-returned"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-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-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 15l-5-5h3V9h4v4h3l-5 5z"></path></g>
-<g id="assignment-turned-in"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-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-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-2 14l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path></g>
-<g id="attachment"><path d="M2 12.5C2 9.46 4.46 7 7.5 7H18c2.21 0 4 1.79 4 4s-1.79 4-4 4H9.5C8.12 15 7 13.88 7 12.5S8.12 10 9.5 10H17v2H9.41c-.55 0-.55 1 0 1H18c1.1 0 2-.9 2-2s-.9-2-2-2H7.5C5.57 9 4 10.57 4 12.5S5.57 16 7.5 16H17v2H7.5C4.46 18 2 15.54 2 12.5z"></path></g>
-<g id="autorenew"><path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z"></path></g>
-<g id="backspace"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z"></path></g>
-<g id="backup"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g>
-<g id="block"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z"></path></g>
-<g id="book"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g>
-<g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"></path></g>
-<g id="bookmark-border"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g>
-<g id="bug-report"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"></path></g>
-<g id="build"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></g>
-<g id="cached"><path d="M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l4 4 4-4H6z"></path></g>
-<g id="camera-enhance"><path d="M9 3L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2h-3.17L15 3H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-1l1.25-2.75L16 13l-2.75-1.25L12 9l-1.25 2.75L8 13l2.75 1.25z"></path></g>
-<g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g>
-<g id="card-giftcard"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g>
-<g id="card-membership"><path d="M20 2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h4v5l4-2 4 2v-5h4c1.11 0 2-.89 2-2V4c0-1.11-.89-2-2-2zm0 13H4v-2h16v2zm0-5H4V4h16v6z"></path></g>
-<g id="card-travel"><path d="M20 6h-3V4c0-1.11-.89-2-2-2H9c-1.11 0-2 .89-2 2v2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM9 4h6v2H9V4zm11 15H4v-2h16v2zm0-5H4V8h3v2h2V8h6v2h2V8h3v6z"></path></g>
-<g id="change-history"><path d="M12 7.77L18.39 18H5.61L12 7.77M12 4L2 20h20L12 4z"></path></g>
-<g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
-<g id="check-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></g>
-<g id="check-box-outline-blank"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g>
-<g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></g>
-<g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></path></g>
-<g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
-<g id="chrome-reader-mode"><path d="M13 12h7v1.5h-7zm0-2.5h7V11h-7zm0 5h7V16h-7zM21 4H3c-1.1 0-2 .9-2 2v13c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 15h-9V6h9v13z"></path></g>
-<g id="class"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g>
-<g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
-<g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
-<g id="cloud"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"></path></g>
-<g id="cloud-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.5 14H8c-1.66 0-3-1.34-3-3s1.34-3 3-3l.14.01C8.58 8.28 10.13 7 12 7c2.21 0 4 1.79 4 4h.5c1.38 0 2.5 1.12 2.5 2.5S17.88 16 16.5 16z"></path></g>
-<g id="cloud-done"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM10 17l-3.5-3.5 1.41-1.41L10 14.17 15.18 9l1.41 1.41L10 17z"></path></g>
-<g id="cloud-download"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"></path></g>
-<g id="cloud-off"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.64-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1.73z"></path></g>
-<g id="cloud-queue"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"></path></g>
-<g id="cloud-upload"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g>
-<g id="code"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"></path></g>
-<g id="compare-arrows"><path d="M9.01 14H2v2h7.01v3L13 15l-3.99-4v3zm5.98-1v-3H22V8h-7.01V5L11 9l3.99 4z"></path></g>
-<g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"></path></g>
-<g id="content-cut"><path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"></path></g>
-<g id="content-paste"><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"></path></g>
-<g id="copyright"><path d="M10.08 10.86c.05-.33.16-.62.3-.87s.34-.46.59-.62c.24-.15.54-.22.91-.23.23.01.44.05.63.13.2.09.38.21.52.36s.25.33.34.53.13.42.14.64h1.79c-.02-.47-.11-.9-.28-1.29s-.4-.73-.7-1.01-.66-.5-1.08-.66-.88-.23-1.39-.23c-.65 0-1.22.11-1.7.34s-.88.53-1.2.92-.56.84-.71 1.36S8 11.29 8 11.87v.27c0 .58.08 1.12.23 1.64s.39.97.71 1.35.72.69 1.2.91 1.05.34 1.7.34c.47 0 .91-.08 1.32-.23s.77-.36 1.08-.63.56-.58.74-.94.29-.74.3-1.15h-1.79c-.01.21-.06.4-.15.58s-.21.33-.36.46-.32.23-.52.3c-.19.07-.39.09-.6.1-.36-.01-.66-.08-.89-.23-.25-.16-.45-.37-.59-.62s-.25-.55-.3-.88-.08-.67-.08-1v-.27c0-.35.03-.68.08-1.01zM12 2C6.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 8z"></path></g>
-<g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"></path></g>
-<g id="create-new-folder"><path d="M20 6h-8l-2-2H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-1 8h-3v3h-2v-3h-3v-2h3V9h2v3h3v2z"></path></g>
-<g id="credit-card"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path></g>
-<g id="dashboard"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"></path></g>
-<g id="date-range"><path d="M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V9h14v11z"></path></g>
-<g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path></g>
-<g id="description"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"></path></g>
-<g id="dns"><path d="M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM20 3H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g>
-<g id="done"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path></g>
-<g id="done-all"><path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L11.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41L1.83 12 .41 13.41z"></path></g>
-<g id="donut-large"><path d="M11 5.08V2c-5 .5-9 4.81-9 10s4 9.5 9 10v-3.08c-3-.48-6-3.4-6-6.92s3-6.44 6-6.92zM18.97 11H22c-.47-5-4-8.53-9-9v3.08C16 5.51 18.54 8 18.97 11zM13 18.92V22c5-.47 8.53-4 9-9h-3.03c-.43 3-2.97 5.49-5.97 5.92z"></path></g>
-<g id="donut-small"><path d="M11 9.16V2c-5 .5-9 4.79-9 10s4 9.5 9 10v-7.16c-1-.41-2-1.52-2-2.84s1-2.43 2-2.84zM14.86 11H22c-.48-4.75-4-8.53-9-9v7.16c1 .3 1.52.98 1.86 1.84zM13 14.84V22c5-.47 8.52-4.25 9-9h-7.14c-.34.86-.86 1.54-1.86 1.84z"></path></g>
-<g id="drafts"><path d="M21.99 8c0-.72-.37-1.35-.94-1.7L12 1 2.95 6.3C2.38 6.65 2 7.28 2 8v10c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2l-.01-10zM12 13L3.74 7.84 12 3l8.26 4.84L12 13z"></path></g>
-<g id="eject"><path d="M5 17h14v2H5zm7-12L5.33 15h13.34z"></path></g>
-<g id="error"><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-2h2v2zm0-4h-2V7h2v6z"></path></g>
-<g id="error-outline"><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g>
-<g id="event"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"></path></g>
-<g id="event-seat"><path d="M4 18v3h3v-3h10v3h3v-6H4zm15-8h3v3h-3zM2 10h3v3H2zm15 3H7V5c0-1.1.9-2 2-2h6c1.1 0 2 .9 2 2v8z"></path></g>
-<g id="exit-to-app"><path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g>
-<g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></path></g>
-<g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></path></g>
-<g id="explore"><path d="M12 10.9c-.61 0-1.1.49-1.1 1.1s.49 1.1 1.1 1.1c.61 0 1.1-.49 1.1-1.1s-.49-1.1-1.1-1.1zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm2.19 12.19L6 18l3.81-8.19L18 6l-3.81 8.19z"></path></g>
-<g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"></path></g>
-<g id="face"><path d="M9 11.75c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zm6 0c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zM12 2C6.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-8 0-.29.02-.58.05-.86 2.36-1.05 4.23-2.98 5.21-5.37C11.07 8.33 14.05 10 17.42 10c.78 0 1.53-.09 2.25-.26.21.71.33 1.47.33 2.26 0 4.41-3.59 8-8 8z"></path></g>
-<g id="favorite"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"></path></g>
-<g id="favorite-border"><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"></path></g>
-<g id="feedback"><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-7 12h-2v-2h2v2zm0-4h-2V6h2v4z"></path></g>
-<g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g>
-<g id="file-upload"><path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"></path></g>
-<g id="filter-list"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"></path></g>
-<g id="find-in-page"><path d="M20 19.59V8l-6-6H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c.45 0 .85-.15 1.19-.4l-4.43-4.43c-.8.52-1.74.83-2.76.83-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L20 19.59zM9 13c0 1.66 1.34 3 3 3s3-1.34 3-3-1.34-3-3-3-3 1.34-3 3z"></path></g>
-<g id="find-replace"><path d="M11 6c1.38 0 2.63.56 3.54 1.46L12 10h6V4l-2.05 2.05C14.68 4.78 12.93 4 11 4c-3.53 0-6.43 2.61-6.92 6H6.1c.46-2.28 2.48-4 4.9-4zm5.64 9.14c.66-.9 1.12-1.97 1.28-3.14H15.9c-.46 2.28-2.48 4-4.9 4-1.38 0-2.63-.56-3.54-1.46L10 12H4v6l2.05-2.05C7.32 17.22 9.07 18 11 18c1.55 0 2.98-.51 4.14-1.36L20 21.49 21.49 20l-4.85-4.86z"></path></g>
-<g id="fingerprint"><path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z"></path></g>
-<g id="flag"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"></path></g>
-<g id="flight-land"><path d="M2.5 19h19v2h-19zm7.18-5.73l4.35 1.16 5.31 1.42c.8.21 1.62-.26 1.84-1.06.21-.8-.26-1.62-1.06-1.84l-5.31-1.42-2.76-9.02L10.12 2v8.28L5.15 8.95l-.93-2.32-1.45-.39v5.17l1.6.43 5.31 1.43z"></path></g>
-<g id="flight-takeoff"><path d="M2.5 19h19v2h-19zm19.57-9.36c-.21-.8-1.04-1.28-1.84-1.06L14.92 10l-6.9-6.43-1.93.51 4.14 7.17-4.97 1.33-1.97-1.54-1.45.39 1.82 3.16.77 1.33 1.6-.43 5.31-1.42 4.35-1.16L21 11.49c.81-.23 1.28-1.05 1.07-1.85z"></path></g>
-<g id="flip-to-back"><path d="M9 7H7v2h2V7zm0 4H7v2h2v-2zm0-8c-1.11 0-2 .9-2 2h2V3zm4 12h-2v2h2v-2zm6-12v2h2c0-1.1-.9-2-2-2zm-6 0h-2v2h2V3zM9 17v-2H7c0 1.1.89 2 2 2zm10-4h2v-2h-2v2zm0-4h2V7h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zM5 7H3v12c0 1.1.89 2 2 2h12v-2H5V7zm10-2h2V3h-2v2zm0 12h2v-2h-2v2z"></path></g>
-<g id="flip-to-front"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3c0 1.1.89 2 2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9c-1.11 0-2 .9-2 2v10c0 1.1.89 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z"></path></g>
-<g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"></path></g>
-<g id="folder-open"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path></g>
-<g id="folder-shared"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-5 3c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm4 8h-8v-1c0-1.33 2.67-2 4-2s4 .67 4 2v1z"></path></g>
-<g id="font-download"><path d="M9.93 13.5h4.14L12 7.98zM20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-4.05 16.5l-1.14-3H9.17l-1.12 3H5.96l5.11-13h1.86l5.11 13h-2.09z"></path></g>
-<g id="forward"><path d="M12 8V4l8 8-8 8v-4H4V8z"></path></g>
-<g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g>
-<g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"></path></g>
-<g id="gavel"><path d="M1 21h12v2H1zM5.245 8.07l2.83-2.827 14.14 14.142-2.828 2.828zM12.317 1l5.657 5.656-2.83 2.83-5.654-5.66zM3.825 9.485l5.657 5.657-2.828 2.828-5.657-5.657z"></path></g>
-<g id="gesture"><path d="M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H21v-2.5h-2.47c-.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-.58.73-2.06 2.48-2.29 2.72-.25.3-.68.84-1.11.84-.45 0-.72-.83-.36-1.92.35-1.09 1.4-2.86 1.85-3.52.78-1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25c-.36.36-.66.66-.88.93l1.75 1.71zm9.29 11.66c-.31 0-.74-.26-.74-.72 0-.6.73-2.2 2.87-2.76-.3 2.69-1.43 3.48-2.13 3.48z"></path></g>
-<g id="get-app"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g>
-<g id="gif"><path d="M11.5 9H13v6h-1.5zM9 9H6c-.6 0-1 .5-1 1v4c0 .5.4 1 1 1h3c.6 0 1-.5 1-1v-2H8.5v1.5h-2v-3H10V10c0-.5-.4-1-1-1zm10 1.5V9h-4.5v6H16v-2h2v-1.5h-2v-1z"></path></g>
-<g id="grade"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
-<g id="group-work"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM8 17.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5zM9.5 8c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5S9.5 9.38 9.5 8zm6.5 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"></path></g>
-<g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"></path></g>
-<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="highlight-off"><path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59 9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 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 8z"></path></g>
-<g id="history"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"></path></g>
-<g id="home"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></g>
-<g id="hourglass-empty"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6zm10 14.5V20H8v-3.5l4-4 4 4zm-4-5l-4-4V4h8v3.5l-4 4z"></path></g>
-<g id="hourglass-full"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6z"></path></g>
-<g id="http"><path d="M4.5 11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5v2zm2.5-.5h1.5V15H10v-4.5h1.5V9H7v1.5zm5.5 0H14V15h1.5v-4.5H17V9h-4.5v1.5zm9-1.5H18v6h1.5v-2h2c.8 0 1.5-.7 1.5-1.5v-1c0-.8-.7-1.5-1.5-1.5zm0 2.5h-2v-1h2v1z"></path></g>
-<g id="https"><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>
-<g id="important-devices"><path d="M23 11.01L18 11c-.55 0-1 .45-1 1v9c0 .55.45 1 1 1h5c.55 0 1-.45 1-1v-9c0-.55-.45-.99-1-.99zM23 20h-5v-7h5v7zM20 2H2C.89 2 0 2.89 0 4v12c0 1.1.89 2 2 2h7v2H7v2h8v-2h-2v-2h2v-2H2V4h18v5h2V4c0-1.11-.9-2-2-2zm-8.03 7L11 6l-.97 3H7l2.47 1.76-.94 2.91 2.47-1.8 2.47 1.8-.94-2.91L15 9h-3.03z"></path></g>
-<g id="inbox"><path d="M19 3H4.99c-1.11 0-1.98.89-1.98 2L3 19c0 1.1.88 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.11-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V5H19v10z"></path></g>
-<g id="indeterminate-check-box"><path d="M19 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-2 10H7v-2h10v2z"></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="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.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 8zM11 9h2V7h-2v2z"></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>
-<g id="invert-colors"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8.19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"></path></g>
-<g id="label"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"></path></g>
-<g id="label-outline"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"></path></g>
-<g id="language"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"></path></g>
-<g id="launch"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path></g>
-<g id="lightbulb-outline"><path d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z"></path></g>
-<g id="line-style"><path d="M3 16h5v-2H3v2zm6.5 0h5v-2h-5v2zm6.5 0h5v-2h-5v2zM3 20h2v-2H3v2zm4 0h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM3 12h8v-2H3v2zm10 0h8v-2h-8v2zM3 4v4h18V4H3z"></path></g>
-<g id="line-weight"><path d="M3 17h18v-2H3v2zm0 3h18v-1H3v1zm0-7h18v-3H3v3zm0-9v4h18V4H3z"></path></g>
-<g id="link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"></path></g>
-<g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"></path></g>
-<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>
-<g id="lock-open"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10z"></path></g>
-<g id="lock-outline"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-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-2zM8.9 6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v2H8.9V6zM18 20H6V10h12v10z"></path></g>
-<g id="loyalty"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7zm11.77 8.27L13 19.54l-4.27-4.27C8.28 14.81 8 14.19 8 13.5c0-1.38 1.12-2.5 2.5-2.5.69 0 1.32.28 1.77.74l.73.72.73-.73c.45-.45 1.08-.73 1.77-.73 1.38 0 2.5 1.12 2.5 2.5 0 .69-.28 1.32-.73 1.77z"></path></g>
-<g id="mail"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g>
-<g id="markunread"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g>
-<g id="markunread-mailbox"><path d="M20 6H10v6H8V4h6V0H6v6H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"></path></g>
-<g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g>
-<g id="more-horiz"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></g>
-<g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></g>
-<g id="motorcycle"><path d="M19.44 9.03L15.41 5H11v2h3.59l2 2H5c-2.8 0-5 2.2-5 5s2.2 5 5 5c2.46 0 4.45-1.69 4.9-4h1.65l2.77-2.77c-.21.54-.32 1.14-.32 1.77 0 2.8 2.2 5 5 5s5-2.2 5-5c0-2.65-1.97-4.77-4.56-4.97zM7.82 15C7.4 16.15 6.28 17 5 17c-1.63 0-3-1.37-3-3s1.37-3 3-3c1.28 0 2.4.85 2.82 2H5v2h2.82zM19 17c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"></path></g>
-<g id="move-to-inbox"><path d="M19 3H4.99c-1.11 0-1.98.9-1.98 2L3 19c0 1.1.88 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V5H19v10zm-3-5h-2V7h-4v3H8l4 4 4-4z"></path></g>
-<g id="next-week"><path d="M20 7h-4V5c0-.55-.22-1.05-.59-1.41C15.05 3.22 14.55 3 14 3h-4c-1.1 0-2 .9-2 2v2H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zM10 5h4v2h-4V5zm1 13.5l-1-1 3-3-3-3 1-1 4 4-4 4z"></path></g>
-<g id="note-add"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 14h-3v3h-2v-3H8v-2h3v-3h2v3h3v2zm-3-7V3.5L18.5 9H13z"></path></g>
-<g id="offline-pin"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm5 16H7v-2h10v2zm-6.7-4L7 10.7l1.4-1.4 1.9 1.9 5.3-5.3L17 7.3 10.3 14z"></path></g>
-<g id="opacity"><path d="M17.66 8L12 2.35 6.34 8C4.78 9.56 4 11.64 4 13.64s.78 4.11 2.34 5.67 3.61 2.35 5.66 2.35 4.1-.79 5.66-2.35S20 15.64 20 13.64 19.22 9.56 17.66 8zM6 14c.01-2 .62-3.27 1.76-4.4L12 5.27l4.24 4.38C17.38 10.77 17.99 12 18 14H6z"></path></g>
-<g id="open-in-browser"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z"></path></g>
-<g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></path></g>
-<g id="open-with"><path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path></g>
-<g id="pageview"><path d="M11.5 9C10.12 9 9 10.12 9 11.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5S12.88 9 11.5 9zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-3.21 14.21l-2.91-2.91c-.69.44-1.51.7-2.39.7C9.01 16 7 13.99 7 11.5S9.01 7 11.5 7 16 9.01 16 11.5c0 .88-.26 1.69-.7 2.39l2.91 2.9-1.42 1.42z"></path></g>
-<g id="pan-tool"><path d="M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1.19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31 2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5z"></path></g>
-<g id="payment"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path></g>
-<g id="perm-camera-mic"><path d="M20 5h-3.17L15 3H9L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v-2.09c-2.83-.48-5-2.94-5-5.91h2c0 2.21 1.79 4 4 4s4-1.79 4-4h2c0 2.97-2.17 5.43-5 5.91V21h7c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-6 8c0 1.1-.9 2-2 2s-2-.9-2-2V9c0-1.1.9-2 2-2s2 .9 2 2v4z"></path></g>
-<g id="perm-contact-calendar"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1z"></path></g>
-<g id="perm-data-setting"><path d="M18.99 11.5c.34 0 .67.03 1 .07L20 0 0 20h11.56c-.04-.33-.07-.66-.07-1 0-4.14 3.36-7.5 7.5-7.5zm3.71 7.99c.02-.16.04-.32.04-.49 0-.17-.01-.33-.04-.49l1.06-.83c.09-.08.12-.21.06-.32l-1-1.73c-.06-.11-.19-.15-.31-.11l-1.24.5c-.26-.2-.54-.37-.85-.49l-.19-1.32c-.01-.12-.12-.21-.24-.21h-2c-.12 0-.23.09-.25.21l-.19 1.32c-.3.13-.59.29-.85.49l-1.24-.5c-.11-.04-.24 0-.31.11l-1 1.73c-.06.11-.04.24.06.32l1.06.83c-.02.16-.03.32-.03.49 0 .17.01.33.03.49l-1.06.83c-.09.08-.12.21-.06.32l1 1.73c.06.11.19.15.31.11l1.24-.5c.26.2.54.37.85.49l.19 1.32c.02.12.12.21.25.21h2c.12 0 .23-.09.25-.21l.19-1.32c.3-.13.59-.29.84-.49l1.25.5c.11.04.24 0 .31-.11l1-1.73c.06-.11.03-.24-.06-.32l-1.07-.83zm-3.71 1.01c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path></g>
-<g id="perm-device-information"><path d="M13 7h-2v2h2V7zm0 4h-2v6h2v-6zm4-9.99L7 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>
-<g id="perm-identity"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"></path></g>
-<g id="perm-media"><path d="M2 6H0v5h.01L0 20c0 1.1.9 2 2 2h18v-2H2V6zm20-2h-8l-2-2H6c-1.1 0-1.99.9-1.99 2L4 16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM7 15l4.5-6 3.5 4.51 2.5-3.01L21 15H7z"></path></g>
-<g id="perm-phone-msg"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM12 3v10l3-3h6V3h-9z"></path></g>
-<g id="perm-scan-wifi"><path d="M12 3C6.95 3 3.15 4.85 0 7.23L12 22 24 7.25C20.85 4.87 17.05 3 12 3zm1 13h-2v-6h2v6zm-2-8V6h2v2h-2z"></path></g>
-<g id="pets"><circle cx="4.5" cy="9.5" r="2.5"></circle><circle cx="9" cy="5.5" r="2.5"></circle><circle cx="15" cy="5.5" r="2.5"></circle><circle cx="19.5" cy="9.5" r="2.5"></circle><path d="M17.34 14.86c-.87-1.02-1.6-1.89-2.48-2.91-.46-.54-1.05-1.08-1.75-1.32-.11-.04-.22-.07-.33-.09-.25-.04-.52-.04-.78-.04s-.53 0-.79.05c-.11.02-.22.05-.33.09-.7.24-1.28.78-1.75 1.32-.87 1.02-1.6 1.89-2.48 2.91-1.31 1.31-2.92 2.76-2.62 4.79.29 1.02 1.02 2.03 2.33 2.32.73.15 3.06-.44 5.54-.44h.18c2.48 0 4.81.58 5.54.44 1.31-.29 2.04-1.31 2.33-2.32.31-2.04-1.3-3.49-2.61-4.8z"></path></g>
-<g id="picture-in-picture"><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"></path></g>
-<g id="picture-in-picture-alt"><path d="M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1 3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V4.97h18v14.05z"></path></g>
-<g id="play-for-work"><path d="M11 5v5.59H7.5l4.5 4.5 4.5-4.5H13V5h-2zm-5 9c0 3.31 2.69 6 6 6s6-2.69 6-6h-2c0 2.21-1.79 4-4 4s-4-1.79-4-4H6z"></path></g>
-<g id="polymer"><path d="M19 4h-4L7.11 16.63 4.5 12 9 4H5L.5 12 5 20h4l7.89-12.63L19.5 12 15 20h4l4.5-8z"></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="pregnant-woman"><path d="M9 4c0-1.11.89-2 2-2s2 .89 2 2-.89 2-2 2-2-.89-2-2zm7 9c-.01-1.34-.83-2.51-2-3 0-1.66-1.34-3-3-3s-3 1.34-3 3v7h2v5h3v-5h3v-4z"></path></g>
-<g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"></path></g>
-<g id="query-builder"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g>
-<g id="question-answer"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"></path></g>
-<g id="radio-button-checked"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g>
-<g id="radio-button-unchecked"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g>
-<g id="receipt"><path d="M18 17H6v-2h12v2zm0-4H6v-2h12v2zm0-4H6V7h12v2zM3 22l1.5-1.5L6 22l1.5-1.5L9 22l1.5-1.5L12 22l1.5-1.5L15 22l1.5-1.5L18 22l1.5-1.5L21 22V2l-1.5 1.5L18 2l-1.5 1.5L15 2l-1.5 1.5L12 2l-1.5 1.5L9 2 7.5 3.5 6 2 4.5 3.5 3 2v20z"></path></g>
-<g id="record-voice-over"><circle cx="9" cy="9" r="4"></circle><path d="M9 15c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4zm7.76-9.64l-1.68 1.69c.84 1.18.84 2.71 0 3.89l1.68 1.69c2.02-2.02 2.02-5.07 0-7.27zM20.07 2l-1.63 1.63c2.77 3.02 2.77 7.56 0 10.74L20.07 16c3.9-3.89 3.91-9.95 0-14z"></path></g>
-<g id="redeem"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g>
-<g id="redo"><path d="M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z"></path></g>
-<g id="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></g>
-<g id="remove"><path d="M19 13H5v-2h14v2z"></path></g>
-<g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z"></path></g>
-<g id="remove-circle-outline"><path d="M7 11v2h10v-2H7zm5-9C6.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 8z"></path></g>
-<g id="reorder"><path d="M3 15h18v-2H3v2zm0 4h18v-2H3v2zm0-8h18V9H3v2zm0-6v2h18V5H3z"></path></g>
-<g id="reply"><path d="M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"></path></g>
-<g id="reply-all"><path d="M7 8V5l-7 7 7 7v-3l-4-4 4-4zm6 1V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"></path></g>
-<g id="report"><path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0 .72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z"></path></g>
-<g id="report-problem"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
-<g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"></path></g>
-<g id="room"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"></path></g>
-<g id="rounded-corner"><path d="M19 19h2v2h-2v-2zm0-2h2v-2h-2v2zM3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm0-4h2V3H3v2zm4 0h2V3H7v2zm8 16h2v-2h-2v2zm-4 0h2v-2h-2v2zm4 0h2v-2h-2v2zm-8 0h2v-2H7v2zm-4 0h2v-2H3v2zM21 8c0-2.76-2.24-5-5-5h-5v2h5c1.65 0 3 1.35 3 3v5h2V8z"></path></g>
-<g id="rowing"><path d="M8.5 14.5L4 19l1.5 1.5L9 17h2l-2.5-2.5zM15 1c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 20.01L18 24l-2.99-3.01V19.5l-7.1-7.09c-.31.05-.61.07-.91.07v-2.16c1.66.03 3.61-.87 4.67-2.04l1.4-1.55c.19-.21.43-.38.69-.5.29-.14.62-.23.96-.23h.03C15.99 6.01 17 7.02 17 8.26v5.75c0 .84-.35 1.61-.92 2.16l-3.58-3.58v-2.27c-.63.52-1.43 1.02-2.29 1.39L16.5 18H18l3 3.01z"></path></g>
-<g id="save"><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"></path></g>
-<g id="schedule"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g>
-<g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
-<g id="select-all"><path d="M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm2-8h6v6H9V9z"></path></g>
-<g id="send"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path></g>
-<g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
-<g id="settings-applications"><path d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm7-7H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-1.75 9c0 .23-.02.46-.05.68l1.48 1.16c.13.11.17.3.08.45l-1.4 2.42c-.09.15-.27.21-.43.15l-1.74-.7c-.36.28-.76.51-1.18.69l-.26 1.85c-.03.17-.18.3-.35.3h-2.8c-.17 0-.32-.13-.35-.29l-.26-1.85c-.43-.18-.82-.41-1.18-.69l-1.74.7c-.16.06-.34 0-.43-.15l-1.4-2.42c-.09-.15-.05-.34.08-.45l1.48-1.16c-.03-.23-.05-.46-.05-.69 0-.23.02-.46.05-.68l-1.48-1.16c-.13-.11-.17-.3-.08-.45l1.4-2.42c.09-.15.27-.21.43-.15l1.74.7c.36-.28.76-.51 1.18-.69l.26-1.85c.03-.17.18-.3.35-.3h2.8c.17 0 .32.13.35.29l.26 1.85c.43.18.82.41 1.18.69l1.74-.7c.16-.06.34 0 .43.15l1.4 2.42c.09.15.05.34-.08.45l-1.48 1.16c.03.23.05.46.05.69z"></path></g>
-<g id="settings-backup-restore"><path d="M14 12c0-1.1-.9-2-2-2s-2 .9-2 2 .9 2 2 2 2-.9 2-2zm-2-9c-4.97 0-9 4.03-9 9H0l4 4 4-4H5c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.51 0-2.91-.49-4.06-1.3l-1.42 1.44C8.04 20.3 9.94 21 12 21c4.97 0 9-4.03 9-9s-4.03-9-9-9z"></path></g>
-<g id="settings-bluetooth"><path d="M11 24h2v-2h-2v2zm-4 0h2v-2H7v2zm8 0h2v-2h-2v2zm2.71-18.29L12 0h-1v7.59L6.41 3 5 4.41 10.59 10 5 15.59 6.41 17 11 12.41V20h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 3.83l1.88 1.88L13 7.59V3.83zm1.88 10.46L13 16.17v-3.76l1.88 1.88z"></path></g>
-<g id="settings-brightness"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02zM8 16h2.5l1.5 1.5 1.5-1.5H16v-2.5l1.5-1.5-1.5-1.5V8h-2.5L12 6.5 10.5 8H8v2.5L6.5 12 8 13.5V16zm4-7c1.66 0 3 1.34 3 3s-1.34 3-3 3V9z"></path></g>
-<g id="settings-cell"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM16 .01L8 0C6.9 0 6 .9 6 2v16c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V2c0-1.1-.9-1.99-2-1.99zM16 16H8V4h8v12z"></path></g>
-<g id="settings-ethernet"><path d="M7.77 6.76L6.23 5.48.82 12l5.41 6.52 1.54-1.28L3.42 12l4.35-5.24zM7 13h2v-2H7v2zm10-2h-2v2h2v-2zm-6 2h2v-2h-2v2zm6.77-7.52l-1.54 1.28L20.58 12l-4.35 5.24 1.54 1.28L23.18 12l-5.41-6.52z"></path></g>
-<g id="settings-input-antenna"><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.12-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3 3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9h2c0-6.07-4.93-11-11-11z"></path></g>
-<g id="settings-input-component"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g>
-<g id="settings-input-composite"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g>
-<g id="settings-input-hdmi"><path d="M18 7V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v3H5v6l3 6v3h8v-3l3-6V7h-1zM8 4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"></path></g>
-<g id="settings-input-svideo"><path d="M8 11.5c0-.83-.67-1.5-1.5-1.5S5 10.67 5 11.5 5.67 13 6.5 13 8 12.33 8 11.5zm7-5c0-.83-.67-1.5-1.5-1.5h-3C9.67 5 9 5.67 9 6.5S9.67 8 10.5 8h3c.83 0 1.5-.67 1.5-1.5zM8.5 15c-.83 0-1.5.67-1.5 1.5S7.67 18 8.5 18s1.5-.67 1.5-1.5S9.33 15 8.5 15zM12 1C5.93 1 1 5.93 1 12s4.93 11 11 11 11-4.93 11-11S18.07 1 12 1zm0 20c-4.96 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9zm5.5-11c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm-2 5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"></path></g>
-<g id="settings-overscan"><path d="M12.01 5.5L10 8h4l-1.99-2.5zM18 10v4l2.5-1.99L18 10zM6 10l-2.5 2.01L6 14v-4zm8 6h-4l2.01 2.5L14 16zm7-13H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"></path></g>
-<g id="settings-phone"><path d="M13 9h-2v2h2V9zm4 0h-2v2h2V9zm3 6.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 9v2h2V9h-2z"></path></g>
-<g id="settings-power"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm2-22h-2v10h2V2zm3.56 2.44l-1.45 1.45C16.84 6.94 18 8.83 18 11c0 3.31-2.69 6-6 6s-6-2.69-6-6c0-2.17 1.16-4.06 2.88-5.12L7.44 4.44C5.36 5.88 4 8.28 4 11c0 4.42 3.58 8 8 8s8-3.58 8-8c0-2.72-1.36-5.12-3.44-6.56zM15 24h2v-2h-2v2z"></path></g>
-<g id="settings-remote"><path d="M15 9H9c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V10c0-.55-.45-1-1-1zm-3 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM7.05 6.05l1.41 1.41C9.37 6.56 10.62 6 12 6s2.63.56 3.54 1.46l1.41-1.41C15.68 4.78 13.93 4 12 4s-3.68.78-4.95 2.05zM12 0C8.96 0 6.21 1.23 4.22 3.22l1.41 1.41C7.26 3.01 9.51 2 12 2s4.74 1.01 6.36 2.64l1.41-1.41C17.79 1.23 15.04 0 12 0z"></path></g>
-<g id="settings-voice"><path d="M7 24h2v-2H7v2zm5-11c1.66 0 2.99-1.34 2.99-3L15 4c0-1.66-1.34-3-3-3S9 2.34 9 4v6c0 1.66 1.34 3 3 3zm-1 11h2v-2h-2v2zm4 0h2v-2h-2v2zm4-14h-1.7c0 3-2.54 5.1-5.3 5.1S6.7 13 6.7 10H5c0 3.41 2.72 6.23 6 6.72V20h2v-3.28c3.28-.49 6-3.31 6-6.72z"></path></g>
-<g id="shop"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"></path></g>
-<g id="shop-two"><path d="M3 9H1v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2H3V9zm15-4V3c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H5v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2V5h-5zm-6-2h4v2h-4V3zm0 12V8l5.5 3-5.5 4z"></path></g>
-<g id="shopping-basket"><path d="M17.21 9l-4.38-6.56c-.19-.28-.51-.42-.83-.42-.32 0-.64.14-.83.43L6.79 9H2c-.55 0-1 .45-1 1 0 .09.01.18.04.27l2.54 9.27c.23.84 1 1.46 1.92 1.46h13c.92 0 1.69-.62 1.93-1.46l2.54-9.27L23 10c0-.55-.45-1-1-1h-4.79zM9 9l3-4.4L15 9H9zm3 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g>
-<g id="shopping-cart"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"></path></g>
-<g id="sort"><path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"></path></g>
-<g id="speaker-notes"><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-2zM8 14H6v-2h2v2zm0-3H6V9h2v2zm0-3H6V6h2v2zm7 6h-5v-2h5v2zm3-3h-8V9h8v2zm0-3h-8V6h8v2z"></path></g>
-<g id="spellcheck"><path d="M12.45 16h2.09L9.43 3H7.57L2.46 16h2.09l1.12-3h5.64l1.14 3zm-6.02-5L8.5 5.48 10.57 11H6.43zm15.16.59l-8.09 8.09L9.83 16l-1.41 1.41 5.09 5.09L23 13l-1.41-1.41z"></path></g>
-<g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
-<g id="star-border"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"></path></g>
-<g id="star-half"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4V6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"></path></g>
-<g id="stars"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm4.24 16L12 15.45 7.77 18l1.12-4.81-3.73-3.23 4.92-.42L12 5l1.92 4.53 4.92.42-3.73 3.23L16.23 18z"></path></g>
-<g id="store"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h1zm-9 4H6v-4h6v4z"></path></g>
-<g id="subdirectory-arrow-left"><path d="M11 9l1.42 1.42L8.83 14H18V4h2v12H8.83l3.59 3.58L11 21l-6-6 6-6z"></path></g>
-<g id="subdirectory-arrow-right"><path d="M19 15l-6 6-1.42-1.42L15.17 16H4V4h2v10h9.17l-3.59-3.58L13 9l6 6z"></path></g>
-<g id="subject"><path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z"></path></g>
-<g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 16.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.66 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"></path></g>
-<g id="swap-horiz"><path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"></path></g>
-<g id="swap-vert"><path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3V14h2V6.99h3L9 3z"></path></g>
-<g id="swap-vertical-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM6.5 9L10 5.5 13.5 9H11v4H9V9H6.5zm11 6L14 18.5 10.5 15H13v-4h2v4h2.5z"></path></g>
-<g id="system-update-alt"><path d="M12 16.5l4-4h-3v-9h-2v9H8l4 4zm9-13h-6v1.99h6v14.03H3V5.49h6V3.5H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2z"></path></g>
-<g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"></path></g>
-<g id="tab-unselected"><path d="M1 9h2V7H1v2zm0 4h2v-2H1v2zm0-8h2V3c-1.1 0-2 .9-2 2zm8 16h2v-2H9v2zm-8-4h2v-2H1v2zm2 4v-2H1c0 1.1.9 2 2 2zM21 3h-8v6h10V5c0-1.1-.9-2-2-2zm0 14h2v-2h-2v2zM9 5h2V3H9v2zM5 21h2v-2H5v2zM5 5h2V3H5v2zm16 16c1.1 0 2-.9 2-2h-2v2zm0-8h2v-2h-2v2zm-8 8h2v-2h-2v2zm4 0h2v-2h-2v2z"></path></g>
-<g id="text-format"><path d="M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L6.5 15h2.1l.9-2.2zM12 5.98L13.87 11h-3.74L12 5.98z"></path></g>
-<g id="theaters"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8 17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h2v2z"></path></g>
-<g id="thumb-down"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v1.91l.01.01L1 14c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"></path></g>
-<g id="thumb-up"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23 10z"></path></g>
-<g id="thumbs-up-down"><path d="M12 6c0-.55-.45-1-1-1H5.82l.66-3.18.02-.23c0-.31-.13-.59-.33-.8L5.38 0 .44 4.94C.17 5.21 0 5.59 0 6v6.5c0 .83.67 1.5 1.5 1.5h6.75c.62 0 1.15-.38 1.38-.91l2.26-5.29c.07-.17.11-.36.11-.55V6zm10.5 4h-6.75c-.62 0-1.15.38-1.38.91l-2.26 5.29c-.07.17-.11.36-.11.55V18c0 .55.45 1 1 1h5.18l-.66 3.18-.02.24c0 .31.13.59.33.8l.79.78 4.94-4.94c.27-.27.44-.65.44-1.06v-6.5c0-.83-.67-1.5-1.5-1.5z"></path></g>
-<g id="timeline"><path d="M23 8c0 1.1-.9 2-2 2-.18 0-.35-.02-.51-.07l-3.56 3.55c.05.16.07.34.07.52 0 1.1-.9 2-2 2s-2-.9-2-2c0-.18.02-.36.07-.52l-2.55-2.55c-.16.05-.34.07-.52.07s-.36-.02-.52-.07l-4.55 4.56c.05.16.07.33.07.51 0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2c.18 0 .35.02.51.07l4.56-4.55C8.02 9.36 8 9.18 8 9c0-1.1.9-2 2-2s2 .9 2 2c0 .18-.02.36-.07.52l2.55 2.55c.16-.05.34-.07.52-.07s.36.02.52.07l3.55-3.56C19.02 8.35 19 8.18 19 8c0-1.1.9-2 2-2s2 .9 2 2z"></path></g>
-<g id="toc"><path d="M3 9h14V7H3v2zm0 4h14v-2H3v2zm0 4h14v-2H3v2zm16 0h2v-2h-2v2zm0-10v2h2V7h-2zm0 6h2v-2h-2v2z"></path></g>
-<g id="today"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"></path></g>
-<g id="toll"><path d="M15 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zM3 12c0-2.61 1.67-4.83 4-5.65V4.26C3.55 5.15 1 8.27 1 12s2.55 6.85 6 7.74v-2.09c-2.33-.82-4-3.04-4-5.65z"></path></g>
-<g id="touch-app"><path d="M9 11.24V7.5C9 6.12 10.12 5 11.5 5S14 6.12 14 7.5v3.74c1.21-.81 2-2.18 2-3.74C16 5.01 13.99 3 11.5 3S7 5.01 7 7.5c0 1.56.79 2.93 2 3.74zm9.84 4.63l-4.54-2.26c-.17-.07-.35-.11-.54-.11H13v-6c0-.83-.67-1.5-1.5-1.5S10 6.67 10 7.5v10.74l-3.43-.72c-.08-.01-.15-.03-.24-.03-.31 0-.59.13-.79.33l-.79.8 4.94 4.94c.27.27.65.44 1.06.44h6.79c.75 0 1.33-.55 1.44-1.28l.75-5.27c.01-.07.02-.14.02-.2 0-.62-.38-1.16-.91-1.38z"></path></g>
-<g id="track-changes"><path d="M19.07 4.93l-1.41 1.41C19.1 7.79 20 9.79 20 12c0 4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93v2.02C8.16 6.57 6 9.03 6 12c0 3.31 2.69 6 6 6s6-2.69 6-6c0-1.66-.67-3.16-1.76-4.24l-1.41 1.41C15.55 9.9 16 10.9 16 12c0 2.21-1.79 4-4 4s-4-1.79-4-4c0-1.86 1.28-3.41 3-3.86v2.14c-.6.35-1 .98-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V2h-1C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10c0-2.76-1.12-5.26-2.93-7.07z"></path></g>
-<g id="translate"><path d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"></path></g>
-<g id="trending-down"><path d="M16 18l2.29-2.29-4.88-4.88-4 4L2 7.41 3.41 6l6 6 4-4 6.3 6.29L22 12v6z"></path></g>
-<g id="trending-flat"><path d="M22 12l-4-4v3H3v2h15v3z"></path></g>
-<g id="trending-up"><path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4 4 6.3-6.29L22 12V6z"></path></g>
-<g id="turned-in"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"></path></g>
-<g id="turned-in-not"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g>
-<g id="unarchive"><path d="M20.55 5.22l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.15.55L3.46 5.22C3.17 5.57 3 6.01 3 6.5V19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.49-.17-.93-.45-1.28zM12 9.5l5.5 5.5H14v2h-4v-2H6.5L12 9.5zM5.12 5l.82-1h12l.93 1H5.12z"></path></g>
-<g id="undo"><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z"></path></g>
-<g id="unfold-less"><path d="M7.41 18.59L8.83 20 12 16.83 15.17 20l1.41-1.41L12 14l-4.59 4.59zm9.18-13.18L15.17 4 12 7.17 8.83 4 7.41 5.41 12 10l4.59-4.59z"></path></g>
-<g id="unfold-more"><path d="M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z"></path></g>
-<g id="update"><path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z"></path></g>
-<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>
-<g id="view-agenda"><path d="M20 13H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zm0-10H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1z"></path></g>
-<g id="view-array"><path d="M4 18h3V5H4v13zM18 5v13h3V5h-3zM8 18h9V5H8v13z"></path></g>
-<g id="view-carousel"><path d="M7 19h10V4H7v15zm-5-2h4V6H2v11zM18 6v11h4V6h-4z"></path></g>
-<g id="view-column"><path d="M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z"></path></g>
-<g id="view-day"><path d="M2 21h19v-3H2v3zM20 8H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zM2 3v3h19V3H2z"></path></g>
-<g id="view-headline"><path d="M4 15h16v-2H4v2zm0 4h16v-2H4v2zm0-8h16V9H4v2zm0-6v2h16V5H4z"></path></g>
-<g id="view-list"><path d="M4 14h4v-4H4v4zm0 5h4v-4H4v4zM4 9h4V5H4v4zm5 5h12v-4H9v4zm0 5h12v-4H9v4zM9 5v4h12V5H9z"></path></g>
-<g id="view-module"><path d="M4 11h5V5H4v6zm0 7h5v-6H4v6zm6 0h5v-6h-5v6zm6 0h5v-6h-5v6zm-6-7h5V5h-5v6zm6-6v6h5V5h-5z"></path></g>
-<g id="view-quilt"><path d="M10 18h5v-6h-5v6zm-6 0h5V5H4v13zm12 0h5v-6h-5v6zM10 5v6h11V5H10z"></path></g>
-<g id="view-stream"><path d="M4 18h17v-6H4v6zM4 5v6h17V5H4z"></path></g>
-<g id="view-week"><path d="M6 5H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zm14 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zm-7 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1z"></path></g>
-<g id="visibility"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"></path></g>
-<g id="visibility-off"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"></path></g>
-<g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
-<g id="watch-later"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm4.2 14.2L11 13V7h1.5v5.2l4.5 2.7-.8 1.3z"></path></g>
-<g id="weekend"><path d="M21 10c-1.1 0-2 .9-2 2v3H5v-3c0-1.1-.9-2-2-2s-2 .9-2 2v5c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-5c0-1.1-.9-2-2-2zm-3-5H6c-1.1 0-2 .9-2 2v2.15c1.16.41 2 1.51 2 2.82V14h12v-2.03c0-1.3.84-2.4 2-2.82V7c0-1.1-.9-2-2-2z"></path></g>
-<g id="work"><path d="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-6 0h-4V4h4v2z"></path></g>
-<g id="youtube-searched-for"><path d="M17.01 14h-.8l-.27-.27c.98-1.14 1.57-2.61 1.57-4.23 0-3.59-2.91-6.5-6.5-6.5s-6.5 3-6.5 6.5H2l3.84 4 4.16-4H6.51C6.51 7 8.53 5 11.01 5s4.5 2.01 4.5 4.5c0 2.48-2.02 4.5-4.5 4.5-.65 0-1.26-.14-1.82-.38L7.71 15.1c.97.57 2.09.9 3.3.9 1.61 0 3.08-.59 4.22-1.57l.27.27v.79l5.01 4.99L22 19l-4.99-5z"></path></g>
-<g id="zoom-in"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zm2.5-4h-2v2H9v-2H7V9h2V7h1v2h2v1z"></path></g>
-<g id="zoom-out"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z"></path></g>
-</defs></svg>
-</iron-iconset-svg>
<dom-module id="paper-ripple" assetpath="chrome://resources/polymer/v1_0/paper-ripple/">
@@ -1291,7 +1054,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
#progressContainer,
.indeterminate::after {
- background-color: var(--paper-progress-container-color, --google-grey-300);
+ background: var(--paper-progress-container-color, --google-grey-300);
}
:host(.transiting) #primaryProgress,
@@ -1323,20 +1086,19 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
#primaryProgress {
- background-color: var(--paper-progress-active-color, --google-green-500);
+ background: var(--paper-progress-active-color, --google-green-500);
}
#secondaryProgress {
- position: relative;
- background-color: var(--paper-progress-secondary-color, --google-green-100);
+ background: var(--paper-progress-secondary-color, --google-green-100);
}
:host([disabled]) #primaryProgress {
- background-color: var(--paper-progress-disabled-active-color, --google-grey-500);
+ background: var(--paper-progress-disabled-active-color, --google-grey-500);
}
:host([disabled]) #secondaryProgress {
- background-color: var(--paper-progress-disabled-secondary-color, --google-grey-300);
+ background: var(--paper-progress-disabled-secondary-color, --google-grey-300);
}
:host(:not([disabled])) #primaryProgress.indeterminate {
@@ -1427,6 +1189,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</template>
</dom-module>
+<iron-iconset-svg name="downloads" size="24">
+ <svg>
+ <defs>
+
+ <g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z"></path></g>
+ </defs>
+ </svg>
+</iron-iconset-svg>
<dom-module id="inky-text-button" assetpath="chrome://downloads/">
<template><content></content></template>
<style>
@@ -1534,11 +1304,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
width: 32px;
}
-#danger-icon[icon='warning'] {
+#danger-icon[icon='cr:warning'] {
color: rgb(255, 193, 7);
}
-#danger-icon[icon='remove-circle'] {
+#danger-icon[icon='downloads:remove-circle'] {
color: rgb(244, 67, 54);
}
@@ -1721,7 +1491,7 @@ paper-button {
<span id="tag">[[computeTag_(data.state, data.last_reason_text, data.file_externally_removed)]]</span>
</div>
- <a id="url" target="_blank" href="[[data.url]]">[[data.url]]</a>
+ <a id="url" target="_blank">[[data.url]]</a>
<div id="description">[[computeDescription_(data.state, data.danger_type, data.file_name, data.progress_status_text)]]</div>
@@ -1730,18 +1500,26 @@ paper-button {
</template>
<div id="safe" class="controls" hidden="[[isDangerous_]]">
- <a is="action-link" id="show" i18n-content="controlShowInFolder" on-tap="onShowTap_" hidden="[[!completelyOnDisk_]]"></a>
+ <a is="action-link" id="show" on-tap="onShowTap_" hidden="[[!completelyOnDisk_]]">$i18n{controlShowInFolder}</a>
<template is="dom-if" if="[[data.retry]]">
- <paper-button id="retry" on-tap="onRetryTap_">[[i18n_.retry]]</paper-button>
+ <paper-button id="retry" on-tap="onRetryTap_">
+ $i18n{controlRetry}
+ </paper-button>
</template>
<template is="dom-if" if="[[isInProgress_]]">
- <paper-button id="pause" on-tap="onPauseTap_">[[i18n_.pause]]</paper-button>
+ <paper-button id="pause" on-tap="onPauseTap_">
+ $i18n{controlPause}
+ </paper-button>
</template>
<template is="dom-if" if="[[data.resume]]">
- <paper-button id="resume" on-tap="onResumeTap_">[[i18n_.resume]]</paper-button>
+ <paper-button id="resume" on-tap="onResumeTap_">
+ $i18n{controlResume}
+ </paper-button>
</template>
<template is="dom-if" if="[[showCancel_]]">
- <paper-button id="cancel" on-tap="onCancelTap_">[[i18n_.cancel]]</paper-button>
+ <paper-button id="cancel" on-tap="onCancelTap_">
+ $i18n{controlCancel}
+ </paper-button>
</template>
<span id="controlled-by"></span>
</div>
@@ -1750,24 +1528,25 @@ paper-button {
<div id="dangerous" class="controls">
<template is="dom-if" if="[[!isMalware_]]">
- <paper-button id="discard" on-tap="onDiscardDangerousTap_" class="discard">[[i18n_.discard]]</paper-button>
- <paper-button id="save" on-tap="onSaveDangerousTap_" class="keep">[[i18n_.save]]</paper-button>
+ <paper-button id="discard" on-tap="onDiscardDangerousTap_" class="discard">$i18n{dangerDiscard}</paper-button>
+ <paper-button id="save" on-tap="onSaveDangerousTap_" class="keep">$i18n{dangerSave}</paper-button>
</template>
<template is="dom-if" if="[[isMalware_]]">
- <paper-button id="danger-remove" on-tap="onDiscardDangerousTap_" class="discard">[[i18n_.remove]]</paper-button>
- <paper-button id="restore" on-tap="onSaveDangerousTap_" class="keep">[[i18n_.restore]]</paper-button>
+ <paper-button id="danger-remove" on-tap="onDiscardDangerousTap_" class="discard">$i18n{controlRemoveFromList}</paper-button>
+ <paper-button id="restore" on-tap="onSaveDangerousTap_" class="keep">$i18n{dangerRestore}</paper-button>
</template>
</div>
</template>
</div>
<div id="remove-wrapper" class="icon-wrapper">
- <inky-text-button id="remove" i18n-values="title:controlRemoveFromList" style$="[[computeRemoveStyle_(isDangerous_, showCancel_)]]" on-tap="onRemoveTap_">✕</inky-text-button>
+ <inky-text-button id="remove" title="$i18n{controlRemoveFromList}" style$="[[computeRemoveStyle_(isDangerous_, showCancel_)]]" on-tap="onRemoveTap_">✕</inky-text-button>
</div>
- <div id="incognito" i18n-values="title:inIncognito" hidden="[[!data.otr]]"></div>
+ <div id="incognito" title="$i18n{inIncognito}" hidden="[[!data.otr]]">
+ </div>
</div>
</template>
@@ -1834,40 +1613,235 @@ paper-button {
}
</style>
+<style>
+/* 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. */
+
+@font-face {
+ font-family: 'Roboto';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Roboto'), local('Roboto-Regular'),
+ url("chrome://resources/roboto/roboto-regular.woff2") format('woff2');
+}
+
+@font-face {
+ font-family: 'Roboto';
+ font-style: normal;
+ font-weight: 500;
+ src: local('Roboto Medium'), local('Roboto-Medium'),
+ url("chrome://resources/roboto/roboto-medium.woff2") format('woff2');
+}
+
+@font-face {
+ font-family: 'Roboto';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Roboto Bold'), local('Roboto-Bold'),
+ url("chrome://resources/roboto/roboto-bold.woff2") format('woff2');
+}
+
+</style>
+<style is="custom-style">
+
+ :root {
+
+ /* Shared Styles */
+ --paper-font-common-base: {
+ font-family: 'Roboto', 'Noto', sans-serif;
+ -webkit-font-smoothing: antialiased;
+ };
+
+ --paper-font-common-code: {
+ font-family: 'Roboto Mono', 'Consolas', 'Menlo', monospace;
+ -webkit-font-smoothing: antialiased;
+ };
+
+ --paper-font-common-expensive-kerning: {
+ text-rendering: optimizeLegibility;
+ };
+
+ --paper-font-common-nowrap: {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ };
+
+ /* Material Font Styles */
+
+ --paper-font-display4: {
+ @apply(--paper-font-common-base);
+ @apply(--paper-font-common-nowrap);
+
+ font-size: 112px;
+ font-weight: 300;
+ letter-spacing: -.044em;
+ line-height: 120px;
+ };
+
+ --paper-font-display3: {
+ @apply(--paper-font-common-base);
+ @apply(--paper-font-common-nowrap);
+
+ font-size: 56px;
+ font-weight: 400;
+ letter-spacing: -.026em;
+ line-height: 60px;
+ };
+
+ --paper-font-display2: {
+ @apply(--paper-font-common-base);
+
+ font-size: 45px;
+ font-weight: 400;
+ letter-spacing: -.018em;
+ line-height: 48px;
+ };
+
+ --paper-font-display1: {
+ @apply(--paper-font-common-base);
+
+ font-size: 34px;
+ font-weight: 400;
+ letter-spacing: -.01em;
+ line-height: 40px;
+ };
+
+ --paper-font-headline: {
+ @apply(--paper-font-common-base);
+
+ font-size: 24px;
+ font-weight: 400;
+ letter-spacing: -.012em;
+ line-height: 32px;
+ };
+
+ --paper-font-title: {
+ @apply(--paper-font-common-base);
+ @apply(--paper-font-common-nowrap);
+
+ font-size: 20px;
+ font-weight: 500;
+ line-height: 28px;
+ };
+
+ --paper-font-subhead: {
+ @apply(--paper-font-common-base);
+
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 24px;
+ };
+
+ --paper-font-body2: {
+ @apply(--paper-font-common-base);
+
+ font-size: 14px;
+ font-weight: 500;
+ line-height: 24px;
+ };
+
+ --paper-font-body1: {
+ @apply(--paper-font-common-base);
+
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 20px;
+ };
+
+ --paper-font-caption: {
+ @apply(--paper-font-common-base);
+ @apply(--paper-font-common-nowrap);
+
+ font-size: 12px;
+ font-weight: 400;
+ letter-spacing: 0.011em;
+ line-height: 20px;
+ };
+
+ --paper-font-menu: {
+ @apply(--paper-font-common-base);
+ @apply(--paper-font-common-nowrap);
+
+ font-size: 13px;
+ font-weight: 500;
+ line-height: 24px;
+ };
+
+ --paper-font-button: {
+ @apply(--paper-font-common-base);
+ @apply(--paper-font-common-nowrap);
+
+ font-size: 14px;
+ font-weight: 500;
+ letter-spacing: 0.018em;
+ line-height: 24px;
+ text-transform: uppercase;
+ };
+
+ --paper-font-code2: {
+ @apply(--paper-font-common-code);
+
+ font-size: 14px;
+ font-weight: 700;
+ line-height: 20px;
+ };
+
+ --paper-font-code1: {
+ @apply(--paper-font-common-code);
+
+ font-size: 14px;
+ font-weight: 500;
+ line-height: 20px;
+ };
+
+ }
+
+</style>
<dom-module id="paper-item-shared-styles" assetpath="chrome://resources/polymer/v1_0/paper-item/">
<template>
<style>
- :host {
+ :host, .paper-item {
display: block;
position: relative;
min-height: var(--paper-item-min-height, 48px);
padding: 0px 16px;
}
- :host([hidden]) {
+ .paper-item {
+ @apply(--paper-font-subhead);
+ border:none;
+ outline: none;
+ background: white;
+ width: 100%;
+ text-align: left;
+ }
+
+ :host([hidden]), .paper-item[hidden] {
display: none !important;
}
- :host(.iron-selected) {
+ :host(.iron-selected), .paper-item.iron-selected {
font-weight: var(--paper-item-selected-weight, bold);
@apply(--paper-item-selected);
}
- :host([disabled]) {
+ :host([disabled]), .paper-item[disabled] {
color: var(--paper-item-disabled-color, --disabled-text-color);
@apply(--paper-item-disabled);
}
- :host(:focus) {
+ :host(:focus), .paper-item:focus {
position: relative;
outline: 0;
@apply(--paper-item-focused);
}
- :host(:focus):before {
+ :host(:focus):before, .paper-item:focus:before {
@apply(--layout-fit);
background: currentColor;
@@ -1962,26 +1936,24 @@ paper-button {
<dom-module id="iron-overlay-backdrop" assetpath="chrome://resources/polymer/v1_0/iron-overlay-behavior/">
<style>
-
:host {
position: fixed;
top: 0;
left: 0;
- width: 100vw;
- height: 100vh;
+ width: 100%;
+ height: 100%;
background-color: var(--iron-overlay-backdrop-background-color, #000);
opacity: 0;
transition: opacity 0.2s;
-
+ pointer-events: none;
@apply(--iron-overlay-backdrop);
}
- :host([opened]) {
+ :host(.opened) {
opacity: var(--iron-overlay-backdrop-opacity, 0.6);
-
+ pointer-events: auto;
@apply(--iron-overlay-backdrop-opened);
}
-
</style>
<template>
@@ -2015,56 +1987,63 @@ paper-button {
</dom-module>
<dom-module id="paper-menu-button" assetpath="chrome://resources/polymer/v1_0/paper-menu-button/">
- <style>
- :host {
- display: inline-block;
- position: relative;
- padding: 8px;
- outline: none;
+ <template>
+ <style>
+ :host {
+ display: inline-block;
+ position: relative;
+ padding: 8px;
+ outline: none;
- @apply(--paper-menu-button);
- }
+ @apply(--paper-menu-button);
+ }
- :host([disabled]) {
- cursor: auto;
- color: var(--disabled-text-color);
+ :host([disabled]) {
+ cursor: auto;
+ color: var(--disabled-text-color);
- @apply(--paper-menu-button-disabled);
- }
+ @apply(--paper-menu-button-disabled);
+ }
- :host([vertical-align="top"]) paper-material {
- margin-bottom: 20px;
- margin-top: -10px;
- top: 10px;
- }
+ iron-dropdown {
+ @apply(--paper-menu-button-dropdown);
+ }
- :host([vertical-align="bottom"]) paper-material {
- bottom: 10px;
- margin-bottom: -10px;
- margin-top: 20px;
- }
+ .dropdown-content {
+ @apply(--shadow-elevation-2dp);
- iron-dropdown {
- @apply(--paper-menu-button-dropdown);
- }
+ position: relative;
+ border-radius: 2px;
+ background-color: var(--paper-menu-button-dropdown-background, --primary-background-color);
- .dropdown-content {
- border-radius: 2px;
- background-color: var(--paper-menu-button-dropdown-background, --primary-background-color);
- @apply(--paper-menu-button-content);
- }
- </style>
- <template>
- <div id="trigger" on-tap="open">
+ @apply(--paper-menu-button-content);
+ }
+
+ :host([vertical-align="top"]) .dropdown-content {
+ margin-bottom: 20px;
+ margin-top: -10px;
+ top: 10px;
+ }
+
+ :host([vertical-align="bottom"]) .dropdown-content {
+ bottom: 10px;
+ margin-bottom: -10px;
+ margin-top: 20px;
+ }
+ </style>
+
+ <div id="trigger" on-tap="toggle">
<content select=".dropdown-trigger"></content>
</div>
- <iron-dropdown id="dropdown" opened="{{opened}}" horizontal-align="[[horizontalAlign]]" vertical-align="[[verticalAlign]]" horizontal-offset="[[horizontalOffset]]" vertical-offset="[[verticalOffset]]" open-animation-config="[[openAnimationConfig]]" close-animation-config="[[closeAnimationConfig]]" no-animations="[[noAnimations]]" focus-target="[[_dropdownContent]]">
- <paper-material class="dropdown-content">
+
+ <iron-dropdown id="dropdown" opened="{{opened}}" horizontal-align="[[horizontalAlign]]" vertical-align="[[verticalAlign]]" horizontal-offset="[[horizontalOffset]]" vertical-offset="[[verticalOffset]]" open-animation-config="[[openAnimationConfig]]" close-animation-config="[[closeAnimationConfig]]" no-animations="[[noAnimations]]" focus-target="[[_dropdownContent]]" on-iron-overlay-canceled="__onIronOverlayCanceled">
+ <div class="dropdown-content">
<content id="content" select=".dropdown-content"></content>
- </paper-material>
+ </div>
</iron-dropdown>
</template>
-</dom-module>
+
+ </dom-module>
<dom-module id="paper-icon-button" assetpath="chrome://resources/polymer/v1_0/paper-icon-button/">
<template strip-whitespace="">
<style>
@@ -2081,12 +2060,13 @@ paper-button {
cursor: pointer;
z-index: 0;
line-height: 1;
-
+
width: 40px;
height: 40px;
/* Because of polymer/2558, this style has lower specificity than * */
box-sizing: border-box !important;
+
@apply(--paper-icon-button);
}
@@ -2099,10 +2079,11 @@ paper-button {
color: var(--paper-icon-button-disabled-text, --disabled-text-color);
pointer-events: none;
cursor: auto;
+
@apply(--paper-icon-button-disabled);
}
-
- :host(:hover) {
+
+ :host(:hover) {
@apply(--paper-icon-button-hover);
}
@@ -2111,198 +2092,59 @@ paper-button {
--iron-icon-height: 100%;
}
</style>
+
<iron-icon id="icon" src="[[src]]" icon="[[icon]]" alt$="[[alt]]"></iron-icon>
</template>
</dom-module>
-<style>
-/* 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. */
-
-@font-face {
- font-family: 'Roboto';
- font-style: normal;
- font-weight: 300;
- src: local('Roboto Light'), local('Roboto-Light'),
- url("chrome://resources/roboto/roboto-light.woff2") format('woff2');
-}
-
-@font-face {
- font-family: 'Roboto';
- font-style: normal;
- font-weight: 400;
- src: local('Roboto'), local('Roboto-Regular'),
- url("chrome://resources/roboto/roboto-regular.woff2") format('woff2');
-}
-
-@font-face {
- font-family: 'Roboto';
- font-style: normal;
- font-weight: 500;
- src: local('Roboto Medium'), local('Roboto-Medium'),
- url("chrome://resources/roboto/roboto-medium.woff2") format('woff2');
-}
-
-</style>
-<style is="custom-style">
-
- :root {
-
- /* Shared Styles */
- --paper-font-common-base: {
- font-family: 'Roboto', 'Noto', sans-serif;
- -webkit-font-smoothing: antialiased;
- };
-
- --paper-font-common-code: {
- font-family: 'Roboto Mono', 'Consolas', 'Menlo', monospace;
- -webkit-font-smoothing: antialiased;
- };
-
- --paper-font-common-expensive-kerning: {
- text-rendering: optimizeLegibility;
- };
-
- --paper-font-common-nowrap: {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- };
-
- /* Material Font Styles */
-
- --paper-font-display4: {
- @apply(--paper-font-common-base);
- @apply(--paper-font-common-nowrap);
-
- font-size: 112px;
- font-weight: 300;
- letter-spacing: -.044em;
- line-height: 120px;
- };
-
- --paper-font-display3: {
- @apply(--paper-font-common-base);
- @apply(--paper-font-common-nowrap);
-
- font-size: 56px;
- font-weight: 400;
- letter-spacing: -.026em;
- line-height: 60px;
- };
-
- --paper-font-display2: {
- @apply(--paper-font-common-base);
-
- font-size: 45px;
- font-weight: 400;
- letter-spacing: -.018em;
- line-height: 48px;
- };
-
- --paper-font-display1: {
- @apply(--paper-font-common-base);
-
- font-size: 34px;
- font-weight: 400;
- letter-spacing: -.01em;
- line-height: 40px;
- };
-
- --paper-font-headline: {
- @apply(--paper-font-common-base);
-
- font-size: 24px;
- font-weight: 400;
- letter-spacing: -.012em;
- line-height: 32px;
- };
-
- --paper-font-title: {
- @apply(--paper-font-common-base);
- @apply(--paper-font-common-nowrap);
-
- font-size: 20px;
- font-weight: 500;
- line-height: 28px;
- };
-
- --paper-font-subhead: {
- @apply(--paper-font-common-base);
-
- font-size: 16px;
- font-weight: 400;
- line-height: 24px;
- };
-
- --paper-font-body2: {
- @apply(--paper-font-common-base);
-
- font-size: 14px;
- font-weight: 500;
- line-height: 24px;
- };
-
- --paper-font-body1: {
- @apply(--paper-font-common-base);
-
- font-size: 14px;
- font-weight: 400;
- line-height: 20px;
- };
-
- --paper-font-caption: {
- @apply(--paper-font-common-base);
- @apply(--paper-font-common-nowrap);
-
- font-size: 12px;
- font-weight: 400;
- letter-spacing: 0.011em;
- line-height: 20px;
- };
-
- --paper-font-menu: {
- @apply(--paper-font-common-base);
- @apply(--paper-font-common-nowrap);
-
- font-size: 13px;
- font-weight: 500;
- line-height: 24px;
- };
-
- --paper-font-button: {
- @apply(--paper-font-common-base);
- @apply(--paper-font-common-nowrap);
-
- font-size: 14px;
- font-weight: 500;
- letter-spacing: 0.018em;
- line-height: 24px;
- text-transform: uppercase;
- };
-
- --paper-font-code2: {
- @apply(--paper-font-common-code);
-
- font-size: 14px;
- font-weight: 700;
- line-height: 20px;
- };
-
- --paper-font-code1: {
- @apply(--paper-font-common-code);
-
- font-size: 14px;
- font-weight: 500;
- line-height: 20px;
- };
+<iron-iconset-svg name="cr" size="24">
+ <svg>
+ <defs>
+
+ <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
+ <g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g>
+<if expr="chromeos">
+ <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
+</if>
+ <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
+ <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
+ <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
+ <g id="domain"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"></path></g>
+ <g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></path></g>
+ <g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></path></g>
+ <g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"></path></g>
+ <g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g>
+ <g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g>
+ <g id="group"><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="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></g>
+ <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
+ <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"></path></g>
+ <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
+ <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
+ <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
+ <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
+<if expr="chromeos">
+ <g id="star-border"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"></path></g>
+</if>
+ </defs>
+ </svg>
+</iron-iconset-svg>
- }
-</style>
+<dom-module id="iron-a11y-announcer" assetpath="chrome://resources/polymer/v1_0/iron-a11y-announcer/">
+ <style>
+ :host {
+ display: inline-block;
+ position: fixed;
+ clip: rect(0px,0px,0px,0px);
+ }
+ </style>
+ <template>
+ <div aria-live$="[[mode]]">[[_text]]</div>
+ </template>
+ </dom-module>
<dom-module id="paper-input-container" assetpath="chrome://resources/polymer/v1_0/paper-input/">
<template>
<style>
@@ -2612,11 +2454,11 @@ paper-icon-button {
}
</style>
- <paper-icon-button icon="search" id="search-button" disabled$="[[showingSearch_]]" title="[[label]]" on-click="toggleShowingSearch_"></paper-icon-button>
+ <paper-icon-button icon="cr:search" id="search-button" disabled$="[[showingSearch_]]" title="[[label]]" on-click="toggleShowingSearch_"></paper-icon-button>
<template is="dom-if" if="[[showingSearch_]]" id="search-container">
<paper-input-container id="search-term" on-search="onSearchTermSearch_" on-keydown="onSearchTermKeydown_" hidden$="[[!showingSearch_]]" no-label-float="">
<input is="iron-input" id="search-input" type="search" placeholder="[[label]]" incremental="">
- <paper-icon-button icon="cancel" id="clear-search" on-click="toggleShowingSearch_" title="[[clearLabel]]" hidden$="[[!showingSearch_]]"></paper-icon-button>
+ <paper-icon-button icon="cr:cancel" id="clear-search" on-click="toggleShowingSearch_" title="[[clearLabel]]" hidden$="[[!showingSearch_]]"></paper-icon-button>
</paper-input-container>
</template>
</template>
@@ -2630,7 +2472,7 @@ paper-icon-button {
:host {
align-items: center;
- background: rgb(52, 73, 94);
+ background: var(--md-toolbar-color);
color: white;
content-sizing: padding-box;
display: flex;
@@ -2755,19 +2597,27 @@ paper-button {
</style>
<div id="title">
- <h1 i18n-content="title"></h1>
+ <h1>$i18n{title}</h1>
</div>
<div id="actions">
- <paper-button class="clear-all" i18n-content="clearAll" on-tap="onClearAllTap_"></paper-button>
- <paper-button i18n-content="openDownloadsFolder" on-tap="onOpenDownloadsFolderTap_"></paper-button>
+ <paper-button class="clear-all" on-tap="onClearAllTap_">
+ $i18n{clearAll}
+ </paper-button>
+ <paper-button on-tap="onOpenDownloadsFolderTap_">
+ $i18n{openDownloadsFolder}
+ </paper-button>
</div>
<div id="search">
- <cr-search-field id="search-input" i18n-values="label:search;clear-label:clearSearch"></cr-search-field>
+ <cr-search-field id="search-input" label="$i18n{search}" clear-label="$i18n{clearSearch}"></cr-search-field>
<paper-menu-button id="more" horizontal-align="[[overflowAlign_]]">
- <paper-icon-button icon="more-vert" i18n-values="title:moreActions" class="dropdown-trigger"></paper-icon-button>
+ <paper-icon-button icon="cr:more-vert" title="$i18n{moreActions}" class="dropdown-trigger"></paper-icon-button>
<paper-menu class="dropdown-content">
- <paper-item class="clear-all" i18n-content="clearAll" on-tap="onClearAllTap_"></paper-item>
- <paper-item i18n-content="openDownloadsFolder" on-tap="onOpenDownloadsFolderTap_"></paper-item>
+ <paper-item class="clear-all" on-tap="onClearAllTap_">
+ $i18n{clearAll}
+ </paper-item>
+ <paper-item on-tap="onOpenDownloadsFolderTap_">
+ $i18n{openDownloadsFolder}
+ </paper-item>
</paper-menu>
</paper-menu-button>
</div>
@@ -2775,6 +2625,20 @@ paper-button {
</dom-module>
+<style>
+/* 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. */
+
+:root {
+ /* These are custom, Chrome-specific colors that don't have --paper or
+ * --google equivalents. Blame bettes@. http://crbug.com/598451 */
+ --md-background-color: rgb(236, 239, 241);
+ --md-toolbar-color: rgb(52, 73, 94);
+}
+
+</style>
+
<dom-module id="downloads-manager" assetpath="chrome://downloads/">
<template><style>
/* Copyright 2015 The Chromium Authors. All rights reserved.
@@ -2845,6 +2709,11 @@ paper-button {
}
</style>
+ <style no-process="">
+ #toolbar {
+ background: var(--md-toolbar-color);
+ }
+ </style>
<downloads-toolbar id="toolbar"></downloads-toolbar>
<iron-list id="downloads-list" items="{{items_}}" hidden="[[!hasDownloads_]]">
<template>
@@ -2874,5 +2743,4 @@ paper-button {
<command id="find-command" shortcut="Ctrl-U+0046"></command>
</if>
<link rel="import" href="chrome://resources/html/polymer.html">
-
<script src="crisper.js"></script></body></html> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/md_extensions/compiled_resources.gyp b/chromium/chrome/browser/resources/md_extensions/compiled_resources.gyp
deleted file mode 100644
index 7f1c7697bb1..00000000000
--- a/chromium/chrome/browser/resources/md_extensions/compiled_resources.gyp
+++ /dev/null
@@ -1,32 +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.
-{
- 'targets': [
- {
- 'target_name': 'manager',
- 'variables': {
- 'depends': [
- '../../../../ui/webui/resources/cr_elements/cr_search_field/cr_search_field.js',
- '../../../../ui/webui/resources/js/assert.js',
- '../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
- '../../../../ui/webui/resources/js/cr.js',
- '../../../../ui/webui/resources/js/i18n_behavior.js',
- '../../../../ui/webui/resources/js/promise_resolver.js',
- 'item.js',
- 'item_list.js',
- 'manager.js',
- 'service.js',
- 'sidebar.js',
- 'toolbar.js',
- ],
- 'externs': [
- '<(EXTERNS_DIR)/chrome_send.js',
- '<(EXTERNS_DIR)/developer_private.js',
- '<(EXTERNS_DIR)/management.js',
- ],
- },
- 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
- }
- ],
-}
diff --git a/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
new file mode 100644
index 00000000000..eb30953c84a
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
@@ -0,0 +1,97 @@
+# 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': 'detail_view',
+ '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',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp:neon-animatable-behavior-extracted',
+ '<(EXTERNS_GYP):developer_private',
+ 'item',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'extensions',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ 'manager',
+ 'service',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'item',
+ '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',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(EXTERNS_GYP):developer_private',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'item_list',
+ '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',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp:neon-animatable-behavior-extracted',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
+ '<(EXTERNS_GYP):developer_private',
+ 'item',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'manager',
+ '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',
+ '<(EXTERNS_GYP):developer_private',
+ 'item',
+ 'sidebar',
+ 'toolbar',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'service',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):developer_private',
+ '<(EXTERNS_GYP):management',
+ 'item',
+ 'manager',
+ 'sidebar',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'sidebar',
+ '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'],
+ },
+ {
+ '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/cr_elements/cr_search_field/compiled_resources2.gyp:cr_search_field',
+ ],
+ '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
new file mode 100644
index 00000000000..973c7d8652d
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/detail_view.html
@@ -0,0 +1,144 @@
+<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-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.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/animations/hero-animation.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/scale-down-animation.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html">
+
+<dom-module id="extensions-detail-view">
+ <style include="iron-flex"></style>
+ <template>
+ <style>
+ #main {
+ background-color: white;
+ height: 800px;
+ width: 90%;
+ }
+ #top-bar {
+ align-items: center;
+ color: var(--paper-grey-600);
+ display: flex;
+ height: 40px;
+ margin-bottom: 30px;
+ padding: 8px 12px 0;
+ }
+ #name {
+ flex-grow: 1;
+ }
+ .section {
+ border-bottom: var(--paper-grey-600);
+ padding: 12px 20px;
+ }
+ .section:last-child {
+ border: none;
+ }
+ .section-title {
+ color: var(--paper-grey-800);
+ }
+ .section-content {
+ color: var(--paper-grey-600);
+ }
+ .section paper-checkbox {
+ align-items: center;
+ display: flex;
+ min-height: 40px;
+ }
+ paper-checkbox {
+ --paper-checkbox-checked-color: var(--google-blue-500);
+ --primary-text-color: var(--paper-grey-800);
+ }
+ ul {
+ -webkit-padding-start: 20px;
+ margin: 0;
+ }
+ </style>
+ <div id="main">
+ <div id="top-bar">
+ <paper-icon-button id="close-button" icon="arrow-back"
+ on-click="onCloseButtonClick_"></paper-icon-button>
+ <span id="name">[[data.name]]</span>
+ <paper-icon-button id="open-in-webstore" icon="open-in-new">
+ </paper-icon-button>
+ <paper-icon-button id="options" icon="settings">
+ </paper-icon-button>
+ </div>
+ <div class="section">
+ <div class="section-title">$i18n{itemDescriptionLabel}</div>
+ <div class="section-content">[[data.description]]</div>
+ </div>
+ <div class="section">
+ <div class="section-title">$i18n{itemVersion}</div>
+ <div class="section-content">[[data.version]]</div>
+ </div>
+ <div class="section">
+ <div class="section-title">$i18n{itemPermissions}</div>
+ <div class="section-content">
+ <span id="no-permissions"
+ hidden$="[[hasPermissions_(data.permissions.splices)]]">
+ $i18n{itemPermissionsEmpty}
+ </span>
+ <ul id="permissions-list"
+ hidden$="[[!hasPermissions_(data.permissions.splices)]]">
+ <template is="dom-repeat" items="[[data.permissions]]">
+ <li>[[item]]</li>
+ </template>
+ </ul>
+ </div>
+ </div>
+ <template is="dom-if"
+ if="[[hasDependentExtensions_(data.dependentExtensions.splices)]]">
+ <div class="section">
+ <div class="section-title">$i18n{itemDependencies}</div>
+ <div class="section-content">
+ <ul id="dependent-extensions-list">
+ <template is="dom-repeat" items="[[data.dependentExtensions]]">
+ <li>[[computeDependentEntry_(item)]]</li>
+ </template>
+ </ul>
+ </div>
+ </div>
+ </template>
+ <template is="dom-if" if="[[shouldShowOptionsSection_(data.*)]]">
+ <div class="section layout vertical">
+ <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>
+ </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>
+ </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>
+ </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>
+ </template>
+ </div>
+ </template>
+ <div class="section">
+ <div class="section-title">$i18n{itemSource}</div>
+ <div class="section-content">TODO</div>
+ </div>
+ </div>
+ </template>
+ <script src="chrome://extensions/detail_view.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/detail_view.js b/chromium/chrome/browser/resources/md_extensions/detail_view.js
new file mode 100644
index 00000000000..0815cc20af3
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/detail_view.js
@@ -0,0 +1,114 @@
+// 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('extensions', function() {
+ 'use strict';
+
+ var DetailView = Polymer({
+ is: 'extensions-detail-view',
+
+ behaviors: [Polymer.NeonAnimatableBehavior],
+
+ properties: {
+ animationConfig: {
+ type: Object,
+ /** @suppress {checkTypes} Compiler doesn't recognize this.$.main. */
+ value: function() {
+ return {
+ entry: [{
+ name: 'hero-animation',
+ id: 'hero',
+ toPage: this
+ }],
+ exit: [{
+ name: 'scale-down-animation',
+ node: this.$.main,
+ transformOrigin: '50% 50%',
+ axis: 'y'
+ }],
+ };
+ },
+ },
+
+ /**
+ * The underlying ExtensionInfo for the details being displayed.
+ * @type {chrome.developerPrivate.ExtensionInfo}
+ */
+ data: Object,
+
+ /** @type {!extensions.ItemDelegate} */
+ delegate: Object,
+ },
+
+ ready: function() {
+ this.sharedElements = {hero: this.$.main};
+ },
+
+ /** @private */
+ onCloseButtonClick_: function() {
+ this.fire('close');
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ hasDependentExtensions_: function() {
+ return this.data.dependentExtensions.length > 0;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ hasPermissions_: function() {
+ return this.data.permissions.length > 0;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ shouldShowOptionsSection_: function() {
+ return this.data.incognitoAccess.isEnabled ||
+ this.data.fileAccess.isEnabled ||
+ this.data.runOnAllUrls.isEnabled ||
+ this.data.errorCollection.isEnabled;
+ },
+
+ /** @private */
+ onAllowIncognitoChange_: function() {
+ this.delegate.setItemAllowedIncognito(
+ this.data.id, this.$$('#allow-incognito').checked);
+ },
+
+ /** @private */
+ onAllowOnFileUrlsChange_: function() {
+ this.delegate.setItemAllowedOnFileUrls(
+ this.data.id, this.$$('#allow-on-file-urls').checked);
+ },
+
+ /** @private */
+ onAllowOnAllSitesChange_: function() {
+ this.delegate.setItemAllowedOnAllSites(
+ this.data.id, this.$$('#allow-on-all-sites').checked);
+ },
+
+ /** @private */
+ onCollectErrorsChange_: function() {
+ this.delegate.setItemCollectsErrors(
+ this.data.id, this.$$('#collect-errors').checked);
+ },
+
+ /**
+ * @param {!chrome.developerPrivate.DependentExtension} item
+ * @private
+ */
+ computeDependentEntry_: function(item) {
+ return loadTimeData.getStringF('itemDependentEntry', item.name, item.id);
+ },
+ });
+
+ return {DetailView: DetailView};
+});
diff --git a/chromium/chrome/browser/resources/md_extensions/extensions.html b/chromium/chrome/browser/resources/md_extensions/extensions.html
index 75c0b878fca..153b60fecc5 100644
--- a/chromium/chrome/browser/resources/md_extensions/extensions.html
+++ b/chromium/chrome/browser/resources/md_extensions/extensions.html
@@ -20,7 +20,9 @@
<body>
<extensions-manager></extensions-manager>
<link rel="import" href="chrome://resources/html/load_time_data.html">
- <link rel="import" href="chrome://extensions/strings.html">
<link rel="import" href="chrome://resources/html/i18n_template.html">
+ <link rel="import" href="chrome://extensions/strings.html">
+ <link rel="import" href="chrome://extensions/service.html">
+ <script src="chrome://extensions/extensions.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/md_extensions/extensions.js b/chromium/chrome/browser/resources/md_extensions/extensions.js
new file mode 100644
index 00000000000..a152964ff7d
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/extensions.js
@@ -0,0 +1,12 @@
+// 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.
+
+(function() {
+ 'use strict';
+ var manager = /** @type {extensions.Manager} */(
+ document.querySelector('extensions-manager'));
+ manager.readyPromiseResolver.promise.then(function() {
+ extensions.Service.getInstance().managerReady(manager);
+ });
+})();
diff --git a/chromium/chrome/browser/resources/md_extensions/icons.html b/chromium/chrome/browser/resources/md_extensions/icons.html
index 0d93dfb2e9b..34714cc4e7b 100644
--- a/chromium/chrome/browser/resources/md_extensions/icons.html
+++ b/chromium/chrome/browser/resources/md_extensions/icons.html
@@ -2,20 +2,59 @@
<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
<iron-iconset-svg name="extensions-icons" size="24">
- <svg>
+<svg>
+<defs>
+ <!-- Custom SVG (bettes). -->
+ <g id="unpacked">
<defs>
- <g id="pack">
- <path d="M0 0h24v24H0z" fill="none"></path>
- <path d="M19 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-5 6h-2v2h2v2h-2v-2h-2V9h2V7h-2V5h2v2h2v2zm0 8h-2v-2h-2v-2h2v2h2v2z"></path>
- </g>
- <g id="update">
- <defs>
- <path id="a" d="M0 0h24v24H0V0z"></path>
- </defs>
- <clipPath id="b">
- <use xlink:href="#a" overflow="visible"></use>
- </clipPath>
- <path d="M7.3 5.3c-1.3 1.3-2 3-2 4.7 0 1.7.7 3.4 2 4.7l1.2-1.2c-1-1-1.5-2.3-1.5-3.5 0-1.3.5-2.6 1.5-3.5L7.3 5.3zm11.8-2.4l-1.2 1.2c1.6 1.6 2.4 3.8 2.4 5.9s-.8 4.3-2.4 5.9l1.2 1.2c2-2 2.9-4.5 2.9-7.1s-1-5.1-2.9-7.1zm-13 1.2L4.9 2.9C3 4.9 2 7.4 2 10s1 5.1 2.9 7.1l1.2-1.2c-1.6-1.6-2.4-3.8-2.4-5.9s.8-4.3 2.4-5.9zm10.6 1.2l-1.2 1.2c1 1 1.5 2.3 1.5 3.5 0 1.3-.5 2.6-1.5 3.5l1.2 1.2c1.3-1.3 2-3 2-4.7-.1-1.7-.7-3.4-2-4.7zM12 7.5c-1.4 0-2.5 1.1-2.5 2.5 0 1 .6 1.9 1.5 2.3V21h2v-8.7c.9-.4 1.5-1.3 1.5-2.3 0-1.4-1.1-2.5-2.5-2.5z" clip-path="url(#b)"></path>
+ <style>
+ .cls-1 {
+ fill: none;
+ }
+ </style>
+ </defs>
+ <path class="cls-1" d="M0,0H24V24H0V0Z"></path>
+ <circle cx="9" cy="12" r="1"></circle>
+ <path d="M20,5H4A2,2,0,0,0,2,7V17a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V7A2,2,0,0,0,20,5ZM9,17a5,5,0,1,1,5-5A5,5,0,0,1,9,17Zm11,1a1,1,0,1,1,1-1A1,1,0,0,1,20,18ZM20,8a1,1,0,1,1,1-1A1,1,0,0,1,20,8Z"></path>
+ </g>
+
+ <!-- SVG from Google. -->
+ <g id="store" width="24px" height="24px" viewBox="0 0 192 192">
+ <defs>
+ <path id="a" d="M8 20v140c0 6.6 5.4 12 12 12h152c6.6 0 12-5.4 12-12V20H8zm108 32H76c-4.42 0-8-3.58-8-8s3.58-8 8-8h40c4.42 0 8 3.58 8 8s-3.58 8-8 8z"></path>
+ </defs>
+ <clipPath id="b">
+ <use xlink:href="#a" overflow="visible"></use>
+ </clipPath>
+ <path clip-path="url(#b)" fill="#eee" d="M8 20h176v152H8z"></path>
+ <path fill="#fff" d="M116 36H76c-4.42 0-8 3.58-8 8s3.58 8 8 8h40c4.42 0 8-3.58 8-8s-3.58-8-8-8z" clip-path="url(#b)"></path>
+ <g clip-path="url(#b)">
+ <defs>
+ <circle id="c" cx="96" cy="160" r="76"></circle>
+ </defs>
+ <clipPath id="d">
+ <use xlink:href="#c" overflow="visible"></use>
+ </clipPath>
+ <path d="M32.07 84v93.27h34.01L96 125.45h76V84zm0 0v93.27h34.01L96 125.45h76V84z" clip-path="url(#d)" fill="#DB4437"></path>
+ <path d="M20 236h72.34l33.58-33.58v-25.14l-59.84-.01L20 98.24zm0 0h72.34l33.58-33.58v-25.14l-59.84-.01L20 98.24z" clip-path="url(#d)" fill="#0F9D58"></path>
+ <path d="M96 125.45l29.92 51.82L92.35 236H172V125.45zm0 0l29.92 51.82L92.35 236H172V125.45z" clip-path="url(#d)" fill="#FFCD40"></path>
+ <g clip-path="url(#d)">
+ <circle fill="#F1F1F1" cx="96" cy="160" r="34.55"></circle>
+ <circle fill="#4285F4" cx="96" cy="160" r="27.64"></circle>
</g>
- </svg>
+ </g>
+ <path clip-path="url(#b)" fill="#212121" fill-opacity=".05" d="M8 20h176v76H8z"></path>
+ <path fill="#212121" fill-opacity=".02" d="M8 95h176v1H8z"></path>
+ <path fill="#fff" fill-opacity=".05" d="M8 96h176v1H8z"></path>
+ <path fill="#212121" fill-opacity=".02" d="M116 52H76c-4.25 0-7.72-3.32-7.97-7.5-.02.17-.03.33-.03.5 0 4.42 3.58 8 8 8h40c4.42 0 8-3.58 8-8 0-.17-.01-.33-.03-.5-.25 4.18-3.72 7.5-7.97 7.5zM8 20v1h176v-1H8z"></path>
+ <path fill="#231F20" fill-opacity=".1" d="M76 36h40c4.25 0 7.72 3.32 7.97 7.5.01-.17.03-.33.03-.5 0-4.42-3.58-8-8-8H76c-4.42 0-8 3.58-8 8 0 .17.01.33.03.5.25-4.18 3.72-7.5 7.97-7.5zm96 135H20c-6.6 0-12-5.4-12-12v1c0 6.6 5.4 12 12 12h152c6.6 0 12-5.4 12-12v-1c0 6.6-5.4 12-12 12z"></path>
+ <radialGradient id="e" cx="7.502" cy="19.344" r="227.596" gradientUnits="userSpaceOnUse">
+ <stop offset="0" stop-color="#fff" stop-opacity=".1"></stop>
+ <stop offset="1" stop-color="#fff" stop-opacity="0"></stop>
+ </radialGradient>
+ <path fill="url(#e)" d="M8 20v140c0 6.6 5.4 12 12 12h152c6.6 0 12-5.4 12-12V20H8zm108 32H76c-4.42 0-8-3.58-8-8s3.58-8 8-8h40c4.42 0 8 3.58 8 8s-3.58 8-8 8z"></path>
+ <path fill="none" d="M0 0h192v192H0z"></path>
+ </g>
+</defs>
+</svg>
</iron-icon-set>
diff --git a/chromium/chrome/browser/resources/md_extensions/item.css b/chromium/chrome/browser/resources/md_extensions/item.css
index 447cd33833b..73a19bca041 100644
--- a/chromium/chrome/browser/resources/md_extensions/item.css
+++ b/chromium/chrome/browser/resources/md_extensions/item.css
@@ -2,110 +2,161 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-.content-section {
- padding: 20px;
+[hidden] {
+ display: none !important;
}
#icon-wrapper {
- align-self: center;
+ align-self: flex-start;
display: flex;
- justify-content: center;
- margin: 0 24px;
+ padding: 6px;
}
#icon {
- height: 32px;
- width: 32px;
+ height: 36px;
+ width: 36px;
+}
+
+#card,
+#card-wrapper {
+ min-height: 154px;
+ width: 400px;
}
-/* TODO(devlin): Combine this with downloads style. */
#card-wrapper {
background: white;
- box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .05), 0 1px 4px 0 rgba(0, 0, 0, .08),
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .05),
+ 0 1px 4px 0 rgba(0, 0, 0, .08),
0 3px 1px -2px rgba(0, 0, 0, .2);
- color: #5A5A5A;
- min-height: 103px;
- width: 622px;
}
#card {
display: flex;
+ flex-direction: column;
+ font-size: 13px;
}
#card.disabled {
opacity: 0.6;
}
-#content {
- -webkit-border-start: 1px solid #C5C5C5;
+#main {
display: flex;
- flex: 1;
- flex-direction: column;
+ flex-grow: 1;
+ padding: 16px;
+}
+
+#content {
+ -webkit-margin-start: 24px;
+ width: 100%;
+}
+
+#name-and-version {
+ margin-bottom: 4px;
}
#name {
- color: #222;
- font-weight: 500;
+ -webkit-margin-end: 8px;
+ color: var(--paper-grey-800);
+}
+
+#description {
margin-bottom: 8px;
}
-#controls {
- padding-top: 20px;
+#version,
+#extension-id,
+#inspect-views,
+#button-strip {
+ color: var(--paper-grey-600);
}
-#version {
- -webkit-margin-start: 50px;
- flex: 1;
+#description,
+#extension-id,
+#inspect-views {
+ line-height: 20px;
}
-.checkbox {
- --paper-checkbox-checked-color: rgb(66, 133, 244);
- --primary-text-color: #5A5A5A;
+#inspect-views paper-button {
+ color: var(--google-blue-700);
}
-#details-container {
- border-top: 1px solid #C5C5C5;
- color: #5A5A5A;
+#button-strip {
+ border-top: 1px solid var(--paper-grey-400);
}
-#extension-id {
- padding-bottom: 10px;
+#source-indicator {
+ align-items: center;
+ align-self: flex-end;
+ border-radius: 0 2px;
+ color: var(--paper-grey-800);
+ display: flex;
+ min-height: 32px;
+ padding: 0 8px;
+ position: absolute;
+ white-space: nowrap;
}
-#inspect-views {
- padding-bottom: 20px;
+#source-indicator iron-icon {
+ height: 16px;
+ width: 16px;
}
-#inspect-views paper-button {
- color: rgb(51, 103, 214);
+#source-indicator span {
+ -webkit-margin-end: 8px;
+ display: none;
+}
+
+#source-indicator:hover {
+ background-color: var(--paper-grey-700);
+ color: white;
}
-paper-button {
- /* TODO(devlin): Decide whether all webui should do this. */
+#source-indicator:hover span {
+ display: block;
+}
+
+paper-button,
+paper-toggle-button {
cursor: pointer;
}
-#warnings-container {
- border-top: 1px solid #C5C5C5;
+#button-strip paper-button {
+ align-items: center;
display: flex;
- padding: 10px;
+ margin: 4px;
+ min-height: 32px;
+ padding: 0 12px;
+ text-transform: uppercase;
+}
+
+#enable-toggle {
+ -webkit-margin-end: 16px;
}
-#warnings-container div {
- color: #333;
+.warning {
+ align-items: center;
+ display: flex;
+ font-size: 13px;
+ justify-content: space-between;
+ padding: 12px 16px;
}
-#warnings-container iron-icon {
- -webkit-margin-end: 10px;
- flex-shrink: 0;
+.warning paper-button {
+ -webkit-margin-start: 12px;
+ align-items: center;
+ display: flex;
+ text-transform: uppercase;
}
-#warnings-container.severe iron-icon {
- color: rgb(219, 68, 55);
+.severe.warning {
+ background-color: var(--paper-red-50);
+ color: var(--paper-red-700);
}
-#warnings-container.mild iron-icon {
- color: rgb(240, 147, 0);
+.mild.warning {
+ background-color: var(--paper-yellow-50);
+ color: var(--paper-grey-600);
}
#blacklisted-warning:empty {
diff --git a/chromium/chrome/browser/resources/md_extensions/item.html b/chromium/chrome/browser/resources/md_extensions/item.html
index c78cc51d613..39add9135fe 100644
--- a/chromium/chrome/browser/resources/md_extensions/item.html
+++ b/chromium/chrome/browser/resources/md_extensions/item.html
@@ -3,81 +3,81 @@
<link rel="import" href="chrome://resources/html/i18n_behavior.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://extensions/icons.html">
<link rel="import" href="chrome://extensions/strings.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-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/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-toggle-button/paper-toggle-button.html">
<dom-module id="extensions-item">
+ <style include="iron-flex"></style>
<template>
<div id="card-wrapper" class$="[[computeClasses_(data.state)]]">
<div id="card">
- <div id="icon-wrapper">
- <img alt="" id="icon" src="[[data.iconUrl]]">
- </div>
- <div id="content">
- <div class="content-section">
- <div class="layout horizontal justified center">
+ <template is="dom-if"
+ if="[[computeSourceIndicatorIcon_(data.*)]]">
+ <div id="source-indicator">
+ <span>[[computeSourceIndicatorText_(data.*)]]</span>
+ <iron-icon icon="[[computeSourceIndicatorIcon_(data.*)]]">
+ </iron-icon>
+ </div>
+ </template>
+ <div id="main">
+ <div id="icon-wrapper">
+ <img alt="" id="icon" src="[[data.iconUrl]]">
+ </div>
+ <div id="content">
+ <div id="name-and-version" class="layout horizontal center">
<div id="name">[[data.name]]</div>
- <paper-icon-button icon="[[computeExpandIcon_(showingDetails_)]]"
- id="show-details" on-tap="onShowDetailsTap_">
- </paper-icon-button>
+ <template is="dom-if" if="[[inDevMode]]">
+ <span id="version">[[data.version]]</span>
+ </template>
</div>
<div id="description">[[data.description]]</div>
- <div id="controls" class="layout horizontal center">
- <paper-checkbox id="enabled" class="checkbox"
- checked="[[isEnabled_(data.state)]]"
- on-change="onEnableChange_">
- [[computeEnableCheckboxLabel_(data.state)]]
- </paper-checkbox>
- <span id="version">[[data.version]]</span>
- <paper-icon-button icon="delete" id="delete-button"
- on-tap="onDeleteTap_"></paper-icon-button>
- </div>
- </div>
- <template is="dom-if" if="[[showingDetails_]]">
- <div id="details-container" class="content-section">
- <template is="dom-if" if="[[inDevMode]]">
- <div id="extension-id"></div>
+ <template is="dom-if" if="[[inDevMode]]">
+ <div id="extension-id">[[data.id]]</div>
<div id="inspect-views">
- <span>[[i18n('itemInspectViews')]]</span>
+ <span>$i18n{itemInspectViews}</span>
<template is="dom-repeat" items="[[data.views]]">
<paper-button on-tap="onInspectTap_">
[[computeInspectLabel_(item)]]
</paper-button>
</template>
</div>
- </template>
- <div class="layout horizontal justified center">
- <paper-checkbox id="allow-incognito" class="checkbox"
- checked="[[data.incognitoAccess.isActive]]"
- on-change="onAllowIncognitoChange_">
- [[i18n('itemAllowIncognito')]]
- </paper-checkbox>
- <paper-button id="details-button" on-tap="onDetailsTap_">
- [[i18n('itemDetails')]]
- </paper-button>
</div>
- </div>
- </template>
+ </template>
+ </div>
+ </div>
+ <div id="button-strip" class="layout horizontal">
+ <div class="layout flex horizontal center">
+ <paper-button id="details-button" on-tap="onDetailsTap_">
+ $i18n{itemDetails}
+ </paper-button>
+ <paper-button id="remove-button" on-tap="onRemoveTap_">
+ $i18n{itemRemove}
+ </paper-button>
+ </div>
+ <paper-toggle-button id="enable-toggle"
+ checked="[[isEnabled_(data.state)]]" on-change="onEnableChange_">
+ </paper-toggle-button>
</div>
</div>
<template is="dom-if" if="[[hasWarnings_(data.*)]]">
- <div id="warnings-container"
- class$="[[computeWarningsClasses_(data.blacklistText)]]">
- <iron-icon icon="warning"></iron-icon>
- <div>
- <div id="corrupted-warning"
- hidden="[[!data.disableReasons.corruptInstall]]">
- [[i18n('itemCorruptInstall')]]
- </div>
- <div id="suspicious-warning"
- hidden="[[!data.disableReasons.suspiciousInstall]]">
- [[i18n('itemSuspiciousInstall')]]
- </div>
- <div id="blacklisted-warning">[[data.blacklistText]]</div>
- </div>
+ <div id="suspicious-warning" class="warning mild"
+ hidden$="[[!data.disableReasons.suspiciousInstall]]">
+ $i18n{itemSuspiciousInstall}
+ </div>
+ <div id="corrupted-warning" class="warning severe"
+ hidden$="[[!data.disableReasons.corruptInstall]]">
+ <span>$i18n{itemCorruptInstall}</span>
+ <paper-button id="repair-button" on-tap="onRepairTap_">
+ $i18n{itemRepair}
+ </paper-button>
</div>
+ <div id="blacklisted-warning" class="warning severe"><!-- No whitespace
+ -->[[data.blacklistText]]<!-- ... so we can use :empty in css
+ --></div>
</template>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/md_extensions/item.js b/chromium/chrome/browser/resources/md_extensions/item.js
index d7a9858ad64..d2910d97c04 100644
--- a/chromium/chrome/browser/resources/md_extensions/item.js
+++ b/chromium/chrome/browser/resources/md_extensions/item.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.
+// 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() {
/** @interface */
var ItemDelegate = function() {};
@@ -16,9 +25,6 @@ cr.define('extensions', function() {
*/
setItemEnabled: assertNotReached,
- /** @param {string} id */
- showItemDetails: assertNotReached,
-
/**
* @param {string} id
* @param {boolean} isAllowedIncognito
@@ -26,10 +32,31 @@ cr.define('extensions', function() {
setItemAllowedIncognito: assertNotReached,
/**
+ * @param {string} id
+ * @param {boolean} isAllowedOnFileUrls
+ */
+ setItemAllowedOnFileUrls: assertNotReached,
+
+ /**
+ * @param {string} id
+ * @param {boolean} isAllowedOnAllSites
+ */
+ setItemAllowedOnAllSites: assertNotReached,
+
+ /**
+ * @param {string} id
+ * @param {boolean} collectsErrors
+ */
+ setItemCollectsErrors: assertNotReached,
+
+ /**
* @param {string} id,
* @param {chrome.developerPrivate.ExtensionView} view
*/
inspectItemView: assertNotReached,
+
+ /** @param {string} id */
+ repairItem: assertNotReached,
};
var Item = Polymer({
@@ -81,29 +108,19 @@ cr.define('extensions', function() {
},
/** @private */
- onShowDetailsTap_: function() {
- this.showingDetails_ = !this.showingDetails_;
- },
-
- /** @private */
- onDeleteTap_: function() {
+ onRemoveTap_: function() {
this.delegate.deleteItem(this.data.id);
},
/** @private */
onEnableChange_: function() {
- this.delegate.setItemEnabled(this.data.id, this.$.enabled.checked);
+ this.delegate.setItemEnabled(this.data.id,
+ this.$['enable-toggle'].checked);
},
/** @private */
onDetailsTap_: function() {
- this.delegate.showItemDetails(this.data.id);
- },
-
- /** @private */
- onAllowIncognitoChange_: function() {
- this.delegate.setItemAllowedIncognito(
- this.data.id, this.$$('#allow-incognito').checked);
+ this.fire('extension-item-show-details', {element: this});
},
/**
@@ -114,6 +131,11 @@ cr.define('extensions', function() {
this.delegate.inspectItemView(this.data.id, e.model.item);
},
+ /** @private */
+ onRepairTap_: function() {
+ this.delegate.repairItem(this.data.id);
+ },
+
/**
* Returns true if the extension is enabled, including terminated
* extensions.
@@ -136,14 +158,59 @@ cr.define('extensions', function() {
return this.isEnabled_() ? 'enabled' : 'disabled';
},
- /** @private */
- computeExpandIcon_: function() {
- return this.showingDetails_ ? 'expand-less' : 'expand-more';
+ /**
+ * @return {SourceType}
+ * @private
+ */
+ computeSource_: function() {
+ if (this.data.controlledInfo &&
+ this.data.controlledInfo.type ==
+ chrome.developerPrivate.ControllerType.POLICY) {
+ return SourceType.POLICY;
+ } else if (this.data.location ==
+ chrome.developerPrivate.Location.THIRD_PARTY) {
+ return SourceType.SIDELOADED;
+ } else if (this.data.location ==
+ chrome.developerPrivate.Location.UNPACKED) {
+ return SourceType.UNPACKED;
+ }
+ return SourceType.WEBSTORE;
},
- /** @private */
- computeEnableCheckboxLabel_: function() {
- return this.i18n(this.isEnabled_() ? 'itemEnabled' : 'itemDisabled');
+ /**
+ * @return {string}
+ * @private
+ */
+ computeSourceIndicatorIcon_: function() {
+ switch (this.computeSource_()) {
+ case SourceType.POLICY:
+ return 'communication:business';
+ case SourceType.SIDELOADED:
+ return 'input';
+ case SourceType.UNPACKED:
+ return 'extensions-icons:unpacked';
+ case SourceType.WEBSTORE:
+ return '';
+ }
+ assertNotReached();
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ computeSourceIndicatorText_: function() {
+ switch (this.computeSource_()) {
+ 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 '';
+ }
+ assertNotReached();
},
/**
diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.css b/chromium/chrome/browser/resources/md_extensions/item_list.css
index 9163291f92b..4b8f0a688c6 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_list.css
+++ b/chromium/chrome/browser/resources/md_extensions/item_list.css
@@ -2,14 +2,15 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-h2 {
- color: #5a5a5a;
- font-size: 1.1em;
- font-weight: normal;
- margin-bottom: 0;
- margin-top: 30px;
+:host {
+ @apply(--layout-vertical);
+}
+
+iron-list {
+ @apply(--layout-flex);
+ margin-top: 18px;
}
.wrapper {
- padding: 10px 0;
+ padding: 6px;
}
diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.html b/chromium/chrome/browser/resources/md_extensions/item_list.html
index b3c08940e1e..fba5cf77d7b 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_list.html
+++ b/chromium/chrome/browser/resources/md_extensions/item_list.html
@@ -1,13 +1,15 @@
<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-list/iron-list.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/hero-animation.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html">
<link rel="import" href="chrome://extensions/item.html">
<dom-module id="extensions-item-list">
<template>
- <h2>[[header]]</h2>
<iron-list id="list" items="[[computeShownItems_(items.*, filter)]]"
- as="item">
+ as="item" grid>
<template>
<div class="wrapper">
<extensions-item data="[[item]]" delegate="[[delegate]]"
diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.js b/chromium/chrome/browser/resources/md_extensions/item_list.js
index 2e6d9c3257d..ede5d1c6dd5 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_list.js
+++ b/chromium/chrome/browser/resources/md_extensions/item_list.js
@@ -6,15 +6,31 @@ cr.define('extensions', function() {
var ItemList = Polymer({
is: 'extensions-item-list',
+ behaviors: [
+ Polymer.NeonAnimatableBehavior,
+ Polymer.IronResizableBehavior
+ ],
+
properties: {
+ animationConfig: {
+ type: Object,
+ value: function() {
+ return {
+ exit: [{
+ name: 'hero-animation',
+ id: 'hero',
+ fromPage: this,
+ }],
+ };
+ },
+ },
+
/** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */
items: Array,
/** @type {extensions.ItemDelegate} */
delegate: Object,
- header: String,
-
inDevMode: {
type: Boolean,
value: false,
@@ -25,6 +41,7 @@ cr.define('extensions', function() {
listeners: {
'list.extension-item-size-changed': 'itemSizeChanged_',
+ 'list.extension-item-show-details': 'showItemDetails_',
},
/**
@@ -38,6 +55,15 @@ cr.define('extensions', function() {
},
/**
+ * Called right before an item enters the detailed view.
+ * @param {CustomEvent} e
+ * @private
+ */
+ showItemDetails_: function(e) {
+ this.sharedElements = {hero: e.detail.element};
+ },
+
+ /**
* Computes the list of items to be shown.
* @param {Object} changeRecord The changeRecord for |items|.
* @param {string} filter The updated filter string.
diff --git a/chromium/chrome/browser/resources/md_extensions/manager.css b/chromium/chrome/browser/resources/md_extensions/manager.css
index cef4d23721d..5ed617ae418 100644
--- a/chromium/chrome/browser/resources/md_extensions/manager.css
+++ b/chromium/chrome/browser/resources/md_extensions/manager.css
@@ -2,6 +2,10 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
+[hidden] {
+ display: none !important;
+}
+
:host {
height: 100%;
}
@@ -12,7 +16,7 @@
};
}
-#items {
+#pages {
-webkit-margin-start: 30px;
overflow-y: auto;
padding-bottom: 30px;
diff --git a/chromium/chrome/browser/resources/md_extensions/manager.html b/chromium/chrome/browser/resources/md_extensions/manager.html
index dc736958c58..908c9304d0e 100644
--- a/chromium/chrome/browser/resources/md_extensions/manager.html
+++ b/chromium/chrome/browser/resources/md_extensions/manager.html
@@ -1,7 +1,11 @@
<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/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">
<link rel="import" href="chrome://extensions/item_list.html">
<link rel="import" href="chrome://extensions/service.html">
<link rel="import" href="chrome://extensions/sidebar.html">
@@ -12,28 +16,18 @@
<paper-header-panel id="panel">
<extensions-toolbar class="paper-header" id="toolbar">
</extensions-toolbar>
- <extensions-sidebar in-dev-mode="[[inDevMode]]"
- hide-extensions-button="[[computeListHidden_(extensions, extensions.splices)]]"
- hide-apps-button="[[computeListHidden_(apps, apps.splices)]]"
- hide-websites-button="[[computeListHidden_(websites, websites.splices)]]">
+ <extensions-sidebar in-dev-mode="[[inDevMode]]">
</extensions-sidebar>
- <div id="items">
- <extensions-item-list id="extensions-list" items="[[extensions]]"
- delegate="[[service]]" header="[[i18n('sidebarExtensions')]]"
- in-dev-mode="[[inDevMode]]" filter="[[filter]]"
- hidden$="[[computeListHidden_(extensions, extensions.splices)]]">
+ <neon-animated-pages id="pages" selected="0">
+ <extensions-item-list id="items-list" items="[[extensions]]"
+ delegate="[[itemDelegate]]" in-dev-mode="[[inDevMode]]"
+ filter="[[filter]]"
+ hidden$="[[computeListHidden_(extensions, extensions.splices, apps, apps.splices)]]">
</extensions-item-list>
- <extensions-item-list id="apps-list" items="[[apps]]"
- delegate="[[service]]" header="[[i18n('sidebarApps')]]"
- in-dev-mode="[[inDevMode]]" filter="[[filter]]"
- hidden$="[[computeListHidden_(apps, apps.splices)]]">
- </extensions-item-list>
- <extensions-item-list id="websites-list" items="[[websites]]"
- delegate="[[service]]" header="[[i18n('sidebarWebsites')]]"
- in-dev-mode="[[inDevMode]]" filter="[[filter]]"
- hidden$="[[computeListHidden_(websites, websites.splices)]]">
- </extensions-item-list>
- </div>
+ <extensions-detail-view id="details-view" delegate="[[itemDelegate]]"
+ on-close="onDetailsViewClose_">
+ </extensions-detail-view>
+ </neon-animated-pages>
</paper-header-panel>
</template>
<link rel="import" type="css" href="chrome://extensions/manager.css">
diff --git a/chromium/chrome/browser/resources/md_extensions/manager.js b/chromium/chrome/browser/resources/md_extensions/manager.js
index 60c33b48dc5..a08641f9be6 100644
--- a/chromium/chrome/browser/resources/md_extensions/manager.js
+++ b/chromium/chrome/browser/resources/md_extensions/manager.js
@@ -36,8 +36,8 @@ cr.define('extensions', function() {
/** @type {extensions.Sidebar} */
sidebar: Object,
- /** @type {extensions.Service} */
- service: Object,
+ /** @type {extensions.ItemDelegate} */
+ itemDelegate: Object,
inDevMode: {
type: Boolean,
@@ -60,27 +60,28 @@ cr.define('extensions', function() {
type: Array,
value: function() { return []; },
},
-
- /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */
- websites: {
- type: Array,
- value: function() { return []; },
- },
},
behaviors: [
I18nBehavior,
],
+ listeners: {
+ 'items-list.extension-item-show-details': 'showItemDetails_',
+ },
+
+ created: function() {
+ this.readyPromiseResolver = new PromiseResolver();
+ },
+
ready: function() {
/** @type {extensions.Sidebar} */
this.sidebar =
/** @type {extensions.Sidebar} */(this.$$('extensions-sidebar'));
- this.service = extensions.Service.getInstance();
- this.service.managerReady(this);
- this.scrollHelper_ = new ScrollHelper(this);
- this.sidebar.setScrollDelegate(this.scrollHelper_);
+ this.listHelper_ = new ListHelper(this);
+ this.sidebar.setListDelegate(this.listHelper_);
this.$.toolbar.setSearchDelegate(new SearchHelper(this));
+ this.readyPromiseResolver.resolve();
},
/**
@@ -94,8 +95,6 @@ cr.define('extensions', function() {
switch (type) {
case ExtensionType.HOSTED_APP:
case ExtensionType.LEGACY_PACKAGED_APP:
- listId = 'websites';
- break;
case ExtensionType.PLATFORM_APP:
listId = 'apps';
break;
@@ -125,11 +124,11 @@ cr.define('extensions', function() {
},
/**
- * @param {!Array<!chrome.developerPrivate.ExtensionInfo>} list
* @return {boolean} Whether the list should be visible.
+ * @private
*/
- computeListHidden_: function(list) {
- return list.length == 0;
+ computeListHidden_: function() {
+ return this.$['items-list'].items.length == 0;
},
/**
@@ -173,35 +172,46 @@ cr.define('extensions', function() {
assert(index >= 0);
this.splice(listId, index, 1);
},
+
+ /**
+ * Shows the detailed view for a given item.
+ * @param {CustomEvent} e
+ * @private
+ */
+ showItemDetails_: function(e) {
+ this.$['details-view'].set('data', assert(e.detail.element.data));
+ this.$.pages.selected = 1;
+ },
+
+ /** @private */
+ onDetailsViewClose_: function() {
+ this.$.pages.selected = 0;
+ }
});
/**
* @param {extensions.Manager} manager
* @constructor
- * @implements {extensions.SidebarScrollDelegate}
+ * @implements {extensions.SidebarListDelegate}
*/
- function ScrollHelper(manager) {
- this.items_ = manager.$.items;
+ function ListHelper(manager) {
+ this.manager_ = manager;
}
- ScrollHelper.prototype = {
- /** @override */
- scrollToExtensions: function() {
- this.items_.scrollTop =
- this.items_.querySelector('#extensions-list').offsetTop;
- },
-
+ ListHelper.prototype = {
/** @override */
- scrollToApps: function() {
- this.items_.scrollTop =
- this.items_.querySelector('#apps-list').offsetTop;
- },
-
- /** @override */
- scrollToWebsites: function() {
- this.items_.scrollTop =
- this.items_.querySelector('#websites-list').offsetTop;
- },
+ showType: function(type) {
+ var items;
+ switch (type) {
+ case extensions.ShowingType.EXTENSIONS:
+ items = this.manager_.extensions;
+ break;
+ case extensions.ShowingType.APPS:
+ items = this.manager_.apps;
+ break;
+ }
+ this.manager_.$['items-list'].set('items', assert(items));
+ }
};
/**
diff --git a/chromium/chrome/browser/resources/md_extensions/service.js b/chromium/chrome/browser/resources/md_extensions/service.js
index a0837206eb1..8451b067a1f 100644
--- a/chromium/chrome/browser/resources/md_extensions/service.js
+++ b/chromium/chrome/browser/resources/md_extensions/service.js
@@ -14,15 +14,14 @@ cr.define('extensions', function() {
Service.prototype = {
/** @private {boolean} */
- promptIsShowing_: false,
+ isDeleting_: false,
/** @param {extensions.Manager} manager */
managerReady: function(manager) {
/** @private {extensions.Manager} */
this.manager_ = manager;
- /** @private {extensions.Sidebar} */
- this.sidebar_ = manager.sidebar;
- this.sidebar_.setDelegate(this);
+ this.manager_.sidebar.setDelegate(this);
+ this.manager_.set('itemDelegate', this);
chrome.developerPrivate.onProfileStateChanged.addListener(
this.onProfileStateChanged_.bind(this));
chrome.developerPrivate.onItemStateChanged.addListener(
@@ -44,8 +43,6 @@ cr.define('extensions', function() {
* @private
*/
onProfileStateChanged_: function(profileInfo) {
- /** @private {chrome.developerPrivate.ProfileInfo} */
- this.profileInfo_ = profileInfo;
this.manager_.set('inDevMode', profileInfo.inDeveloperMode);
},
@@ -93,15 +90,15 @@ cr.define('extensions', function() {
/** @override */
deleteItem: function(id) {
- if (this.promptIsShowing_)
+ if (this.isDeleting_)
return;
- this.promptIsShowing_ = true;
+ this.isDeleting_ = true;
chrome.management.uninstall(id, {showConfirmDialog: true}, function() {
// The "last error" was almost certainly the user canceling the dialog.
// Do nothing. We only check it so we don't get noisy logs.
/** @suppress {suspiciousCode} */
chrome.runtime.lastError;
- this.promptIsShowing_ = false;
+ this.isDeleting_ = false;
}.bind(this));
},
@@ -111,9 +108,6 @@ cr.define('extensions', function() {
},
/** @override */
- showItemDetails: function(id) {},
-
- /** @override */
setItemAllowedIncognito: function(id, isAllowedIncognito) {
chrome.developerPrivate.updateExtensionConfiguration({
extensionId: id,
@@ -122,6 +116,30 @@ cr.define('extensions', function() {
},
/** @override */
+ setItemAllowedOnFileUrls: function(id, isAllowedOnFileUrls) {
+ chrome.developerPrivate.updateExtensionConfiguration({
+ extensionId: id,
+ fileAccess: isAllowedOnFileUrls,
+ });
+ },
+
+ /** @override */
+ setItemAllowedOnAllSites: function(id, isAllowedOnAllSites) {
+ chrome.developerPrivate.updateExtensionConfiguration({
+ extensionId: id,
+ runOnAllUrls: isAllowedOnAllSites,
+ });
+ },
+
+ /** @override */
+ setItemCollectsErrors: function(id, collectsErrors) {
+ chrome.developerPrivate.updateExtensionConfiguration({
+ extensionId: id,
+ errorCollection: collectsErrors,
+ });
+ },
+
+ /** @override */
inspectItemView: function(id, view) {
chrome.developerPrivate.openDevTools({
extensionId: id,
@@ -132,6 +150,11 @@ cr.define('extensions', function() {
},
/** @override */
+ repairItem: function(id) {
+ chrome.developerPrivate.repairExtension(id);
+ },
+
+ /** @override */
setProfileInDevMode: function(inDevMode) {
chrome.developerPrivate.updateProfileConfiguration(
{inDeveloperMode: inDevMode});
diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.css b/chromium/chrome/browser/resources/md_extensions/sidebar.css
index 30618144e0b..c13d31838b8 100644
--- a/chromium/chrome/browser/resources/md_extensions/sidebar.css
+++ b/chromium/chrome/browser/resources/md_extensions/sidebar.css
@@ -3,11 +3,15 @@
* found in the LICENSE file. */
:host {
- -webkit-margin-start: 30px;
margin-top: 30px;
white-space: nowrap;
}
+#section-menu,
+.section-item {
+ -webkit-margin-start: 20px;
+}
+
#section-menu {
--paper-menu-background-color: {
transparent;
@@ -20,30 +24,36 @@
padding: 0;
}
+#more-extensions {
+ display: flex;
+ text-decoration: none;
+}
+
paper-item {
- -webkit-margin-start: 0;
- -webkit-padding-start: 0;
color: #5A5A5A;
cursor: pointer;
font-size: 88%;
+ padding: 0;
}
-.section-menu-item span {
- -webkit-margin-start: 15px;
-}
-
-#devtools-container {
- border-bottom: 1px solid #C5C5C5;
- border-top: 1px solid #C5C5C5;
- margin: 10px 0;
+.section-menu-item iron-icon,
+.section-item iron-icon {
+ -webkit-margin-end: 15px;
}
#developer-mode-checkbox {
--paper-checkbox-checked-color: rgb(66, 133, 244);
--primary-text-color: #5A5A5A;
- -webkit-margin-start: 10px;
+}
+
+#developer-mode {
+ display: flex;
+}
+
+#developer-mode span {
+ flex-grow: 1;
}
#devtools-controls {
- -webkit-margin-start: 20px;
+ border-top: 1px solid grey;
}
diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.html b/chromium/chrome/browser/resources/md_extensions/sidebar.html
index 418dee24d3e..22950e646fe 100644
--- a/chromium/chrome/browser/resources/md_extensions/sidebar.html
+++ b/chromium/chrome/browser/resources/md_extensions/sidebar.html
@@ -1,6 +1,7 @@
<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-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-item/paper-item.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
@@ -8,54 +9,51 @@
<dom-module id="extensions-sidebar">
<template>
- <paper-menu id="section-menu">
+ <paper-menu id="section-menu" selected="0">
<paper-item class="section-menu-item" id="sections-extensions"
- on-tap="onExtensionsTap_" hidden$="[[hideExtensionsButton]]">
+ on-tap="onExtensionsTap_">
<iron-icon icon="extension"></iron-icon>
<span i18n-content="sidebarExtensions"></span>
</paper-item>
<paper-item class="section-menu-item" id="sections-apps"
- on-tap="onAppsTap_" hidden$="[[hideAppsButton]]">
+ on-tap="onAppsTap_">
<iron-icon icon="apps"></iron-icon>
<span i18n-content="sidebarApps"></span>
</paper-item>
- <paper-item class="section-menu-item" id="sections-websites"
- on-tap="onWebsitesTap_" hidden$="[[hideWebsitesButton]]">
- <iron-icon icon="cloud"></iron-icon>
- <span i18n-content="sidebarWebsites"></span>
- </paper-item>
</paper-menu>
- <div id="devtools-container">
- <paper-item id="developer-mode">
- <span i18n-content="developerMode"></span>
+ <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>
+ </a>
+ <paper-item class="section-item" id="keyboard-shortcuts">
+ <iron-icon icon="hardware:keyboard"></iron-icon>
+ <span>$i18n{keyboardShortcuts}</span>
+ </paper-item>
+ <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]]">
- <div id="devtools-controls">
- <paper-item class="section-menu-item" id="load-unpacked"
- on-tap="onLoadUnpackedTap_">
- <iron-icon icon="file-download"></iron-icon>
- <span>[[i18n('sidebarLoadUnpacked')]]</span>
- </paper-item>
- <paper-item class="section-menu-item" id="pack-extensions"
- on-tap="onPackTap_">
- <iron-icon icon="extensions-icons:pack"></iron-icon>
- <span>[[i18n('sidebarPack')]]</span>
- </paper-item>
- <paper-item class="section-menu-item" id="update-now"
- on-tap="onUpdateNowTap_">
- <iron-icon icon="extensions-icons:update"></iron-icon>
- <span>[[i18n('sidebarUpdateNow')]]</span>
- </paper-item>
- </div>
+ <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>
- <paper-item id="more-extensions" i18n-content="getMoreExtensions">
- </paper-item>
- <paper-item id="keyboard-shortcuts" i18n-content="keyboardShortcuts">
- </paper-item>
</template>
<link rel="import" type="css" href="chrome://extensions/sidebar.css">
<script src="chrome://extensions/sidebar.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.js b/chromium/chrome/browser/resources/md_extensions/sidebar.js
index 622c5ec3ada..65ec6fe0c05 100644
--- a/chromium/chrome/browser/resources/md_extensions/sidebar.js
+++ b/chromium/chrome/browser/resources/md_extensions/sidebar.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.
+cr.exportPath('extensions');
+
+// Declare this here to make closure compiler happy, and us sad.
+/** @enum {number} */
+extensions.ShowingType = {
+ EXTENSIONS: 0,
+ APPS: 1,
+};
+
cr.define('extensions', function() {
/** @interface */
var SidebarDelegate = function() {};
@@ -24,17 +33,14 @@ cr.define('extensions', function() {
};
/** @interface */
- var SidebarScrollDelegate = function() {};
-
- SidebarScrollDelegate.prototype = {
- /** Scrolls to the extensions section. */
- scrollToExtensions: assertNotReached,
+ var SidebarListDelegate = function() {};
- /** Scrolls to the apps section. */
- scrollToApps: assertNotReached,
-
- /** Scrolls to the websites section. */
- scrollToWebsites: assertNotReached,
+ SidebarListDelegate.prototype = {
+ /**
+ * Shows the given type of item.
+ * @param {extensions.ShowingType} type
+ */
+ showType: assertNotReached,
};
var Sidebar = Polymer({
@@ -45,26 +51,9 @@ cr.define('extensions', function() {
type: Boolean,
value: false,
},
-
- hideExtensionsButton: {
- type: Boolean,
- value: false,
- },
-
- hideAppsButton: {
- type: Boolean,
- value: false,
- },
-
- hideWebsitesButton: {
- type: Boolean,
- value: false,
- },
},
- behaviors: [
- I18nBehavior,
- ],
+ behaviors: [I18nBehavior],
/** @param {extensions.SidebarDelegate} delegate */
setDelegate: function(delegate) {
@@ -72,25 +61,20 @@ cr.define('extensions', function() {
this.delegate_ = delegate;
},
- /** @param {extensions.SidebarScrollDelegate} scrollDelegate */
- setScrollDelegate: function(scrollDelegate) {
- /** @private {extensions.SidebarScrollDelegate} */
- this.scrollDelegate_ = scrollDelegate;
+ /** @param {extensions.SidebarListDelegate} listDelegate */
+ setListDelegate: function(listDelegate) {
+ /** @private {extensions.SidebarListDelegate} */
+ this.listDelegate_ = listDelegate;
},
/** @private */
onExtensionsTap_: function() {
- this.scrollDelegate_.scrollToExtensions();
+ this.listDelegate_.showType(extensions.ShowingType.EXTENSIONS);
},
/** @private */
onAppsTap_: function() {
- this.scrollDelegate_.scrollToApps();
- },
-
- /** @private */
- onWebsitesTap_: function() {
- this.scrollDelegate_.scrollToWebsites();
+ this.listDelegate_.showType(extensions.ShowingType.APPS);
},
/** @private */
@@ -118,7 +102,7 @@ cr.define('extensions', function() {
return {
Sidebar: Sidebar,
SidebarDelegate: SidebarDelegate,
- SidebarScrollDelegate: SidebarScrollDelegate,
+ SidebarListDelegate: SidebarListDelegate,
};
});
diff --git a/chromium/chrome/browser/resources/md_feedback/OWNERS b/chromium/chrome/browser/resources/md_feedback/OWNERS
new file mode 100644
index 00000000000..02b5b4649de
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_feedback/OWNERS
@@ -0,0 +1 @@
+apacible@chromium.org
diff --git a/chromium/chrome/browser/resources/md_history/app.html b/chromium/chrome/browser/resources/md_history/app.html
new file mode 100644
index 00000000000..9a7294f7323
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_history/app.html
@@ -0,0 +1,61 @@
+<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/iron-pages/iron-pages.html">
+<link rel="import" href="chrome://history/history_list.html">
+<link rel="import" href="chrome://history/history_toolbar.html">
+<link rel="import" href="chrome://history/synced_device_manager.html">
+<link rel="import" href="chrome://history/side_bar.html">
+<link rel="import" href="chrome://history/shared_style.html">
+
+<dom-module id="history-app">
+ <!-- TODO(calamity): work around this deprecated import style -->
+ <link rel="import" type="css" href="chrome://resources/css/md_colors.css">
+ <template>
+ <style include="shared-style">
+ :host {
+ display: flex;
+ flex-direction: column;
+ min-width: 800px;
+ }
+
+ #main-container {
+ display: flex;
+ flex: 1 0 0;
+ overflow: hidden;
+ }
+
+ history-list,
+ #history-synced-device-manager {
+ flex: 1 0 0;
+ }
+
+ #content {
+ display: flex;
+ flex: 1 0 0;
+ }
+
+ history-toolbar {
+ background: var(--md-toolbar-color);
+ }
+ </style>
+ <history-toolbar id="toolbar" searching="[[queryState_.querying]]"
+ search-term="{{queryState_.searchTerm}}"
+ query-start-time="[[queryState_.queryStartTime]]"
+ query-end-time="[[queryState_.queryEndTime]]">
+ </history-toolbar>
+
+ <div id="main-container">
+ <history-side-bar id="history-side-bar" selected-page="{{selectedPage}}">
+ </history-side-bar>
+ <iron-pages id="content" attr-for-selected="id"
+ selected="{{selectedPage}}">
+ <history-list id="history-list" querying="[[queryState_.querying]]"
+ searched-term="{{queryState_.info.term}}">
+ </history-list>
+ <history-synced-device-manager id="history-synced-device-manager">
+ </history-synced-device-manager>
+ </iron-pages>
+ </div>
+ </template>
+ <script src="chrome://history/app.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_history/app.js b/chromium/chrome/browser/resources/md_history/app.js
new file mode 100644
index 00000000000..d58fcfdab7c
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_history/app.js
@@ -0,0 +1,151 @@
+// 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.
+
+/**
+ * @typedef {{querying: boolean,
+ * searchTerm: string,
+ * results: ?Array<!HistoryEntry>,
+ * info: ?HistoryQuery}}
+ */
+var QueryState;
+
+Polymer({
+ is: 'history-app',
+
+ properties: {
+ // The id of the currently selected page.
+ selectedPage: {
+ type: String,
+ value: 'history-list'
+ },
+
+ /** @type {!QueryState} */
+ queryState_: {
+ type: Object,
+ value: function() {
+ return {
+ // A query is initiated by page load.
+ querying: true,
+ searchTerm: '',
+ results: null,
+ info: null,
+ };
+ }
+ },
+ },
+
+ observers: [
+ 'searchTermChanged_(queryState_.searchTerm)',
+ ],
+
+ // TODO(calamity): Replace these event listeners with data bound properties.
+ listeners: {
+ 'history-checkbox-select': 'checkboxSelected',
+ 'unselect-all': 'unselectAll',
+ 'delete-selected': 'deleteSelected',
+ 'search-domain': 'searchDomain_',
+ 'load-more-history': 'loadMoreHistory_',
+ },
+
+ ready: function() {
+ this.$.toolbar.isGroupedMode = loadTimeData.getBoolean('groupByDomain');
+ },
+
+ /**
+ * Listens for history-item being selected or deselected (through checkbox)
+ * and changes the view of the top toolbar.
+ * @param {{detail: {countAddition: number}}} e
+ */
+ checkboxSelected: function(e) {
+ var toolbar = /** @type {HistoryToolbarElement} */(this.$.toolbar);
+ toolbar.count += e.detail.countAddition;
+ },
+
+ /**
+ * Listens for call to cancel selection and loops through all items to set
+ * checkbox to be unselected.
+ */
+ unselectAll: function() {
+ var historyList =
+ /** @type {HistoryListElement} */(this.$['history-list']);
+ var toolbar = /** @type {HistoryToolbarElement} */(this.$.toolbar);
+ historyList.unselectAllItems(toolbar.count);
+ toolbar.count = 0;
+ },
+
+ /**
+ * Listens for call to delete all selected items and loops through all items
+ * to determine which ones are selected and deletes these.
+ */
+ deleteSelected: function() {
+ if (!loadTimeData.getBoolean('allowDeletingHistory'))
+ return;
+
+ // TODO(hsampson): add a popup to check whether the user definitely
+ // wants to delete the selected items.
+ /** @type {HistoryListElement} */(this.$['history-list']).deleteSelected();
+ },
+
+ loadMoreHistory_: function() {
+ this.queryHistory(true);
+ },
+
+ /**
+ * @param {HistoryQuery} info An object containing information about the
+ * query.
+ * @param {!Array<HistoryEntry>} results A list of results.
+ */
+ historyResult: function(info, results) {
+ this.set('queryState_.querying', false);
+ this.set('queryState_.results', results);
+ this.set('queryState_.info', info);
+
+ var list = /** @type {HistoryListElement} */(this.$['history-list']);
+ list.addNewResults(results);
+ if (info.finished)
+ list.disableResultLoading();
+ },
+
+ /**
+ * Fired when the user presses 'More from this site'.
+ * @param {{detail: {domain: string}}} e
+ */
+ searchDomain_: function(e) {
+ this.$.toolbar.setSearchTerm(e.detail.domain);
+ },
+
+ searchTermChanged_: function() {
+ this.queryHistory(false);
+ },
+
+ queryHistory: function(incremental) {
+ var lastVisitTime = 0;
+ if (incremental) {
+ var lastVisit = this.queryState_.results.slice(-1)[0];
+ lastVisitTime = lastVisit ? lastVisit.time : 0;
+ }
+
+ this.set('queryState_.querying', true);
+ chrome.send(
+ 'queryHistory',
+ [this.queryState_.searchTerm, 0, 0, lastVisitTime, RESULTS_PER_PAGE]);
+ },
+
+ /**
+ * @param {!Array<!ForeignSession>} sessionList Array of objects describing
+ * the sessions from other devices.
+ * @param {boolean} isTabSyncEnabled Is tab sync enabled for this profile?
+ */
+ setForeignSessions: function(sessionList, isTabSyncEnabled) {
+ if (!isTabSyncEnabled)
+ return;
+
+ // TODO(calamity): Add a 'no synced devices' message when sessions are
+ // empty.
+ var syncedDeviceElem = this.$['history-synced-device-manager'];
+ var syncedDeviceManager =
+ /** @type {HistorySyncedDeviceManagerElement} */(syncedDeviceElem);
+ syncedDeviceManager.setSyncedHistory(sessionList);
+ }
+});
diff --git a/chromium/chrome/browser/resources/md_history/browser_service.html b/chromium/chrome/browser/resources/md_history/browser_service.html
new file mode 100644
index 00000000000..0cd11020e7c
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_history/browser_service.html
@@ -0,0 +1,3 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/promise_resolver.html">
+<script src="chrome://history/browser_service.js"></script>
diff --git a/chromium/chrome/browser/resources/md_history/browser_service.js b/chromium/chrome/browser/resources/md_history/browser_service.js
new file mode 100644
index 00000000000..6a03ee39b08
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_history/browser_service.js
@@ -0,0 +1,83 @@
+// 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 Defines a singleton object, md_history.BrowserService, which
+ * provides access to chrome.send APIs.
+ */
+
+cr.define('md_history', function() {
+ /** @constructor */
+ function BrowserService() {
+ /** @private {Array<!HistoryEntry>} */
+ this.pendingDeleteItems_ = null;
+ /** @private {PromiseResolver} */
+ this.pendingDeletePromise_ = null;
+ }
+
+ BrowserService.prototype = {
+ /**
+ * @param {!Array<!HistoryEntry>} items
+ * @return {Promise<!Array<!HistoryEntry>>}
+ */
+ deleteItems: function(items) {
+ if (this.pendingDeleteItems_ != null) {
+ // There's already a deletion in progress, reject immediately.
+ return new Promise(function(resolve, reject) { reject(items); });
+ }
+
+ var removalList = items.map(function(item) {
+ return {
+ url: item.url,
+ timestamps: item.allTimestamps
+ };
+ });
+
+ this.pendingDeleteItems_ = items;
+ this.pendingDeletePromise_ = new PromiseResolver();
+
+ chrome.send('removeVisits', removalList);
+
+ return this.pendingDeletePromise_.promise;
+ },
+
+ /**
+ * @param {boolean} successful
+ * @private
+ */
+ resolveDelete_: function(successful) {
+ if (this.pendingDeleteItems_ == null ||
+ this.pendingDeletePromise_ == null) {
+ return;
+ }
+
+ if (successful)
+ this.pendingDeletePromise_.resolve(this.pendingDeleteItems_);
+ else
+ this.pendingDeletePromise_.reject(this.pendingDeleteItems_);
+
+ this.pendingDeleteItems_ = null;
+ this.pendingDeletePromise_ = null;
+ },
+ };
+
+ cr.addSingletonGetter(BrowserService);
+
+ return {BrowserService: BrowserService};
+});
+
+/**
+ * Called by the history backend when deletion was succesful.
+ */
+function deleteComplete() {
+ md_history.BrowserService.getInstance().resolveDelete_(true);
+}
+
+/**
+ * Called by the history backend when the deletion failed.
+ */
+function deleteFailed() {
+ md_history.BrowserService.getInstance().resolveDelete_(false);
+}
+
diff --git a/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp
index d8345cf1f18..bc683dfd43e 100644
--- a/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_history/compiled_resources2.gyp
@@ -8,8 +8,17 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'browser_service',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '../history/compiled_resources2.gyp:externs',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'history_item',
'dependencies': [
+ '<(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:util',
'../history/compiled_resources2.gyp:externs',
@@ -19,10 +28,12 @@
{
'target_name': 'history_list',
'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-scroll-threshold/compiled_resources2.gyp:iron-scroll-threshold-extracted',
'<(DEPTH)/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp:cr_shared_menu',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
'constants',
+ 'browser_service',
'history_item',
'../history/compiled_resources2.gyp:externs',
],
@@ -33,13 +44,25 @@
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_search_field/compiled_resources2.gyp:cr_search_field',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'history',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ 'constants',
+ 'app',
+ '<(EXTERNS_GYP):chrome_send',
+ '../history/compiled_resources2.gyp:externs',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'app',
+ 'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
'constants',
'history_list',
@@ -60,7 +83,7 @@
'target_name': 'synced_device_card',
'dependencies': [
'../history/compiled_resources2.gyp:externs',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/md_history/elements.html b/chromium/chrome/browser/resources/md_history/elements.html
deleted file mode 100644
index 57fe11d531a..00000000000
--- a/chromium/chrome/browser/resources/md_history/elements.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<link rel="import" href="chrome://history/history_list.html">
-<link rel="import" href="chrome://history/history_toolbar.html">
-<link rel="import" href="chrome://history/synced_device_manager.html">
-<link rel="import" href="chrome://history/side_bar.html">
diff --git a/chromium/chrome/browser/resources/md_history/history.html b/chromium/chrome/browser/resources/md_history/history.html
index 30040553097..009049ab7fe 100644
--- a/chromium/chrome/browser/resources/md_history/history.html
+++ b/chromium/chrome/browser/resources/md_history/history.html
@@ -1,10 +1,11 @@
<!doctype html>
-<html i18n-values="dir:textdirection;lang:language">
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf8">
<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,
@@ -14,54 +15,43 @@
}
body {
- background: #f2f2f2;
+ background: var(--md-background-color);
display: flex;
flex-direction: column;
- min-width: 800px;
}
- #toolbar {
- flex: 0 0 56px;
+ /* Minimal styling required to display app shim. */
+ .loading history-app,
+ .app-shim {
+ display: none;
}
- #toolbar:unresolved {
+ history-app {
+ flex: 1;
+ }
+
+ .loading .app-shim {
+ display: flex;
+ font-size: 123%;
+ }
+
+ .loading #loading-toolbar {
+ -webkit-padding-start: 24px;
align-items: center;
- background: rgb(63, 85, 102);
color: #fff;
- display: flex;
flex-direction: row;
- font-size: 16px;
font-weight: 400;
height: 56px;
- padding-left: 24px;
- }
-
- #history-list {
- flex: 1 0 0;
- overflow: auto;
}
- #history-synced-device-manager {
- flex: 1 0 0;
- }
-
- #main-container {
- display: flex;
- flex: 1 0 0;
- overflow: hidden;
- }
-
- .loading #main-container,
- #loading-message {
- display: none;
+ .loading #loading-toolbar {
+ background: var(--md-toolbar-color);
}
.loading #loading-message {
align-items: center;
color: #b4b4b4;
- display: flex;
flex: 1;
- font-size: 16px;
font-weight: 500;
justify-content: center;
}
@@ -69,16 +59,9 @@
</head>
<body class="loading">
- <history-toolbar class="paper-header" id="toolbar">
- $i18n{title}
- </history-toolbar>
- <div id="main-container">
- <history-side-bar id="history-side-bar"></history-side-bar>
- <history-list id="history-list"></history-list>
- <history-synced-device-manager id="history-synced-device-manager" hidden>
- </history-synced-device-manager>
- </div>
- <span id="loading-message">$i18n{loading}</span>
+ <history-app id="history-app"></history-app>
+ <span class="app-shim" id="loading-toolbar">$i18n{title}</span>
+ <span class="app-shim" id="loading-message">$i18n{loading}</span>
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/util.html">
@@ -87,14 +70,7 @@
<script src="strings.js"></script>
<script src="history.js"></script>
- <link rel="import" href="chrome://history/elements.html" async id="bundle">
-
- <!--
- Prepare strings and perform i18n substitutions.
- TODO(tsergeant): Remove once we are fully converted to
- ReplaceTemplateExpressions. It is currently only used for the <html> tag.
- -->
- <link rel="import" href="chrome://resources/html/i18n_template.html" async>
+ <link rel="import" href="chrome://history/app.html" async id="bundle">
</body>
</html>
diff --git a/chromium/chrome/browser/resources/md_history/history.js b/chromium/chrome/browser/resources/md_history/history.js
index 72aecafbc29..8c14e95ff87 100644
--- a/chromium/chrome/browser/resources/md_history/history.js
+++ b/chromium/chrome/browser/resources/md_history/history.js
@@ -20,64 +20,6 @@ function waitForUpgrade(element) {
});
}
-/**
- * Listens for history-item being selected or deselected (through checkbox)
- * and changes the view of the top toolbar.
- * @param {{detail: {countAddition: number}}} e
- */
-window.addEventListener('history-checkbox-select', function(e) {
- var toolbar = /** @type {HistoryToolbarElement} */($('toolbar'));
- toolbar.count += e.detail.countAddition;
-});
-
-/**
- * Listens for call to cancel selection and loops through all items to set
- * checkbox to be unselected.
- */
-window.addEventListener('unselect-all', function() {
- var historyList = /** @type {HistoryListElement} */($('history-list'));
- var toolbar = /** @type {HistoryToolbarElement} */($('toolbar'));
- historyList.unselectAllItems(toolbar.count);
- toolbar.count = 0;
-});
-
-/**
- * Listens for call to delete all selected items and loops through all items to
- * to determine which ones are selected and deletes these.
- */
-window.addEventListener('delete-selected', function() {
- if (!loadTimeData.getBoolean('allowDeletingHistory'))
- return;
-
- // TODO(hsampson): add a popup to check whether the user definitely wants to
- // delete the selected items.
-
- var historyList = /** @type {HistoryListElement} */($('history-list'));
- var toolbar = /** @type {HistoryToolbarElement} */($('toolbar'));
- var toBeRemoved = historyList.getSelectedItems(toolbar.count);
- chrome.send('removeVisits', toBeRemoved);
-});
-
-/**
- * When the search is changed refresh the results from the backend. Ensures that
- * the search bar is updated with the new search term.
- * @param {{detail: {search: string}}} e
- */
-window.addEventListener('search-changed', function(e) {
- $('toolbar').setSearchTerm(e.detail.search);
- /** @type {HistoryListElement} */($('history-list')).setLoading();
- chrome.send('queryHistory', [e.detail.search, 0, 0, 0, RESULTS_PER_PAGE]);
-});
-
-/**
- * Switches between displaying history data and synced tabs data for the page.
- */
-window.addEventListener('switch-display', function(e) {
- $('history-synced-device-manager').hidden =
- e.detail.display != 'synced-tabs-button';
- $('history-list').hidden = e.detail.display != 'history-button';
-});
-
// Chrome Callbacks-------------------------------------------------------------
/**
@@ -86,12 +28,9 @@ window.addEventListener('switch-display', function(e) {
* @param {!Array<HistoryEntry>} results A list of results.
*/
function historyResult(info, results) {
- var listElem = $('history-list');
- waitForUpgrade(listElem).then(function() {
- var list = /** @type {HistoryListElement} */(listElem);
- list.addNewResults(results, info.term);
- if (info.finished)
- list.disableResultLoading();
+ var appElem = $('history-app');
+ waitForUpgrade(appElem).then(function() {
+ /** @type {HistoryAppElement} */(appElem).historyResult(info, results);
// TODO(tsergeant): Showing everything as soon as the list is ready is not
// ideal, as the sidebar can still pop in after. Fix this to show everything
// at once.
@@ -122,34 +61,14 @@ function showNotification(
* @param {boolean} isTabSyncEnabled Is tab sync enabled for this profile?
*/
function setForeignSessions(sessionList, isTabSyncEnabled) {
- // TODO(calamity): Add a 'no synced devices' message when sessions are empty.
- $('history-side-bar').hidden = !isTabSyncEnabled;
- var syncedDeviceElem = $('history-synced-device-manager');
- waitForUpgrade(syncedDeviceElem).then(function() {
- var syncedDeviceManager =
- /** @type {HistorySyncedDeviceManagerElement} */(syncedDeviceElem);
- if (isTabSyncEnabled)
- syncedDeviceManager.setSyncedHistory(sessionList);
+ var appElem = $('history-app');
+ waitForUpgrade(appElem).then(function() {
+ /** @type {HistoryAppElement} */(appElem)
+ .setForeignSessions(sessionList, isTabSyncEnabled);
});
}
/**
- * Called by the history backend when deletion was succesful.
- */
-function deleteComplete() {
- var historyList = /** @type {HistoryListElement} */($('history-list'));
- var toolbar = /** @type {HistoryToolbarElement} */($('toolbar'));
- historyList.removeDeletedHistory(toolbar.count);
- toolbar.count = 0;
-}
-
-/**
- * Called by the history backend when the deletion failed.
- */
-function deleteFailed() {
-}
-
-/**
* Called when the history is deleted by someone else.
*/
function historyDeleted() {
diff --git a/chromium/chrome/browser/resources/md_history/history_item.html b/chromium/chrome/browser/resources/md_history/history_item.html
index d576463789d..d9bdbcc6c1b 100644
--- a/chromium/chrome/browser/resources/md_history/history_item.html
+++ b/chromium/chrome/browser/resources/md_history/history_item.html
@@ -1,21 +1,21 @@
+<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/iron-icon/iron-icon.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-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/html/icon.html">
<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://history/shared_style.html">
<dom-module id="history-item">
<template>
- <style include="shared-style"></style>
- <style>
+ <style include="shared-style">
:host {
@apply(--layout-center);
@apply(--layout-vertical);
- padding: 0 24px;
+ padding: 0 var(--card-padding-side);
}
#main-container {
@@ -131,12 +131,12 @@
<a href="[[item.url]]" id="title" class="website-title"></a>
<span id="domain">[[item.domain]]</span>
</div>
- <iron-icon icon="star" id="bookmark-star"></iron-icon>
- <paper-icon-button icon="more-vert" id="menu-button"
+ <iron-icon icon="cr:star" id="bookmark-star"></iron-icon>
+ <paper-icon-button icon="cr:more-vert" id="menu-button"
on-tap="onMenuButtonTap_">
</paper-icon-button>
</div>
- <template is="dom-if" if="[[item.hasTimeGap]]">
+ <template is="dom-if" if="[[hasTimeGap]]">
<div id="time-gap-separator"></div>
</template>
</div>
diff --git a/chromium/chrome/browser/resources/md_history/history_item.js b/chromium/chrome/browser/resources/md_history/history_item.js
index f4d95df96c8..289eb07d747 100644
--- a/chromium/chrome/browser/resources/md_history/history_item.js
+++ b/chromium/chrome/browser/resources/md_history/history_item.js
@@ -16,37 +16,35 @@ Polymer({
// True if the website is a bookmarked page.
starred: {
type: Boolean,
- value: false,
reflectToAttribute: true
},
// Search term used to obtain this history-item.
searchTerm: {
- type: String,
- value: '',
+ type: String
},
selected: {
type: Boolean,
- value: false,
notify: true
},
isCardStart: {
type: Boolean,
- value: false,
reflectToAttribute: true
},
isCardEnd: {
type: Boolean,
- value: false,
reflectToAttribute: true
},
+ hasTimeGap: {
+ type: Boolean
+ },
+
numberOfItems: {
- type: Number,
- value: 0
+ type: Number
}
},
@@ -72,11 +70,7 @@ Polymer({
onMenuButtonTap_: function(e) {
this.fire('toggle-menu', {
target: Polymer.dom(e).localTarget,
- itemIdentifier: {
- url: this.item.url,
- timestamps: this.item.time,
- domain: this.item.domain
- },
+ item: this.item,
});
// Stops the 'tap' event from closing the menu when it opens.
@@ -89,7 +83,7 @@ Polymer({
*/
showIcon_: function() {
this.$.icon.style.backgroundImage =
- getFaviconImageSet(this.item.url);
+ cr.icon.getFaviconImageSet(this.item.url);
},
/**
diff --git a/chromium/chrome/browser/resources/md_history/history_list.html b/chromium/chrome/browser/resources/md_history/history_list.html
index 59cb64c8712..3686aa71f2a 100644
--- a/chromium/chrome/browser/resources/md_history/history_list.html
+++ b/chromium/chrome/browser/resources/md_history/history_list.html
@@ -1,18 +1,20 @@
<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/iron-scroll-threshold/iron-scroll-threshold.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
<link rel="import" href="chrome://resources/cr_elements/cr_shared_menu/cr_shared_menu.html">
+<link rel="import" href="chrome://history/browser_service.html">
<link rel="import" href="chrome://history/constants.html">
<link rel="import" href="chrome://history/history_item.html">
<link rel="import" href="chrome://history/shared_style.html">
<dom-module id="history-list">
<template>
- <style include="shared-style"></style>
- <style>
+ <style include="shared-style">
:host {
display: flex;
flex-direction: column;
+ position: relative;
}
#infinite-list {
@@ -31,23 +33,26 @@
}
</style>
<div id="no-results" class="centered-message"
- hidden$="{{hasResults(historyData.length)}}">
- {{noResultsMessage_(searchTerm, loading_)}}
+ hidden$="{{hasResults(historyData_.length)}}">
+ {{noResultsMessage_(searchedTerm, querying)}}
</div>
- <iron-list items="{{historyData}}" as="item" id="infinite-list"
- on-scroll="scrollHandler_"
- hidden$="{{!hasResults(historyData.length)}}">
+ <iron-list items="{{historyData_}}" as="item" id="infinite-list"
+ hidden$="{{!hasResults(historyData_.length)}}">
<template>
<history-item item="[[item]]"
starred="[[item.starred]]"
selected="{{item.selected}}"
- is-card-start="[[item.isFirstItem]]"
- is-card-end="[[item.isLastItem]]"
- search-term="[[searchTerm]]"
- number-of-items="[[historyData.length]]">
+ is-card-start="[[isCardStart_(item, index, historyData_.length)]]"
+ is-card-end="[[isCardEnd_(item, index, historyData_.length)]]"
+ has-time-gap="[[needsTimeGap_(item, index, historyData_.length)]]"
+ search-term="[[searchedTerm]]"
+ number-of-items="[[historyData_.length]]">
</history-item>
</template>
</iron-list>
+ <iron-scroll-threshold id="scroll-threshold" scroll-target="infinite-list"
+ lower-threshold="500" on-lower-threshold="loadMoreData_">
+ </iron-scroll-threshold>
<cr-shared-menu id="sharedMenu">
<paper-item id="menuMoreButton" on-tap="onMoreFromSiteTap_">
$i18n{moreFromSite}
diff --git a/chromium/chrome/browser/resources/md_history/history_list.js b/chromium/chrome/browser/resources/md_history/history_list.js
index 791a9acbe0c..c6d424c7bcd 100644
--- a/chromium/chrome/browser/resources/md_history/history_list.js
+++ b/chromium/chrome/browser/resources/md_history/history_list.js
@@ -6,31 +6,22 @@ Polymer({
is: 'history-list',
properties: {
- // An array of history entries in reverse chronological order.
- historyData: {
- type: Array
+ // The search term for the current query. Set when the query returns.
+ searchedTerm: {
+ type: String,
+ value: '',
},
- // The time of access of the last history item in historyData.
- lastVisitedTime: {
- type: Number,
- value: 0
- },
+ lastSearchedTerm_: String,
- searchTerm: {
- type: String,
- value: ''
- },
+ querying: Boolean,
- // True if there is a pending request to the backend.
- loading_: {
- type: Boolean,
- value: true
- },
+ // An array of history entries in reverse chronological order.
+ historyData_: Array,
resultLoadingDisabled_: {
type: Boolean,
- value: false
+ value: false,
},
},
@@ -49,28 +40,36 @@ Polymer({
},
/**
- * Mark the page as currently loading new data from the back-end.
- */
- setLoading: function() {
- this.loading_ = true;
- },
-
- /**
* Opens the overflow menu unless the menu is already open and the same button
* is pressed.
- * @param {{detail: {itemIdentifier: !Object}}} e
+ * @param {{detail: {item: !HistoryEntry, target: !HTMLElement}}} e
* @private
*/
toggleMenu_: function(e) {
var target = e.detail.target;
/** @type {CrSharedMenuElement} */(this.$.sharedMenu).toggleMenu(
- target, e.detail.itemIdentifier);
+ target, e.detail.item);
},
/** @private */
onMoreFromSiteTap_: function() {
var menu = /** @type {CrSharedMenuElement} */(this.$.sharedMenu);
- this.fire('search-changed', {search: menu.itemData.domain});
+ this.fire('search-domain', {domain: menu.itemData.domain});
+ menu.closeMenu();
+ },
+
+ /** @private */
+ onRemoveFromHistoryTap_: function() {
+ var menu = /** @type {CrSharedMenuElement} */(this.$.sharedMenu);
+ md_history.BrowserService.getInstance()
+ .deleteItems([menu.itemData])
+ .then(function(items) {
+ this.removeDeletedHistory_(items);
+ // This unselect-all is to reset the toolbar when deleting a selected
+ // item. TODO(tsergeant): Make this automatic based on observing list
+ // modifications.
+ this.fire('unselect-all');
+ }.bind(this));
menu.closeMenu();
},
@@ -82,18 +81,19 @@ Polymer({
},
/**
- * Adds the newly updated history results into historyData. Adds new fields
+ * Adds the newly updated history results into historyData_. Adds new fields
* for each result.
* @param {!Array<!HistoryEntry>} historyResults The new history results.
- * @param {string} searchTerm Search query used to find these results.
*/
- addNewResults: function(historyResults, searchTerm) {
- this.loading_ = false;
-
- if (this.searchTerm != searchTerm) {
- if (this.historyData)
- this.splice('historyData', 0, this.historyData.length);
- this.searchTerm = searchTerm;
+ addNewResults: function(historyResults) {
+ /** @type {IronScrollThresholdElement} */(this.$['scroll-threshold'])
+ .clearTriggers();
+
+ if (this.lastSearchedTerm_ != this.searchedTerm) {
+ this.resultLoadingDisabled_ = false;
+ if (this.historyData_)
+ this.splice('historyData_', 0, this.historyData_.length);
+ this.lastSearchedTerm_ = this.searchedTerm;
}
if (historyResults.length == 0)
@@ -105,62 +105,42 @@ Polymer({
var currentDate = results[0].dateRelativeDay;
- // Resets the last history item for the currentDate if new history results
- // for currentDate is loaded.
- if (this.historyData && this.historyData.length > 0) {
- var lastHistoryItem = this.historyData[this.historyData.length - 1];
- if (lastHistoryItem && lastHistoryItem.dateRelativeDay == currentDate) {
- this.set('historyData.' + (this.historyData.length - 1) +
- '.isLastItem', false);
- }
- }
-
for (var i = 0; i < results.length; i++) {
// Sets the default values for these fields to prevent undefined types.
results[i].selected = false;
- results[i].isLastItem = false;
- results[i].isFirstItem = false;
- results[i].needsTimeGap = this.needsTimeGap_(results, i);
results[i].readableTimestamp =
- searchTerm == '' ? results[i].dateTimeOfDay : results[i].dateShort;
+ this.searchedTerm == '' ?
+ results[i].dateTimeOfDay : results[i].dateShort;
if (results[i].dateRelativeDay != currentDate) {
- results[i - 1].isLastItem = true;
- results[i].isFirstItem = true;
currentDate = results[i].dateRelativeDay;
}
}
- results[i - 1].isLastItem = true;
-
- if (!this.historyData || this.historyData.length == 0)
- results[0].isFirstItem = true;
- if (this.historyData) {
+ if (this.historyData_) {
// If we have previously received data, push the new items onto the
// existing array.
- results.unshift('historyData');
+ results.unshift('historyData_');
this.push.apply(this, results);
} else {
// The first time we receive data, use set() to ensure the iron-list is
// initialized correctly.
- this.set('historyData', results);
+ this.set('historyData_', results);
}
-
- this.lastVisitedTime = this.historyData[this.historyData.length - 1].time;
},
/**
- * Cycle through each entry in historyData and set all items to be
+ * Cycle through each entry in historyData_ and set all items to be
* unselected.
* @param {number} overallItemCount The number of checkboxes selected.
*/
unselectAllItems: function(overallItemCount) {
- if (this.historyData === undefined)
+ if (this.historyData_ === undefined)
return;
- for (var i = 0; i < this.historyData.length; i++) {
- if (this.historyData[i].selected) {
- this.set('historyData.' + i + '.selected', false);
+ for (var i = 0; i < this.historyData_.length; i++) {
+ if (this.historyData_[i].selected) {
+ this.set('historyData_.' + i + '.selected', false);
overallItemCount--;
if (overallItemCount == 0)
break;
@@ -169,113 +149,81 @@ Polymer({
},
/**
- * Remove all selected items from the overall array so that they are also
- * removed from view. Make sure that the card length and positioning is
- * updated accordingly.
- * @param {number} overallItemCount The number of items selected.
+ * Remove the given |items| from the list. Expected to be called after the
+ * items are removed from the backend.
+ * @param {!Array<!HistoryEntry>} removalList
+ * @private
*/
- removeDeletedHistory: function(overallItemCount) {
- for (var i = this.historyData.length - 1; i >= 0; i--) {
- if (!this.historyData[i].selected)
- continue;
-
- // TODO: Change to using computed properties to recompute the first and
- // last cards.
-
- // Resets the first history item.
- if (this.historyData[i].isFirstItem &&
- (i + 1) < this.historyData.length &&
- this.historyData[i].dateRelativeDay ==
- this.historyData[i + 1].dateRelativeDay) {
- this.set('historyData.' + (i + 1) + '.isFirstItem', true);
- }
-
- // Resets the last history item.
- if (this.historyData[i].isLastItem && i > 0 &&
- this.historyData[i].dateRelativeDay ==
- this.historyData[i - 1].dateRelativeDay) {
- this.set('historyData.' + (i - 1) + '.isLastItem', true);
-
- if (this.historyData[i - 1].needsTimeGap)
- this.set('historyData.' + (i - 1) + '.needsTimeGap', false);
+ removeDeletedHistory_: function(removalList) {
+ // This set is only for speed. Note that set inclusion for objects is by
+ // reference, so this relies on the HistoryEntry objects never being copied.
+ var deletedItems = new Set(removalList);
+ var splices = [];
+
+ for (var i = this.historyData_.length - 1; i >= 0; i--) {
+ var item = this.historyData_[i];
+ if (deletedItems.has(item)) {
+ // Removes the selected item from historyData_. Use unshift so
+ // |splices| ends up in index order.
+ splices.unshift({
+ index: i,
+ removed: [item],
+ addedCount: 0,
+ object: this.historyData_,
+ type: 'splice'
+ });
+ this.historyData_.splice(i, 1);
}
-
- // Makes sure that the time gap separators are preserved.
- if (this.historyData[i].needsTimeGap && i > 0)
- this.set('historyData.' + (i - 1) + '.needsTimeGap', true);
-
- // Removes the selected item from historyData.
- this.splice('historyData', i, 1);
-
- overallItemCount--;
- if (overallItemCount == 0)
- break;
}
+ // notifySplices gives better performance than individually splicing as it
+ // batches all of the updates together.
+ this.notifySplices('historyData_', splices);
},
/**
- * Based on which items are selected, collect an array of the info required
- * for chrome.send('removeHistory', ...).
- * @param {number} count The number of items that are selected.
- * @return {Array<HistoryEntry>} toBeRemoved An array of objects which contain
- * information on which history-items should be deleted.
+ * Performs a request to the backend to delete all selected items. If
+ * successful, removes them from the view.
*/
- getSelectedItems: function(count) {
- var toBeRemoved = [];
- for (var i = 0; i < this.historyData.length; i++) {
- if (this.historyData[i].selected) {
- toBeRemoved.push({
- url: this.historyData[i].url,
- timestamps: this.historyData[i].allTimestamps
- });
-
- count--;
- if (count == 0)
- break;
- }
- }
- return toBeRemoved;
+ deleteSelected: function() {
+ var toBeRemoved = this.historyData_.filter(function(item) {
+ return item.selected;
+ });
+ md_history.BrowserService.getInstance()
+ .deleteItems(toBeRemoved)
+ .then(function(items) {
+ this.removeDeletedHistory_(items);
+ this.fire('unselect-all');
+ }.bind(this));
},
/**
- * Called when the card manager is scrolled.
+ * Called when the page is scrolled to near the bottom of the list.
* @private
*/
- scrollHandler_: function() {
- if (this.resultLoadingDisabled_)
+ loadMoreData_: function() {
+ if (this.resultLoadingDisabled_ || this.querying)
return;
- // Requests the next list of results when the scrollbar is near the bottom
- // of the window.
- var scrollOffset = 10;
- var scrollElem = this.$['infinite-list'];
-
- if (!this.loading_ && scrollElem.scrollHeight <=
- scrollElem.scrollTop + scrollElem.clientHeight + scrollOffset) {
- this.loading_ = true;
- chrome.send('queryHistory',
- [this.searchTerm, 0, 0, this.lastVisitedTime, RESULTS_PER_PAGE]);
- }
+ this.fire('load-more-history');
},
/**
* Check whether the time difference between the given history item and the
* next one is large enough for a spacer to be required.
- * @param {Array<HistoryEntry>} results A list of history results.
- * @param {number} index The index number of the first item being compared.
+ * @param {HistoryEntry} item
+ * @param {number} index The index of |item| in |historyData_|.
+ * @param {number} length The length of |historyData_|.
* @return {boolean} Whether or not time gap separator is required.
* @private
*/
- needsTimeGap_: function(results, index) {
- // TODO(tsergeant): Allow the final item from one batch of results to have a
- // timegap once more results are added.
- if (index == results.length - 1)
+ needsTimeGap_: function(item, index, length) {
+ if (index >= length - 1 || length == 0)
return false;
- var currentItem = results[index];
- var nextItem = results[index + 1];
+ var currentItem = this.historyData_[index];
+ var nextItem = this.historyData_[index + 1];
- if (this.searchTerm)
+ if (this.searchedTerm)
return currentItem.dateShort != nextItem.dateShort;
return currentItem.time - nextItem.time > BROWSING_GAP_TIME &&
@@ -286,10 +234,42 @@ Polymer({
return historyDataLength > 0;
},
- noResultsMessage_: function(searchTerm, isLoading) {
+ noResultsMessage_: function(searchedTerm, isLoading) {
if (isLoading)
return '';
- var messageId = searchTerm !== '' ? 'noSearchResults' : 'noResults';
+ var messageId = searchedTerm !== '' ? 'noSearchResults' : 'noResults';
return loadTimeData.getString(messageId);
- }
+ },
+
+ /**
+ * True if the given item is the beginning of a new card.
+ * @param {HistoryEntry} item
+ * @param {number} i Index of |item| within |historyData_|.
+ * @param {number} length
+ * @return {boolean}
+ * @private
+ */
+ isCardStart_: function(item, i, length) {
+ if (length == 0 || i > length - 1)
+ return false;
+ return i == 0 ||
+ this.historyData_[i].dateRelativeDay !=
+ this.historyData_[i - 1].dateRelativeDay;
+ },
+
+ /**
+ * True if the given item is the end of a card.
+ * @param {HistoryEntry} item
+ * @param {number} i Index of |item| within |historyData_|.
+ * @param {number} length
+ * @return {boolean}
+ * @private
+ */
+ isCardEnd_: function(item, i, length) {
+ if (length == 0 || i > length - 1)
+ return false;
+ return i == length - 1 ||
+ this.historyData_[i].dateRelativeDay !=
+ this.historyData_[i + 1].dateRelativeDay;
+ },
});
diff --git a/chromium/chrome/browser/resources/md_history/history_toolbar.html b/chromium/chrome/browser/resources/md_history/history_toolbar.html
index ea78ae2531d..25448560482 100644
--- a/chromium/chrome/browser/resources/md_history/history_toolbar.html
+++ b/chromium/chrome/browser/resources/md_history/history_toolbar.html
@@ -1,23 +1,26 @@
+<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-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/iron-icons/hardware-icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tab.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tabs.html">
<link rel="import" href="chrome://resources/cr_elements/cr_search_field/cr_search_field.html">
<link rel="import" href="chrome://history/shared_style.html">
<dom-module id="history-toolbar">
<template>
- <style include="shared-style"></style>
- <style>
+ <style include="shared-style">
:host {
- background: rgb(63, 85, 102);
color: #fff;
- height: 56px;
transition: background-color 150ms;
+ width: 100%;
}
- :host,
- #items,
+ #overlay-buttons,
+ #overlay-wrapper,
#main-content,
#button-container,
#toolbar-container {
@@ -32,87 +35,178 @@
h1 {
@apply(--layout-flex);
- font-size: 16px;
+ -webkit-padding-start: 24px;
+ font-size: 123%;
font-weight: 400;
- padding-left: 24px;
+ }
+
+ #toolbar-container {
+ height: 56px;
+ }
+
+ #right-content {
+ flex: 1 0 0;
+ }
+
+ #left-content {
+ flex: 1 0 var(--side-bar-width);
+ }
+
+ #centered-content {
+ /** Padding-start gives space on one side, flex-basis gives space on the
+ other. */
+ -webkit-padding-start: var(--card-padding-side);
+ display: flex;
+ flex: 1 1 calc(var(--card-max-width) + var(--card-padding-side));
+ }
+
+ #right-content {
+ @apply(--layout-center);
+ @apply(--layout-horizontal);
+ justify-content: flex-end;
}
#search-input {
-webkit-padding-end: 20px;
}
- #items {
+ #searching-spinner {
+ height: 20px;
+ width: 20px;
+ -webkit-padding-end: 10px;
+ }
+
+ #overlay-buttons {
margin: 0 auto;
max-width: var(--card-max-width);
+ padding: 0 var(--card-padding-side);
+ }
+
+ #overlay-wrapper {
+ -webkit-margin-start: var(--side-bar-width);
}
#number-selected {
@apply(--layout-flex);
}
- paper-icon-button {
+ #cancel-icon-button {
+ -webkit-margin-end: 24px;
+ -webkit-margin-start: 2px;
height: 36px;
- margin: 0 24px 0 2px;
min-width: 36px;
width: 36px;
}
- #centered-buttons {
- flex: 0 1 var(--card-max-width);
+ #grouped-nav-container paper-icon-button {
+ --paper-icon-button-ink-color: rgba(255, 255, 255, 0.4);
+ -webkit-margin-start: 24px;
+ flex: 0 0 auto;
}
- paper-button {
- pointer-events: auto;
+ paper-tab {
+ --paper-tab-ink: rgba(255, 255, 255, 0.4);
+ font-size: 13px;
+ text-transform: uppercase;
}
- .toolbar-overlay {
- height: inherit;
- left: 0;
+ paper-tabs {
+ --paper-tabs-selection-bar-color: var(--google-blue-500);
+ height: 45px;
+ min-width: 300px;
+ }
+
+ #grouped-buttons-container {
+ @apply(--layout-center);
+ @apply(--layout-horizontal);
+ -webkit-margin-start: var(--side-bar-width);
+ }
+
+ #grouped-range-buttons {
+ -webkit-margin-start: 32px;
+ }
+
+ #grouped-nav-container {
+ @apply(--layout-center);
+ @apply(--layout-end-justified);
+ @apply(--layout-flex);
+ @apply(--layout-horizontal);
+ -webkit-margin-end: 24px;
+ overflow: hidden;
+ transition: opacity 150ms;
+ }
+
+ :host([grouped-range=0]) #grouped-nav-container {
+ opacity: 0;
pointer-events: none;
- position: absolute;
- top: 0;
}
- #front-padding {
- flex: 1 1 0;
- min-width: 100px;
+ #grouped-date {
+ flex: 0 1 auto;
+ opacity: 0.7;
+ overflow: hidden;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
- #back-padding {
- flex: 1 1 0;
+ :host-context([dir=rtl]) .rtl-reversible {
+ transform: rotate(180deg);
}
</style>
<div id="toolbar-container">
<div id="main-content" hidden$="[[itemsSelected_]]">
- <h1 id="title">$i18n{title}</h1>
- <cr-search-field id="search-input" label="$i18n{search}"
- clear-label="$i18n{clearSearch}">
- </cr-search-field>
+ <div id="left-content">
+ <h1 id="title">$i18n{title}</h1>
+ </div>
+ <div id="centered-content">
+ <div id="right-content">
+ <paper-spinner id="searching-spinner" active="[[searching]]">
+ </paper-spinner>
+ <cr-search-field id="search-input" label="$i18n{search}"
+ clear-label="$i18n{clearSearch}">
+ </cr-search-field>
+ </div>
+ </div>
</div>
- <div id="items" hidden$="[[!itemsSelected_]]">
- <paper-icon-button icon="clear" id="cancel-icon-button"
- on-tap="onClearSelectionTap_"></paper-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 id="overlay-wrapper" hidden$="[[!itemsSelected_]]">
+ <div id="overlay-buttons">
+ <paper-icon-button icon="cr:clear" id="cancel-icon-button"
+ on-tap="onClearSelectionTap_"></paper-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>
</div>
-
- <div id="button-container" class="toolbar-overlay">
- <div id="front-padding"></div>
- <div id="centered-buttons" hidden$="[[itemsSelected_]]">
- <paper-button on-tap="onClearBrowsingDataTap_"
- id="clear-browsing-data-button">
- $i18n{clearBrowsingData}
- </paper-button>
+ <template is="dom-if" if="[[isGroupedMode]]">
+ <div id="grouped-buttons-container">
+ <paper-tabs attr-for-selected="value" selected="{{groupedRange}}"
+ id="grouped-range-buttons">
+ <paper-tab value="0">$i18n{rangeAllTime}</paper-tab>
+ <paper-tab value="1">$i18n{rangeWeek}</paper-tab>
+ <paper-tab value="2">$i18n{rangeMonth}</paper-tab>
+ </paper-tabs>
+ <div id="grouped-nav-container">
+ <span id="grouped-date">
+ {{getHistoryInterval_(queryStartTime, queryEndTime)}}
+ </span>
+ <paper-icon-button icon="today" alt="$i18n{rangeToday}"
+ title="$i18n{rangeToday}"></paper-icon-button>
+ <paper-icon-button icon="hardware:keyboard-arrow-left"
+ alt="$i18n{rangePrevious}" title="$i18n{rangePrevious}"
+ class="rtl-reversible"></paper-icon-button>
+ <paper-icon-button icon="hardware:keyboard-arrow-right"
+ alt="$i18n{rangeNext}" title="$i18n{rangeNext}"
+ class="rtl-reversible"></paper-icon-button>
+ </div>
</div>
- <div id="back-padding"></div>
- </div>
+ </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 48189b8999f..356866d0a0b 100644
--- a/chromium/chrome/browser/resources/md_history/history_toolbar.js
+++ b/chromium/chrome/browser/resources/md_history/history_toolbar.js
@@ -40,8 +40,33 @@ Polymer({
// as the user types.
searchTerm: {
type: String,
- value: ''
- }
+ notify: true,
+ },
+
+ // True if waiting on the search backend.
+ searching: {
+ type: Boolean,
+ value: false
+ },
+
+ // Whether domain-grouped history is enabled.
+ isGroupedMode: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
+
+ // The period to search over. Matches BrowsingHistoryHandler::Range.
+ groupedRange: {
+ type: Number,
+ value: 0,
+ reflectToAttribute: true
+ },
+
+ // The start time of the query range.
+ queryStartTime: String,
+
+ // The end time of the query range.
+ queryEndTime: String,
},
/**
@@ -61,6 +86,7 @@ Polymer({
setSearchTerm: function(search) {
if (this.searchTerm == search)
return;
+
this.searchTerm = search;
var searchField = /** @type {SearchField} */(this.$['search-input']);
searchField.showAndFocus().then(function(showing) {
@@ -72,10 +98,8 @@ Polymer({
* If the search term has changed reload for the new search.
*/
onSearch: function(searchTerm) {
- if (searchTerm != this.searchTerm) {
+ if (searchTerm != this.searchTerm)
this.searchTerm = searchTerm;
- this.fire('search-changed', {search: searchTerm});
- }
},
attached: function() {
@@ -88,14 +112,6 @@ Polymer({
this.fire('unselect-all');
},
- /**
- * Relocates the user to the clear browsing data section of the settings page.
- * @private
- */
- onClearBrowsingDataTap_: function() {
- window.location.href = 'chrome://settings/clearBrowserData';
- },
-
onDeleteTap_: function() {
this.fire('delete-selected');
},
@@ -110,5 +126,11 @@ Polymer({
numberOfItemsSelected_: function(count) {
return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
+ },
+
+ getHistoryInterval_: function(queryStartTime, queryEndTime) {
+ // TODO(calamity): Fix the format of these dates.
+ return loadTimeData.getStringF(
+ 'historyInterval', queryStartTime, queryEndTime);
}
});
diff --git a/chromium/chrome/browser/resources/md_history/shared_style.html b/chromium/chrome/browser/resources/md_history/shared_style.html
index a18de8dbb48..00aaba82db6 100644
--- a/chromium/chrome/browser/resources/md_history/shared_style.html
+++ b/chromium/chrome/browser/resources/md_history/shared_style.html
@@ -5,7 +5,9 @@
--card-border-color: rgba(0, 0, 0, 0.14);
--card-max-width: 960px;
--card-min-width: 500px;
+ --card-padding-side: 24px;
--first-card-padding-top: 40px;
+ --side-bar-width: 256px;
}
[hidden] {
@@ -37,6 +39,8 @@
.website-icon {
-webkit-margin-end: 16px;
+ background-repeat: no-repeat;
+ background-size: 16px;
height: 16px;
min-width: 16px;
}
diff --git a/chromium/chrome/browser/resources/md_history/side_bar.html b/chromium/chrome/browser/resources/md_history/side_bar.html
index f9a6faa9354..2b17e38a8ac 100644
--- a/chromium/chrome/browser/resources/md_history/side_bar.html
+++ b/chromium/chrome/browser/resources/md_history/side_bar.html
@@ -4,13 +4,24 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="chrome://history/shared_style.html">
<dom-module id="history-side-bar">
<template>
- <style>
+ <style include="shared-style">
:host {
padding-top: 5px;
- width: 200px;
+ width: var(--side-bar-width);
+ }
+
+ div.separator {
+ background-color: rgba(0, 0, 0, 0.08);
+ height: 1px;
+ margin: 8px 0;
+ }
+
+ #clear-browsing-data {
+ text-transform: uppercase;
}
paper-item {
@@ -31,15 +42,21 @@
color: #5a5a5a;
}
</style>
- <paper-listbox id="overflow-menu" selected="0" on-iron-select="onSelect_">
- <paper-item id="history-button">
+ <paper-listbox id="overflow-menu" selected="0" on-iron-select="onSelect_"
+ selectable=".page-item">
+ <paper-item view-id="history-list" class="page-item">
<div>$i18n{historyMenuItem}</div>
<paper-ripple></paper-ripple>
</paper-item>
- <paper-item id="synced-tabs-button">
+ <paper-item view-id="history-synced-device-manager" class="page-item">
<div>$i18n{openTabsMenuItem}</div>
<paper-ripple></paper-ripple>
</paper-item>
+ <div class="separator"></div>
+ <paper-item on-tap="onClearBrowsingDataTap_" id="clear-browsing-data">
+ <div>$i18n{clearBrowsingData}</div>
+ <paper-ripple></paper-ripple>
+ </paper-item>
</paper-listbox>
</template>
<script src="chrome://history/side_bar.js"></script>
diff --git a/chromium/chrome/browser/resources/md_history/side_bar.js b/chromium/chrome/browser/resources/md_history/side_bar.js
index 02108615aad..77272c8ece1 100644
--- a/chromium/chrome/browser/resources/md_history/side_bar.js
+++ b/chromium/chrome/browser/resources/md_history/side_bar.js
@@ -5,6 +5,13 @@
Polymer({
is: 'history-side-bar',
+ properties: {
+ selectedPage: {
+ type: String,
+ notify: true
+ }
+ },
+
/**
* Handles menu selection changes.
* @param {Event} e
@@ -12,6 +19,14 @@ Polymer({
*/
onSelect_: function(e) {
this.fire('unselect-all');
- this.fire('switch-display', {display: e.detail.item.id});
+ this.selectedPage = e.detail.item.getAttribute('view-id');
+ },
+
+ /**
+ * Relocates the user to the clear browsing data section of the settings page.
+ * @private
+ */
+ onClearBrowsingDataTap_: function() {
+ window.location.href = 'chrome://settings/clearBrowserData';
},
});
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 ee526bb17bf..1ba602fe457 100644
--- a/chromium/chrome/browser/resources/md_history/synced_device_card.html
+++ b/chromium/chrome/browser/resources/md_history/synced_device_card.html
@@ -1,20 +1,19 @@
+<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-styles/shadow.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
-<link rel="import" href="chrome://resources/html/util.html">
+<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://history/shared_style.html">
<dom-module id="history-synced-device-card">
<template>
- <style include="shared-style"></style>
- <style>
+ <style include="shared-style">
:host {
@apply(--layout-center);
@apply(--layout-vertical);
- padding: 0 24px 20px;
+ padding: 0 var(--card-padding-side) 20px;
}
#card-heading {
@@ -82,7 +81,7 @@
[[device]]
<span id="last-update-time">[[lastUpdateTime]]</span>
</div>
- <iron-icon icon="expand-less" id="dropdown-indicator"></iron-icon>
+ <iron-icon icon="cr:expand-less" id="dropdown-indicator"></iron-icon>
</div>
<iron-collapse opened="{{cardOpen_}}" id="collapse">
diff --git a/chromium/chrome/browser/resources/md_history/synced_device_card.js b/chromium/chrome/browser/resources/md_history/synced_device_card.js
index dc577b9769f..4b01791c355 100644
--- a/chromium/chrome/browser/resources/md_history/synced_device_card.js
+++ b/chromium/chrome/browser/resources/md_history/synced_device_card.js
@@ -51,7 +51,7 @@ Polymer({
toggleTabCard: function() {
this.$.collapse.toggle();
this.$['dropdown-indicator'].icon =
- this.$.collapse.opened ? 'expand-less' : 'expand-more';
+ this.$.collapse.opened ? 'cr:expand-less' : 'cr:expand-more';
},
/**
@@ -65,7 +65,7 @@ Polymer({
for (var i = 0; i < this.tabs.length; i++) {
icons[i].style.backgroundImage =
- getFaviconImageSet(this.tabs[i].url);
+ cr.icon.getFaviconImageSet(this.tabs[i].url);
}
});
}
diff --git a/chromium/chrome/browser/resources/md_user_manager/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_user_manager/compiled_resources2.gyp
index caf1a9222b5..c663bfc2716 100644
--- a/chromium/chrome/browser/resources/md_user_manager/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_user_manager/compiled_resources2.gyp
@@ -15,7 +15,6 @@
'target_name': 'create_profile',
'dependencies': [
'<(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/compiled_resources2.gyp:web_ui_listener_behavior',
'profile_browser_proxy',
@@ -23,6 +22,14 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'import_supervised_user',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ 'profile_browser_proxy',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'profile_browser_proxy',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
@@ -31,7 +38,19 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'supervised_user_create_confirm',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ 'profile_browser_proxy',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'supervised_user_learn_more',
+ 'dependencies': [
+ 'profile_browser_proxy',
+ ],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
diff --git a/chromium/chrome/browser/resources/md_user_manager/control_bar.css b/chromium/chrome/browser/resources/md_user_manager/control_bar.css
deleted file mode 100644
index 3b2489e9827..00000000000
--- a/chromium/chrome/browser/resources/md_user_manager/control_bar.css
+++ /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. */
-
-#container {
- padding-bottom: 12px;
- padding-top: 12px;
-}
-
-paper-button {
- border-radius: 2px;
- color: var(--paper-grey-600);
- font-weight: 500;
- line-height: 32px;
- margin: 0;
- min-width: 52px;
- padding: 0 16px;
-}
-
-#addUser {
- margin: 0 8px;
-}
-
-#logo {
- content: -webkit-image-set(
- url(../../../app/theme/default_100_percent/%DISTRIBUTION%/product_logo_name_48.png) 1x,
- url(../../../app/theme/default_200_percent/%DISTRIBUTION%/product_logo_name_48.png) 2x);
- height: 18px;
- left: 24px;
- position: absolute;
- top: 19px;
-}
-
-:host-context([dir='rtl']) #logo {
- left: auto;
- right: 24px;
-}
diff --git a/chromium/chrome/browser/resources/md_user_manager/control_bar.html b/chromium/chrome/browser/resources/md_user_manager/control_bar.html
index 94591e35a39..aa6b384e9ff 100644
--- a/chromium/chrome/browser/resources/md_user_manager/control_bar.html
+++ b/chromium/chrome/browser/resources/md_user_manager/control_bar.html
@@ -5,16 +5,34 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<dom-module id="control-bar">
- <!-- TODO(mahmadi): this format is deprecated. Change to the new
- "shared styles" format. -->
- <link rel="import" type="css" href="chrome://md-user-manager/control_bar.css">
<template>
- <style include="shared-styles"></style>
+ <style include="shared-styles">
+ #container {
+ min-height: 32px;
+ padding: 12px 8px;
+ }
+
+ #logo {
+ content: -webkit-image-set(
+ url(../../../app/theme/default_100_percent/%DISTRIBUTION%/product_logo_name_48.png) 1x,
+ url(../../../app/theme/default_200_percent/%DISTRIBUTION%/product_logo_name_48.png) 2x);
+ height: 18px;
+ left: 24px;
+ position: absolute;
+ top: 19px;
+ }
+
+ :host-context([dir='rtl']) #logo {
+ left: auto;
+ right: 24px;
+ }
+ </style>
<div id="container" class="layout horizontal end-justified">
<div id="logo"></div>
- <paper-button id="launchGuest" on-tap="onLaunchGuestTap_"
+ <paper-button id="launchGuest" class="action secondary"
+ on-tap="onLaunchGuestTap_"
i18n-content="browseAsGuest" hidden="[[!showGuest]]"></paper-button>
- <paper-button id="addUser" on-tap="onAddUserTap_"
+ <paper-button id="addUser" class="action secondary" on-tap="onAddUserTap_"
i18n-content="addUser" hidden="[[!showAddPerson]]"></paper-button>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/md_user_manager/create_profile.css b/chromium/chrome/browser/resources/md_user_manager/create_profile.css
deleted file mode 100644
index f0e12a72f57..00000000000
--- a/chromium/chrome/browser/resources/md_user_manager/create_profile.css
+++ /dev/null
@@ -1,159 +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. */
-
-.container {
- color: var(--paper-grey-800);
- margin: 0 auto;
- width: 624px;
-}
-
-#message-container {
- background-color: var(--google-red-700);
- color: white;
- left: 0;
- overflow: hidden;
- padding: 10px 16px;
- position: absolute;
- right: 0;
- top: 0;
-}
-
-#message-container iron-icon {
- height: 20px;
- width: 20px;
-}
-
-#message-container #message {
- -webkit-margin-start: 16px;
-}
-
-#message-container #supervised-user-import-existing {
- color: inherit;
- text-decoration: underline;
-}
-
-#title-bar {
- border-bottom: 1px solid rgba(0, 0, 0, .12);
- font-size: 16px;
- font-weight: 500;
- padding: 104px 0 16px;
-}
-
-#nameInput,
-paper-dropdown-menu {
- --paper-input-container: {
- padding: 0;
- };
- --paper-input-container-input: {
- color: inherit;
- font-size: inherit;
- };
-}
-
-#nameInput {
- margin-bottom: 24px;
- margin-top: 32px;
- width: 300px;
-}
-
-paper-dropdown-menu {
- margin-top: 12px;
- width: 200px;
-}
-
-paper-menu {
- --paper-menu: {
- color: inherit;
- padding: 0;
- };
- --paper-menu-selected-item: {
- font-weight: normal;
- }
-}
-
-paper-menu paper-item {
- font-size: inherit;
- min-height: 40px;
-}
-
-#icons #wrapper {
- display: flex;
- flex-wrap: wrap;
- margin: -12px;
-}
-
-#icons paper-button {
- background: var(--paper-grey-300);
- border: 1px solid rgba(0, 0, 0, .12);
- margin: 12px;
- min-width: 0;
- padding: 6px 4px;
-}
-
-#icons paper-button[active] {
- border-color: var(--google-blue-500);
-}
-
-#icons paper-button:focus:not([active]) {
- outline: 1px dotted #666;
-}
-
-#supervised-user-container {
- margin-top: 24px;
-}
-
-#supervised-user-container paper-checkbox {
- --paper-checkbox-label-spacing: 16px;
- --paper-checkbox-size: 20px;
-}
-
-#supervised-user-container #learn-more-accounts {
- -webkit-margin-start: 36px;
-}
-
-#supervised-user-container #learn-more {
- display: block;
- line-height: 20px;
-}
-
-#actions {
- bottom: 16px;
- display: flex;
- position: absolute;
- right: 16px;
-}
-
-:host-context([dir='rtl']) #actions {
- left: 16px;
- right: auto;
-}
-
-#actions paper-button {
- border-radius: 2px;
- font-weight: 500;
- line-height: 32px;
- margin: 0;
- min-width: 52px;
- padding: 0 16px;
-}
-
-#actions paper-spinner {
- align-self: center;
- height: 20px;
- width: 20px;
-}
-
-#actions #cancel {
- color: var(--paper-grey-600);
-}
-
-#actions #save {
- -webkit-margin-start: 8px;
- background: var(--google-blue-500);
- color: white;
-}
-
-#actions #save[disabled] {
- background: rgba(66, 133, 244, .5);
-}
diff --git a/chromium/chrome/browser/resources/md_user_manager/create_profile.html b/chromium/chrome/browser/resources/md_user_manager/create_profile.html
index d25395078b4..efe64cbd19c 100644
--- a/chromium/chrome/browser/resources/md_user_manager/create_profile.html
+++ b/chromium/chrome/browser/resources/md_user_manager/create_profile.html
@@ -1,82 +1,223 @@
+<link rel="import" href="chrome://md-user-manager/import_supervised_user.html">
<link rel="import" href="chrome://md-user-manager/profile_browser_proxy.html">
<link rel="import" href="chrome://md-user-manager/shared_styles.html">
+<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/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/util.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-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-dropdown-menu/paper-dropdown-menu.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-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-listbox/paper-listbox.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
<dom-module id="create-profile">
- <link rel="import" type="css"
- href="chrome://md-user-manager/create_profile.css">
- <link rel="import" type="css" href="chrome://resources/css/action_link.css">
<template>
- <style include="shared-styles"></style>
+ <style include="shared-styles">
+ .container {
+ color: var(--primary-text-color);
+ width: var(--page-width);
+ }
+
+ #message-container {
+ align-items: center;
+ background-color: var(--paper-red-50);
+ color: var(--google-red-700);
+ display: flex;
+ height: 40px;
+ left: 0;
+ overflow: hidden;
+ padding: 0 16px;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+
+ #message-container iron-icon {
+ --iron-icon-height: 20px;
+ --iron-icon-width: 20px;
+ }
+
+ #message-container #message {
+ -webkit-margin-start: 16px;
+ }
+
+ #message-container #supervised-user-import-existing {
+ color: inherit;
+ text-decoration: underline;
+ }
+
+ #title-bar {
+ border-bottom: 1px solid rgba(0, 0, 0, .12);
+ font-size: 16px;
+ font-weight: 500;
+ padding: 104px 0 16px;
+ }
+
+ #nameInput,
+ paper-dropdown-menu {
+ --paper-input-container-color: var(--primary-text-color);
+ --paper-input-container-focus-color: var(--google-blue-500);
+ --paper-input-container-input: {
+ font-size: inherit;
+ };
+ }
+
+ #nameInput {
+ margin-bottom: 24px;
+ margin-top: 32px;
+ width: 300px;
+ }
+
+ #icons {
+ display: flex;
+ flex-wrap: wrap;
+ margin: -12px;
+ }
+
+ #icons paper-button {
+ --paper-button: {
+ background: var(--paper-grey-300);
+ };
+ --paper-button-flat-keyboard-focus: {
+ background: var(--paper-grey-400);
+ };
+ border: 1px solid rgba(0, 0, 0, .12);
+ margin: 12px;
+ min-width: 0;
+ padding: 6px 4px;
+ }
+
+ #icons paper-button[active] {
+ border-color: var(--google-blue-500);
+ }
+
+ paper-checkbox {
+ --paper-checkbox-checked-color: var(--google-blue-500);
+ --paper-checkbox-label-spacing: 16px;
+ --paper-checkbox-size: 16px;
+ --paper-checkbox-unchecked-color: var(--paper-grey-600);
+ margin-top: 24px;
+ }
+
+ #supervised-user-container {
+ -webkit-padding-start: 32px;
+ }
+
+ #supervised-user-container #learn-more {
+ line-height: 20px;
+ }
+
+ #supervised-user-container paper-dropdown-menu {
+ margin-top: 4px;
+ width: 200px;
+ }
+
+ #supervised-user-container paper-listbox paper-item {
+ --paper-item: {
+ font-size: inherit;
+ min-height: 40px;
+ };
+ --paper-item-selected: {
+ font-weight: normal;
+ };
+ }
+
+ #supervised-user-container #import-user {
+ -webkit-margin-start: 16px;
+ }
+
+ #supervised-user-container #sign-in-howto-message {
+ margin-top: 12px;
+ }
+
+ #actions {
+ bottom: 16px;
+ display: flex;
+ position: absolute;
+ right: 16px;
+ }
+
+ :host-context([dir='rtl']) #actions {
+ left: 16px;
+ right: auto;
+ }
+
+ #actions paper-spinner {
+ align-self: center;
+ height: 20px;
+ width: 20px;
+ }
+ </style>
<div id="message-container" hidden="[[!message_]]">
- <iron-icon icon="warning"></iron-icon>
+ <iron-icon icon="cr:warning"></iron-icon>
<span id="message" inner-h-t-m-l="[[message_]]"></span>
</div>
<div class="container">
- <div id="title-bar" i18n-content="createProfileTitle"></div>
+ <div id="title-bar">$i18n{createProfileTitle}</div>
<paper-input id="nameInput" value="{{profileName_}}" pattern=".*\S.*"
no-label-float auto-validate>
</paper-input>
<div id="icons">
- <div id="wrapper">
<template is="dom-repeat" items="[[availableIconUrls_]]">
<paper-button toggles on-tap="onIconTap_" data-icon-url$="[[item]]"
active="[[isActiveIcon_(item, profileIconUrl_)]]">
<img src="[[item]]">
</paper-button>
</template>
- </div>
</div>
- <template is="dom-if" if="[[isSignedIn_(signedInUsers_)]]">
- <div id="supervised-user-container">
- <paper-checkbox checked="{{isSupervised_}}">
- [[i18n('manageProfilesSupervisedSignedInLabel')]]
- </paper-checkbox>
- <div id="learn-more-accounts">
- <a id="learn-more" is="action-link" on-tap="onLearnMoreTap_">
- [[i18n('learnMore')]]
- </a>
- <template is="dom-if" if="[[isSupervised_]]">
- <paper-dropdown-menu no-label-float>
- <paper-menu class="dropdown-content"
- selected="{{signedInUserIndex_}}"
- attr-for-selected="data-user-index">
- <paper-item data-user-index$="[[NO_USER_SELECTED]]">
- [[i18n('selectAnAccount')]]
+ <paper-checkbox checked="{{isSupervised_}}">
+ $i18n{manageProfilesSupervisedSignedInLabel}
+ </paper-checkbox>
+ <div id="supervised-user-container">
+ <div id="learn-more" >
+ <a is="action-link" on-tap="onLearnMoreTap_">$i18n{learnMore}</a>
+ <div>
+ <template is="dom-if" if="[[isSupervised_]]">
+ <template is="dom-if" if="[[isSignedIn_(signedInUsers_)]]">
+ <paper-dropdown-menu no-label-float>
+ <paper-listbox class="dropdown-content"
+ selected="{{signedInUserIndex_}}"
+ attr-for-selected="data-user-index">
+ <paper-item data-user-index$="[[sentinelSignedInUserIndex_]]">
+ $i18n{selectAnAccount}
+ </paper-item>
+ <template is="dom-repeat" items="[[signedInUsers_]]">
+ <paper-item data-user-index$="[[index]]">
+ [[item.username]]
</paper-item>
- <template is="dom-repeat" items="[[signedInUsers_]]">
- <paper-item data-user-index$="[[index]]">
- [[item.username]]
- </paper-item>
- </template>
- </paper-menu>
- </paper-dropdown-menu>
- </template>
+ </template>
+ </paper-listbox>
+ </paper-dropdown-menu>
+ <a id="import-user" is="action-link" on-tap="onImportUserTap_"
+ hidden="[[isImportUserLinkHidden_(createInProgress_,
+ signedInUserIndex_)]]">
+ $i18n{importExistingSupervisedUserLink}
+ </a>
+ </template>
+ <div id="sign-in-howto-message"
+ hidden="[[isSignedIn_(signedInUsers_)]]"
+ inner-h-t-m-l="[[i18nAllowIDAttr_('noSignedInUserMessage')]]">
</div>
- </div>
- </template>
+ </template>
+ </div>
<div id="actions">
<paper-spinner active="[[createInProgress_]]"></paper-spinner>
- <paper-button id="cancel" on-tap="onCancelTap_" i18n-content="cancel">
+ <paper-button id="cancel" class="action secondary"
+ on-tap="onCancelTap_">
+ $i18n{cancel}
</paper-button>
- <paper-button id="save" on-tap="onSaveTap_"
- i18n-content="createProfileConfirm"
+ <paper-button id="save" class="action primary" on-tap="onSaveTap_"
disabled="[[isSaveDisabled_(createInProgress_, profileName_)]]">
+ $i18n{createProfileConfirm}
</paper-button>
</div>
+ <import-supervised-user id="importUserPopup"></import-supervised-user>
</div>
</template>
<script src="chrome://md-user-manager/create_profile.js"></script>
diff --git a/chromium/chrome/browser/resources/md_user_manager/create_profile.js b/chromium/chrome/browser/resources/md_user_manager/create_profile.js
index e7d0113315a..8f5a151ac19 100644
--- a/chromium/chrome/browser/resources/md_user_manager/create_profile.js
+++ b/chromium/chrome/browser/resources/md_user_manager/create_profile.js
@@ -8,7 +8,7 @@
*/
(function() {
/**
- * It means the sentinel menu item is selected.
+ * Sentinel signed-in user's index value.
* @const {number}
*/
var NO_USER_SELECTED = -1;
@@ -94,10 +94,25 @@ Polymer({
value: NO_USER_SELECTED
},
+ /**
+ * Sentinel signed-in user's index value.
+ * @private {number}
+ */
+ sentinelSignedInUserIndex_: {
+ type: Number,
+ value: NO_USER_SELECTED,
+ readOnly: true
+ },
+
/** @private {!signin.ProfileBrowserProxy} */
browserProxy_: Object
},
+ listeners: {
+ 'tap': 'onTap_',
+ 'importUserPopup.import': 'onImportUserPopupImport_'
+ },
+
/** @override */
created: function() {
this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance();
@@ -120,9 +135,31 @@ Polymer({
this.browserProxy_.getAvailableIcons();
this.browserProxy_.getSignedInUsers();
+ },
+
+ /** @override */
+ attached: function() {
+ this.$.nameInput.focus();
+ },
+
+ /**
+ * Handles tap events from:
+ * - links within dynamic warning/error messages pushed from the browser.
+ * - the 'noSignedInUserMessage' i18n string.
+ * @param {!Event} event
+ * @private
+ */
+ onTap_: function(event) {
+ var element = Polymer.dom(event).rootTarget;
- // Alias on 'this' to use in html.
- this.NO_USER_SELECTED = NO_USER_SELECTED;
+ if (element.id == 'supervised-user-import-existing') {
+ this.onImportUserTap_(event);
+ event.preventDefault();
+ } else if (element.id == 'sign-in-to-chrome') {
+ this.browserProxy_.openUrlInLastActiveProfileBrowser(element.href);
+ event.preventDefault();
+ }
+ // TODO(mahmadi): handle tap event on '#reauth' to re-auth the custodian.
},
/**
@@ -137,7 +174,7 @@ Polymer({
/**
* Handler for when the profile defaults are pushed from the browser.
- * @param {ProfileInfo} profileInfo Default Info for the new profile.
+ * @param {!ProfileInfo} profileInfo Default Info for the new profile.
* @private
*/
handleProfileDefaults_: function(profileInfo) {
@@ -172,35 +209,61 @@ Polymer({
},
/**
+ * Handler for the 'Import Supervised User' link tap event.
+ * @param {!Event} event
+ * @private
+ */
+ onImportUserTap_: function(event) {
+ if (this.signedInUserIndex_ == NO_USER_SELECTED) {
+ // A custodian must be selected.
+ this.handleMessage_(this.i18n('custodianAccountNotSelectedError'));
+ } else {
+ var signedInUser = this.signedInUser_(this.signedInUserIndex_);
+ this.createInProgress_ = true;
+ this.browserProxy_.getExistingSupervisedUsers(signedInUser.profilePath)
+ .then(this.showImportSupervisedUserPopup_.bind(this),
+ this.handleMessage_.bind(this));
+ }
+ },
+
+ /**
* Handler for the 'Save' button tap event.
* @param {!Event} event
* @private
*/
onSaveTap_: function(event) {
- this.createInProgress_ = true;
-
if (!this.isSupervised_) {
// The new profile is not supervised. Go ahead and create it.
this.createProfile_();
} else if (this.signedInUserIndex_ == NO_USER_SELECTED) {
// If the new profile is supervised, a custodian must be selected.
this.handleMessage_(this.i18n('custodianAccountNotSelectedError'));
- this.createInProgress_ = false;
} else {
var signedInUser = this.signedInUser_(this.signedInUserIndex_);
- this.browserProxy_.getExistingSupervisedUsers(
- signedInUser.profilePath).then(
- this.createProfileIfValidSupervisedUser_.bind(this),
- /** @param {*} error */
- function(error) { this.handleMessage_(error); }.bind(this));
+ this.createInProgress_ = true;
+ this.browserProxy_.getExistingSupervisedUsers(signedInUser.profilePath)
+ .then(this.createProfileIfValidSupervisedUser_.bind(this),
+ this.handleMessage_.bind(this));
}
},
/**
+ * Displays the import supervised user popup.
+ * @param {!Array<!SupervisedUser>} supervisedUsers The list of existing
+ * supervised users.
+ * @private
+ */
+ showImportSupervisedUserPopup_: function(supervisedUsers) {
+ this.createInProgress_ = false;
+ this.$.importUserPopup.show(this.signedInUser_(this.signedInUserIndex_),
+ supervisedUsers);
+ },
+
+ /**
* Checks if the entered name matches name of an existing supervised user.
* If yes, the user is prompted to import the existing supervised user.
* If no, the new supervised profile gets created.
- * @param {Array<SupervisedUser>} supervisedUsers The list of existing
+ * @param {!Array<!SupervisedUser>} supervisedUsers The list of existing
* supervised users.
* @private
*/
@@ -224,12 +287,28 @@ Polymer({
}
}
+ var opts = {
+ 'substitutions':
+ [HTMLEscape(elide(this.profileName_, /* maxLength */ 50))],
+ 'attrs': {
+ 'id': function(node, value) {
+ return node.tagName == 'A';
+ },
+ 'is': function(node, value) {
+ return node.tagName == 'A' && value == 'action-link';
+ },
+ 'role': function(node, value) {
+ return node.tagName == 'A' && value == 'link';
+ },
+ 'tabindex': function(node, value) {
+ return node.tagName == 'A';
+ }
+ }
+ };
+
this.handleMessage_(allOnCurrentDevice ?
this.i18n('managedProfilesExistingLocalSupervisedUser') :
- this.i18n('manageProfilesExistingSupervisedUser',
- HTMLEscape(elide(this.profileName_, /* maxLength */ 50))));
-
- this.createInProgress_ = false;
+ this.i18nAdvanced('manageProfilesExistingSupervisedUser', opts));
return;
}
// No existing supervised user's name matches the entered profile name.
@@ -247,13 +326,29 @@ Polymer({
custodianProfilePath =
this.signedInUser_(this.signedInUserIndex_).profilePath;
}
-
+ this.createInProgress_ = true;
this.browserProxy_.createProfile(
- this.profileName_, this.profileIconUrl_, this.isSupervised_,
+ this.profileName_, this.profileIconUrl_, this.isSupervised_, '',
custodianProfilePath);
},
/**
+ * Handler for the 'import' event fired by #importUserPopup once a supervised
+ * user is selected to be imported and the popup closes.
+ * @param {!{detail: {supervisedUser: !SupervisedUser,
+ * signedInUser: !SignedInUser}}} event
+ * @private
+ */
+ onImportUserPopupImport_: function(event) {
+ var supervisedUser = event.detail.supervisedUser;
+ var signedInUser = event.detail.signedInUser;
+ this.createInProgress_ = true;
+ this.browserProxy_.createProfile(
+ supervisedUser.name, supervisedUser.iconURL, true, supervisedUser.id,
+ signedInUser.profilePath);
+ },
+
+ /**
* Handler for the 'Cancel' button tap event.
* @param {!Event} event
* @private
@@ -292,23 +387,40 @@ Polymer({
*/
handleSuccess_: function(profileInfo) {
this.createInProgress_ = false;
- this.fire('change-page', {page: 'user-pods-page'});
+ if (profileInfo.showConfirmation) {
+ this.fire('change-page', {page: 'supervised-create-confirm-page',
+ data: profileInfo});
+ } else {
+ this.fire('change-page', {page: 'user-pods-page'});
+ }
},
/**
* Handles profile create/import warning/error message pushed by the browser.
- * @param {string} message An HTML warning/error message.
+ * @param {*} message An HTML warning/error message.
* @private
*/
handleMessage_: function(message) {
this.createInProgress_ = false;
- this.message_ = message;
+ this.message_ = '' + message;
+ },
- // TODO(mahmadi): attach handler to '#supervised-user-import-existing'
- // in order to import supervised user with the given name.
+ /**
+ * Returns a translated message that contains link elements with the 'id'
+ * attribute.
+ * @param {string} id The ID of the string to translate.
+ * @private
+ */
+ i18nAllowIDAttr_: function(id) {
+ var opts = {
+ 'attrs': {
+ 'id' : function(node, value) {
+ return node.tagName == 'A';
+ }
+ }
+ };
- // TODO(mahmadi): attach handler to '#reauth' in order to re-authenticate
- // custodian.
+ return this.i18nAdvanced(id, opts);
},
/**
@@ -338,6 +450,17 @@ Polymer({
},
/**
+ * Returns True if the import supervised user link should be hidden.
+ * @param {boolean} createInProgress True if create/import is in progress
+ * @param {number} signedInUserIndex Index of the selected signed-in user.
+ * @return {boolean}
+ * @private
+ */
+ isImportUserLinkHidden_: function(createInProgress, signedInUserIndex) {
+ return createInProgress || !this.signedInUser_(signedInUserIndex);
+ },
+
+ /**
* Computed binding that returns True if there are any signed-in users.
* @param {!Array<!SignedInUser>} signedInUsers signed-in users.
* @return {boolean}
diff --git a/chromium/chrome/browser/resources/md_user_manager/icons.html b/chromium/chrome/browser/resources/md_user_manager/icons.html
new file mode 100644
index 00000000000..2143f12a3a9
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_user_manager/icons.html
@@ -0,0 +1,14 @@
+<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 name="user-manager" size="24">
+ <svg>
+ <defs>
+ <!--
+ 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="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 16.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.66 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"></path></g>
+ </defs>
+ </svg>
+</iron-iconset-svg>
diff --git a/chromium/chrome/browser/resources/md_user_manager/import_supervised_user.html b/chromium/chrome/browser/resources/md_user_manager/import_supervised_user.html
new file mode 100644
index 00000000000..7fbeff15144
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_user_manager/import_supervised_user.html
@@ -0,0 +1,148 @@
+<link rel="import" href="chrome://md-user-manager/profile_browser_proxy.html">
+<link rel="import" href="chrome://md-user-manager/shared_styles.html">
+<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/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.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-listbox/paper-listbox.html">
+
+<dom-module id="import-supervised-user">
+ <template>
+ <style include="shared-styles">
+ :host {
+ --item-height: 52px;
+ --items-container-max-height: calc(var(--item-height) * 4);
+ }
+
+ #backdrop {
+ align-items: center;
+ background: rgba(255, 255, 255, 0.6);
+ bottom: 0;
+ display: flex;
+ justify-content: center;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+
+ #dialog {
+ background: white;
+ border-radius: 2px;
+ box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14),
+ 0 6px 30px 5px rgba(0, 0, 0, 0.12),
+ 0 8px 10px -5px rgba(0, 0, 0, 0.4);
+ color: var(--primary-text-color);
+ width: 512px;
+ }
+
+ #title-bar {
+ -webkit-padding-end: 6px;
+ -webkit-padding-start: 16px;
+ align-items: center;
+ border-bottom: 1px solid rgba(0, 0, 0, .12);
+ font-size: 16px;
+ padding-bottom: 6px;
+ padding-top: 6px;
+ }
+
+ #title-bar paper-icon-button {
+ --paper-icon-button: {
+ padding: 10px;
+ };
+ }
+
+ #message {
+ padding: 20px 16px 16px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ }
+
+ paper-listbox {
+ max-height: var(--items-container-max-height);
+ overflow: auto;
+ }
+
+ paper-listbox paper-item {
+ --paper-item: {
+ font-size: inherit;
+ height: var(--item-height);
+ line-height: inherit;
+ padding: 0 16px;
+ };
+ --paper-item-disabled: {
+ color: inherit;
+ };
+ --paper-item-focused: {
+ background: rgba(0, 0, 0, .04);
+ };
+ --paper-item-focused-before: {
+ background: none;
+ };
+ --paper-item-selected: {
+ background: rgba(0, 0, 0, .04);
+ font-weight: normal;
+ };
+ }
+
+ paper-listbox paper-item .profile-img {
+ flex-shrink: 0;
+ }
+
+ paper-listbox paper-item .profile-name {
+ -webkit-margin-start: 10px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ paper-listbox paper-item .on-device {
+ -webkit-margin-start: 10px;
+ flex-shrink: 0;
+ }
+
+ #actions {
+ margin-top: 20px;
+ padding: 16px;
+ }
+ </style>
+ <template is="dom-if" if="[[!popupHidden_]]">
+ <div id="backdrop">
+ <div id="dialog">
+ <div id="title-bar" class="horizontal justified layout">
+ <span id="title">$i18n{supervisedUserImportTitle}</span>
+ <paper-icon-button icon="cr:close" on-tap="onCancelTap_">
+ </paper-icon-button>
+ </div>
+ <div id="message">[[getMessage_(supervisedUsers_)]]</div>
+ <paper-listbox selected="{{supervisedUserIndex_}}">
+ <template is="dom-repeat" items="[[supervisedUsers_]]">
+ <paper-item disabled="[[item.onCurrentDevice]]">
+ <img class="profile-img" src="[[item.iconURL]]"></img>
+ <div class="profile-name">[[item.name]]</div>
+ <div class="on-device" hidden="[[!item.onCurrentDevice]]">
+ $i18n{supervisedUserAlreadyOnThisDevice}
+ </div>
+ </paper-item>
+ </template>
+ </paper-listbox>
+ <div id="actions" class="horizontal end-justified layout">
+ <paper-button id="cancel" class="action secondary"
+ on-tap="onCancelTap_">
+ $i18n{cancel}
+ </paper-button>
+ <paper-button id="import" class="action primary"
+ on-tap="onImportTap_"
+ disabled="[[isImportDisabled_(supervisedUserIndex_)]]">
+ $i18n{supervisedUserImportOk}
+ </paper-button>
+ </div>
+ </div>
+ </div>
+ </template>
+ </template>
+ <script src="chrome://md-user-manager/import_supervised_user.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_user_manager/import_supervised_user.js b/chromium/chrome/browser/resources/md_user_manager/import_supervised_user.js
new file mode 100644
index 00000000000..f50131d2c0d
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_user_manager/import_supervised_user.js
@@ -0,0 +1,130 @@
+// 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 'import-supervised-user' is a popup that allows user to select
+ * a supervised profile from a list of profiles to import on the current device.
+ */
+(function() {
+/**
+ * It means no supervised user is selected.
+ * @const {number}
+ */
+var NO_USER_SELECTED = -1;
+
+Polymer({
+ is: 'import-supervised-user',
+
+ behaviors: [
+ I18nBehavior,
+ ],
+
+ properties: {
+ /**
+ * True if the element is currently hidden. The element toggles this in
+ * order to display itself or hide itself once done.
+ * @private {boolean}
+ */
+ popupHidden_: {
+ type: Boolean,
+ value: true
+ },
+
+ /**
+ * The currently signed in user and the custodian.
+ * @private {?SignedInUser}
+ */
+ signedInUser_: {
+ type: Object,
+ value: function() { return null; }
+ },
+
+ /**
+ * The list of supervised users managed by signedInUser_.
+ * @private {!Array<!SupervisedUser>}
+ */
+ supervisedUsers_: {
+ type: Array,
+ value: function() { return []; }
+ },
+
+ /**
+ * Index of the selected supervised user.
+ * @private {number}
+ */
+ supervisedUserIndex_: {
+ type: Number,
+ value: NO_USER_SELECTED
+ }
+ },
+
+ /**
+ * Displays the popup.
+ * @param {(!SignedInUser|undefined)} signedInUser
+ * @param {!Array<!SupervisedUser>} supervisedUsers
+ */
+ show: function(signedInUser, supervisedUsers) {
+ this.supervisedUsers_ = supervisedUsers;
+ this.supervisedUsers_.sort(function(a, b) {
+ if (a.onCurrentDevice != b.onCurrentDevice)
+ return a.onCurrentDevice ? 1 : -1;
+ return a.name.localeCompare(b.name);
+ });
+
+ this.supervisedUserIndex_ = NO_USER_SELECTED;
+
+ this.signedInUser_ = signedInUser || null;
+ if (this.signedInUser_)
+ this.popupHidden_ = false;
+
+ this.async(function() {
+ this.$$('paper-listbox').focus();
+ }.bind(this));
+ },
+
+ /**
+ * Computed binding that returns the appropriate import message depending on
+ * whether or not there are any supervised users to import.
+ * @param {!Array<!SupervisedUser>} supervisedUsers
+ * @private
+ * @return {string}
+ */
+ getMessage_: function(supervisedUsers) {
+ return supervisedUsers.length > 0 ? this.i18n('supervisedUserImportText') :
+ this.i18n('noSupervisedUserImportText');
+ },
+
+ /**
+ * Hides the popup.
+ * @private
+ */
+ onCancelTap_: function() {
+ this.popupHidden_ = true;
+ },
+
+ /**
+ * Returns true if the 'Import' button should be enabled and false otherwise.
+ * @private
+ * @return {boolean}
+ */
+ isImportDisabled_: function(supervisedUserIndex) {
+ return supervisedUserIndex == NO_USER_SELECTED;
+ },
+
+ /**
+ * Called when the user clicks the 'Import' button. it proceeds with importing
+ * the supervised user.
+ * @private
+ */
+ onImportTap_: function() {
+ var supervisedUser = this.supervisedUsers_[this.supervisedUserIndex_];
+ if (this.signedInUser_ && supervisedUser) {
+ this.popupHidden_ = true;
+ // Event is caught by create-profile.
+ this.fire('import', {supervisedUser: supervisedUser,
+ signedInUser: this.signedInUser_});
+ }
+ }
+});
+})();
diff --git a/chromium/chrome/browser/resources/md_user_manager/profile_browser_proxy.js b/chromium/chrome/browser/resources/md_user_manager/profile_browser_proxy.js
index b65f737ab84..2bc9630db21 100644
--- a/chromium/chrome/browser/resources/md_user_manager/profile_browser_proxy.js
+++ b/chromium/chrome/browser/resources/md_user_manager/profile_browser_proxy.js
@@ -10,13 +10,20 @@
/** @typedef {{username: string, profilePath: string}} */
var SignedInUser;
-/** @typedef {{name: string, filePath: string, isSupervised: boolean}} */
+/**
+ * @typedef {{name: string,
+ * filePath: string,
+ * isSupervised: boolean,
+ * custodianUsername: string,
+ * showConfirmation: boolean}}
+ */
var ProfileInfo;
-/** @typedef {{id: string,
- * name: string,
- * iconURL: string,
- * onCurrentDevice: boolean}}
+/**
+ * @typedef {{id: string,
+ * name: string,
+ * iconURL: string,
+ * onCurrentDevice: boolean}}
*/
var SupervisedUser;
@@ -62,11 +69,13 @@ cr.define('signin', function() {
* @param {string} profileIconUrl URL of the selected icon of the new
* profile.
* @param {boolean} isSupervised True if the new profile is supervised.
+ * @param {string} supervisedUserId ID of the supervised user to be
+ * imported.
* @param {string} custodianProfilePath Profile path of the custodian if
* the new profile is supervised.
*/
createProfile: function(profileName, profileIconUrl, isSupervised,
- custodianProfilePath) {
+ supervisedUserId, custodianProfilePath) {
assertNotReached();
},
@@ -91,6 +100,24 @@ cr.define('signin', function() {
*/
launchUser: function(profilePath) {
assertNotReached();
+ },
+
+ /**
+ * Opens the given url in a new tab in the browser instance of the last
+ * active profile. Hyperlinks don't work in the user manager since its
+ * browser instance does not support tabs.
+ * @param {string} url
+ */
+ openUrlInLastActiveProfileBrowser: function(url) {
+ assertNotReached();
+ },
+
+ /**
+ * Switches to the profile with the given path.
+ * @param {string} profilePath Path to the profile to switch to.
+ */
+ switchToProfile: function(profilePath) {
+ assertNotReached();
}
};
@@ -127,10 +154,10 @@ cr.define('signin', function() {
/** @override */
createProfile: function(profileName, profileIconUrl, isSupervised,
- custodianProfilePath) {
+ supervisedUserId, custodianProfilePath) {
chrome.send('createProfile',
- [profileName, profileIconUrl, false, isSupervised, '',
- custodianProfilePath]);
+ [profileName, profileIconUrl, false, isSupervised,
+ supervisedUserId, custodianProfilePath]);
},
/** @override */
@@ -146,6 +173,16 @@ cr.define('signin', function() {
/** @override */
launchUser: function(profilePath) {
chrome.send('launchUser', [profilePath]);
+ },
+
+ /** @override */
+ openUrlInLastActiveProfileBrowser: function(url) {
+ chrome.send('openUrlInLastActiveProfileBrowser', [url]);
+ },
+
+ /** @override */
+ switchToProfile: function(profilePath) {
+ chrome.send('switchToProfile', [profilePath]);
}
};
diff --git a/chromium/chrome/browser/resources/md_user_manager/shared_styles.html b/chromium/chrome/browser/resources/md_user_manager/shared_styles.html
index 28ab1f42621..689e70ed714 100644
--- a/chromium/chrome/browser/resources/md_user_manager/shared_styles.html
+++ b/chromium/chrome/browser/resources/md_user_manager/shared_styles.html
@@ -1,10 +1,66 @@
<dom-module id="shared-styles">
<template>
<style>
- a {
+ :root {
+ --error-color: var(--google-red-700);
+ --page-width: 624px;
+ --primary-text-color: var(--paper-grey-800);
+ --title-icon-color: var(--paper-grey-500);
+ }
+
+ a,
+ a:active,
+ a:hover,
+ a:visited {
color: var(--google-blue-700);
+ cursor: pointer;
text-decoration: none;
}
+
+ paper-button.action {
+ border-radius: 2px;
+ line-height: 32px;
+ margin: 0;
+ min-width: 52px;
+ padding: 0 16px;
+ }
+
+ paper-button.action.primary {
+ --paper-button: {
+ background: var(--google-blue-500);
+ color: white;
+ font-weight: 500;
+ };
+ --paper-button-flat-keyboard-focus: {
+ background: rgb(58, 117, 215);
+ font-weight: 500;
+ };
+ --paper-button-disabled: {
+ background: rgba(66, 133, 244, .5);
+ color: white;
+ };
+ }
+
+ paper-button.action.secondary {
+ --paper-button: {
+ color: var(--paper-grey-600);
+ font-weight: 500;
+ };
+ --paper-button-flat-keyboard-focus: {
+ background: rgba(0, 0, 0, .12);
+ font-weight: 500;
+ };
+ }
+
+ paper-button.action + paper-button.action {
+ -webkit-margin-start: 8px;
+ }
+
+ paper-listbox {
+ --paper-listbox: {
+ padding: 0;
+ };
+ }
</style>
</template>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.html b/chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.html
new file mode 100644
index 00000000000..230b455278f
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.html
@@ -0,0 +1,71 @@
+<link rel="import" href="chrome://md-user-manager/icons.html">
+<link rel="import" href="chrome://md-user-manager/profile_browser_proxy.html">
+<link rel="import" href="chrome://md-user-manager/shared_styles.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/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+
+<dom-module id="supervised-user-create-confirm">
+ <template>
+ <style include="shared-styles">
+ :host {
+ align-self: center;
+ }
+
+ #container {
+ color: var(--primary-text-color);
+ line-height: 20px;
+ width: var(--page-width);
+ }
+
+ #title-area {
+ border-bottom: 1px solid rgba(0, 0, 0, .12);
+ font-size: 16px;
+ padding-bottom: 16px;
+ }
+
+ #title-area iron-icon {
+ --iron-icon-height: 20px;
+ --iron-icon-width: 20px;
+ color: var(--title-icon-color);
+ }
+
+ .content-area {
+ padding-top: 32px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ }
+
+ #actions {
+ bottom: 16px;
+ position: absolute;
+ right: 16px;
+ }
+
+ :host-context([dir='rtl']) #actions {
+ left: 16px;
+ right: auto;
+ }
+ </style>
+ <div id="container">
+ <div id="title-area" class="horizontal justified layout">
+ <span id="title">[[titleText_(profileInfo)]]</span>
+ <iron-icon icon="user-manager:supervisor-account"></iron-icon>
+ </div>
+ <div class="content-area"
+ inner-h-t-m-l="[[confirmationMessage_(profileInfo)]]">
+ </div>
+ <div id="actions">
+ <paper-button id="ok" class="action secondary" on-tap="onOkTap_">
+ $i18n{supervisedUserCreatedDone}
+ </paper-button>
+ <paper-button id="switchUser" class="action primary"
+ on-tap="onSwitchUserTap_">
+ [[switchUserText_(profileInfo)]]
+ </paper-button>
+ </div>
+ </div>
+ </template>
+ <script src="chrome://md-user-manager/supervised_user_create_confirm.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.js b/chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.js
new file mode 100644
index 00000000000..f89d0d58c95
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_user_manager/supervised_user_create_confirm.js
@@ -0,0 +1,144 @@
+// 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 'supervised-user-create-confirm' is a page that is displayed
+ * upon successful creation of a supervised user. It contains information for
+ * the custodian on where to configure browsing restrictions as well as how to
+ * exit and childlock their profile.
+ */
+(function() {
+/**
+ * Maximum length of the supervised user profile name or custodian's username.
+ * @const {number}
+ */
+var MAX_NAME_LENGTH = 50;
+
+Polymer({
+ is: 'supervised-user-create-confirm',
+
+ behaviors: [
+ I18nBehavior
+ ],
+
+ properties: {
+ /**
+ * Profile Info of the supervised user that is passed to the page.
+ * @type {?ProfileInfo}
+ */
+ profileInfo: {
+ type: Object,
+ value: function() { return null; }
+ },
+
+ /** @private {!signin.ProfileBrowserProxy} */
+ browserProxy_: Object
+ },
+
+ listeners: {
+ 'tap': 'onTap_'
+ },
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance();
+ },
+
+ /**
+ * Handles tap events from dynamically created links in the
+ * supervisedUserCreatedText i18n string.
+ * @param {!Event} event
+ * @private
+ */
+ onTap_: function(event) {
+ var element = Polymer.dom(event).rootTarget;
+
+ // Handle the tap event only if the target is a '<a>' element.
+ if (element.nodeName == 'A') {
+ this.browserProxy_.openUrlInLastActiveProfileBrowser(element.href);
+ event.preventDefault();
+ }
+ },
+
+ /**
+ * Returns the shortened profile name or empty string if |profileInfo| is
+ * null.
+ * @param {?ProfileInfo} profileInfo
+ * @return {string}
+ * @private
+ */
+ elideProfileName_: function(profileInfo) {
+ var name = profileInfo ? profileInfo.name : '';
+ return elide(name, MAX_NAME_LENGTH);
+ },
+
+ /**
+ * Returns the shortened custodian username or empty string if |profileInfo|
+ * is null.
+ * @param {?ProfileInfo} profileInfo
+ * @return {string}
+ * @private
+ */
+ elideCustodianUsername_: function(profileInfo) {
+ var name = profileInfo ? profileInfo.custodianUsername : '';
+ return elide(name, MAX_NAME_LENGTH);
+ },
+
+ /**
+ * Computed binding returning the text of the title section.
+ * @param {?ProfileInfo} profileInfo
+ * @return {string}
+ * @private
+ */
+ titleText_: function(profileInfo) {
+ return this.i18n('supervisedUserCreatedTitle',
+ this.elideProfileName_(profileInfo));
+ },
+
+ /**
+ * Computed binding returning the sanitized confirmation HTML message that is
+ * safe to set as innerHTML.
+ * @param {?ProfileInfo} profileInfo
+ * @return {string}
+ * @private
+ */
+ confirmationMessage_: function(profileInfo) {
+ return this.i18n('supervisedUserCreatedText',
+ this.elideProfileName_(profileInfo),
+ this.elideCustodianUsername_(profileInfo));
+ },
+
+ /**
+ * Computed binding returning the text of the 'Switch To User' button.
+ * @param {?ProfileInfo} profileInfo
+ * @return {string}
+ * @private
+ */
+ switchUserText_: function(profileInfo) {
+ return this.i18n('supervisedUserCreatedSwitch',
+ this.elideProfileName_(profileInfo));
+ },
+
+ /**
+ * Handler for the 'Ok' button tap event.
+ * @param {!Event} event
+ * @private
+ */
+ onOkTap_: function(event) {
+ // Event is caught by user-manager-pages.
+ this.fire('change-page', {page: 'user-pods-page'});
+ },
+
+ /**
+ * Handler for the 'Switch To User' button tap event.
+ * @param {!Event} event
+ * @private
+ */
+ onSwitchUserTap_: function(event) {
+ this.browserProxy_.switchToProfile(this.profileInfo.filePath);
+ // Event is caught by user-manager-pages.
+ this.fire('change-page', {page: 'user-pods-page'});
+ }
+});
+})();
diff --git a/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.css b/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.css
deleted file mode 100644
index 0cb0fc80d1e..00000000000
--- a/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.css
+++ /dev/null
@@ -1,56 +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. */
-
-:host {
- align-self: center;
-}
-
-#container {
- color: var(--google-grey-800);
- line-height: 20px;
- width: 624px;
-}
-
-#title-area {
- border-bottom: 1px solid rgba(0, 0, 0, .12);
- font-size: 16px;
- padding-bottom: 16px;
-}
-
-#title-area iron-icon {
- --iron-icon-height: 20px;
- --iron-icon-width: 20px;
- color: var(--google-grey-500);
-}
-
-.content-area {
- padding-top: 32px;
- white-space: pre-wrap;
- word-wrap: break-word;
-}
-
-#actions {
- bottom: 16px;
- position: absolute;
- right: 16px;
-}
-
-:host-context([dir='rtl']) #actions {
- left: 16px;
- right: auto;
-}
-
-#actions paper-button {
- border-radius: 2px;
- font-weight: 500;
- line-height: 32px;
- margin: 0;
- min-width: 52px;
- padding: 0 16px;
-}
-
-#actions #done {
- background: var(--google-blue-500);
- color: white;
-}
diff --git a/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html b/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html
index e2abb463556..c10cc3a1874 100644
--- a/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html
+++ b/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.html
@@ -1,25 +1,62 @@
+<link rel="import" href="chrome://md-user-manager/icons.html">
<link rel="import" href="chrome://md-user-manager/shared_styles.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/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<dom-module id="supervised-user-learn-more">
- <link rel="import" type="css"
- href="chrome://md-user-manager/supervised_user_learn_more.css">
<template>
- <style include="shared-styles"></style>
+ <style include="shared-styles">
+ :host {
+ align-self: center;
+ }
+
+ #container {
+ color: var(--primary-text-color);
+ line-height: 20px;
+ width: var(--page-width);
+ }
+
+ #title-area {
+ border-bottom: 1px solid rgba(0, 0, 0, .12);
+ font-size: 16px;
+ padding-bottom: 16px;
+ }
+
+ #title-area iron-icon {
+ --iron-icon-height: 20px;
+ --iron-icon-width: 20px;
+ color: var(--title-icon-color);
+ }
+
+ .content-area {
+ padding-top: 32px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ }
+
+ #actions {
+ bottom: 16px;
+ position: absolute;
+ right: 16px;
+ }
+
+ :host-context([dir='rtl']) #actions {
+ left: 16px;
+ right: auto;
+ }
+ </style>
<div id="container">
<div id="title-area" class="horizontal justified layout">
- <span id="title" i18n-content="supervisedUserLearnMoreTitle"></span>
- <iron-icon icon="supervisor-account"></iron-icon>
+ <span id="title">$i18n{supervisedUserLearnMoreTitle}</span>
+ <iron-icon icon="user-manager:supervisor-account"></iron-icon>
</div>
<div class="content-area"
i18n-values=".innerHTML:supervisedUserLearnMoreText">
</div>
<div id="actions">
- <paper-button id="done" on-tap="onDoneTap_"
- i18n-content="supervisedUserLearnMoreDone">
+ <paper-button id="done" class="action primary" on-tap="onDoneTap_">
+ $i18n{supervisedUserLearnMoreDone}
</paper-button>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.js b/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.js
index 1a0093887ac..394a5598505 100644
--- a/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.js
+++ b/chromium/chrome/browser/resources/md_user_manager/supervised_user_learn_more.js
@@ -10,8 +10,38 @@
Polymer({
is: 'supervised-user-learn-more',
+ properties: {
+ /** @private {!signin.ProfileBrowserProxy} */
+ browserProxy_: Object
+ },
+
+ listeners: {
+ 'tap': 'onTap_'
+ },
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance();
+ },
+
+ /**
+ * Handles tap events from dynamically created links in the
+ * supervisedUserLearnMoreText i18n string.
+ * @param {!Event} event
+ * @private
+ */
+ onTap_: function(event) {
+ var element = Polymer.dom(event).rootTarget;
+
+ // Handle the tap event only if the target is a '<a>' element.
+ if (element.nodeName == 'A') {
+ this.browserProxy_.openUrlInLastActiveProfileBrowser(element.href);
+ event.preventDefault();
+ }
+ },
+
/**
- * Handler for the 'Done' button click event.
+ * Handler for the 'Done' button tap event.
* @param {!Event} event
* @private
*/
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager.html b/chromium/chrome/browser/resources/md_user_manager/user_manager.html
index 6dd9fdc8b4d..71d93d6e187 100644
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager.html
+++ b/chromium/chrome/browser/resources/md_user_manager/user_manager.html
@@ -1,12 +1,12 @@
<!doctype html>
-<html i18n-values="build:buildType;
- dir:textdirection;
- lang:language;
- screen:screenType">
+<html build="$i18n{buildType}"
+ dir="$i18n{textdirection}"
+ lang="$i18n{language}"
+ screen="$i18n{screenType}">
<head>
<meta charset="utf-8">
<meta name="google" value="notranslate">
- <title i18n-content="title"></title>
+ <title>$i18n{title}</title>
<link rel="stylesheet" href="../../../../ui/login/account_picker/screen_account_picker.css">
<link rel="stylesheet" href="../../../../ui/login/account_picker/user_pod_row.css">
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager.js b/chromium/chrome/browser/resources/md_user_manager/user_manager.js
index caaf404f0a4..6864f2c15ae 100644
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager.js
+++ b/chromium/chrome/browser/resources/md_user_manager/user_manager.js
@@ -6,6 +6,7 @@
<include src="../../../../ui/login/bubble.js">
<include src="../../../../ui/login/login_ui_tools.js">
<include src="../../../../ui/login/display_manager.js">
+<include src="../../../../ui/login/account_picker/user_pod_template.js">
<include src="../../../../ui/login/account_picker/screen_account_picker.js">
<include src="../../../../ui/login/account_picker/user_pod_row.js">
@@ -14,6 +15,13 @@ cr.define('cr.ui', function() {
var DisplayManager = cr.ui.login.DisplayManager;
/**
+ * Maximum possible height of the #login-header-bar, including the padding
+ * and the border.
+ * @const {number}
+ */
+ var MAX_LOGIN_HEADER_BAR_HEIGHT = 57;
+
+ /**
* Manages initialization of screens, transitions, and error messages.
* @constructor
* @extends {DisplayManager}
@@ -24,6 +32,28 @@ cr.define('cr.ui', function() {
UserManager.prototype = {
__proto__: DisplayManager.prototype,
+
+ /**
+ * Indicates that this is the Material Design Desktop User Manager.
+ * @type {boolean}
+ */
+ newDesktopUserManager: true,
+
+ /**
+ * @override
+ * Overrides clientAreaSize in DisplayManager. When a new profile is created
+ * the #outer-container page may not be visible yet, so user-pods cannot be
+ * placed correctly. Therefore, we use dimensions of the #animated-pages.
+ * @type {{width: number, height: number}}
+ */
+ get clientAreaSize() {
+ var userManagerPages = document.querySelector('user-manager-pages');
+ var width = userManagerPages.offsetWidth;
+ // Deduct the maximum possible height of the #login-header-bar from the
+ // height of #animated-pages. Result is the remaining visible height.
+ var height = userManagerPages.offsetHeight - MAX_LOGIN_HEADER_BAR_HEIGHT;
+ return {width: width, height: height};
+ }
};
/**
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.css b/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.css
deleted file mode 100644
index 385e3ee3f79..00000000000
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.css
+++ /dev/null
@@ -1,12 +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. */
-
-neon-animated-pages {
- height: 100%;
-}
-
-neon-animated-pages > div {
- display: flex;
- justify-content: center;
-}
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.html b/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.html
index 5ce6be90406..cda9ca8e4f9 100644
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.html
+++ b/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.html
@@ -1,34 +1,56 @@
<link rel="import" href="chrome://md-user-manager/create_profile.html">
+<link rel="import" href="chrome://md-user-manager/supervised_user_create_confirm.html">
<link rel="import" href="chrome://md-user-manager/supervised_user_learn_more.html">
<link rel="import" href="chrome://resources/html/polymer.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-right-animation.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/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animated-pages.html">
<dom-module id="user-manager-pages">
- <link rel="import" type="css"
- href="chrome://md-user-manager/user_manager_pages.css">
<template>
+ <style>
+ neon-animated-pages {
+ height: 100%;
+ }
+
+ neon-animatable {
+ display: flex;
+ justify-content: center;
+ }
+
+ /* neon-animated-pages does not automatically hide what's under content */
+ neon-animatable:not(.iron-selected) > ::content > * {
+ display: none !important;
+ }
+ </style>
<neon-animated-pages id="animatedPages" attr-for-selected="id"
- selected="[[selectedPage_]]" entry-animation="slide-from-left-animation"
- exit-animation="slide-right-animation">
- <div id="create-user-page">
- <template is="dom-if" if="[[isPageVisible_(selectedPage_, 'create-user-page')]]" restamp>
+ selected="[[selectedPage_]]" entry-animation="fade-in-animation"
+ exit-animation="fade-out-animation">
+ <neon-animatable id="create-user-page">
+ <template is="dom-if"
+ if="[[isPageVisible_(selectedPage_, 'create-user-page')]]" restamp>
<create-profile></create-profile>
</template>
- </div>
- <div id="user-pods-page">
- <template is="dom-if" if="[[isPageVisible_(selectedPage_, 'user-pods-page')]]">
+ </neon-animatable>
+ <neon-animatable id="user-pods-page">
<content></content>
- </template>
- </div>
- <div id="supervised-learn-more-page">
+ </neon-animatable>
+ <neon-animatable id="supervised-learn-more-page">
<template is="dom-if"
- if="[[isPageVisible_(selectedPage_, 'supervised-learn-more-page')]]">
+ if="[[isPageVisible_(selectedPage_,
+ 'supervised-learn-more-page')]]">
<supervised-user-learn-more></supervised-user-learn-more>
</template>
- </div>
- <content></content>
+ </neon-animatable>
+ <neon-animatable id="supervised-create-confirm-page">
+ <template is="dom-if"
+ if="[[isPageVisible_(selectedPage_,
+ 'supervised-create-confirm-page')]]">
+ <supervised-user-create-confirm profile-info="[[pageData_]]">
+ </supervised-user-create-confirm>
+ </template>
+ </neon-animatable>
</neon-animated-pages>
</template>
<script src="chrome://md-user-manager/user_manager_pages.js"></script>
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.js b/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.js
index 434f840f1df..21c3982e555 100644
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.js
+++ b/chromium/chrome/browser/resources/md_user_manager/user_manager_pages.js
@@ -17,6 +17,15 @@ Polymer({
selectedPage_: {
type: String,
value: 'user-pods-page'
+ },
+
+ /**
+ * Data passed to the currently selected page.
+ * @private {?Object}
+ */
+ pageData_: {
+ type: Object,
+ value: null
}
},
@@ -30,6 +39,7 @@ Polymer({
* @private
*/
changePage_: function(e) {
+ this.pageData_ = e.detail.data || null;
this.selectedPage_ = e.detail.page;
},
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager_styles.html b/chromium/chrome/browser/resources/md_user_manager/user_manager_styles.html
index 7b0785b4975..38379b4d829 100644
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager_styles.html
+++ b/chromium/chrome/browser/resources/md_user_manager/user_manager_styles.html
@@ -4,10 +4,10 @@
<template>
<style include="shared-styles">
body {
- background-color: #eee;
+ background-color: var(--paper-grey-200);
}
- /* Overrides for the desktop user manager screen. */
+ user-manager-pages,
#login-header-bar {
bottom: 0;
left: 0;
@@ -15,8 +15,23 @@
right: 0;
}
+ user-manager-pages {
+ top: 0;
+ }
+
+ #login-header-bar.shadow {
+ box-shadow: 0 -1px 3px rgba(0, 0, 0, .2);
+ }
+
+ /* Overrides src/ui/login/screen_container.css for the desktop user
+ * manager. */
+
#outer-container {
min-height: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding: 40px 0 30px;
+ z-index: initial;
}
.bubble.faded {
@@ -24,193 +39,230 @@
}
.pod {
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
- height: 226px;
- /* On non-retina desktop, the text is blurry if we use the scale3d()
- inherited from user_pod_row.js */
- transform: scale(0.9);
- }
-
- podrow[ncolumns='6'] .pod {
- transform: scale(0.8);
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .24),
+ 0 0 2px 0 rgba(0, 0, 0, .12);
+ color: var(--paper-grey-800);
+ cursor: default;
+ height: auto;
+ transform: none;
+ width: auto;
}
- /* Because of crbug.com/406529, the text in the .name div is janky if there's
- both a transform:scale and a transition:opacity applied to a div, so we must
- apply the opacity change to the children instead. */
.pod.faded {
- opacity: 1;
- }
-
- .pod.faded .user-image-pane,
- .pod.faded .main-pane {
- opacity: .4;
- }
-
- .pod.hovered:not(.focused) {
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ opacity: .6;
}
.pod.focused {
- box-shadow: 0 16px 21px rgba(0, 0, 0, 0.2);
- transform: scale(1) !important;
- }
-
- .pod.focused.locked {
- box-shadow: 0 12px 21px rgba(0, 0, 0, 0.2);
- height: 220px;
+ box-shadow: 0 10px 10px 0 rgba(0, 0, 0, .26),
+ 0 14px 28px 0 rgba(0, 0, 0, .25);
}
- .user-image-pane {
+ .pod .user-image-pane {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
- height: 180px;
- left: 0;
- top: 0;
- width: 180px;
+ overflow: hidden;
+ position: static;
}
- html[dir=rtl] .user-image-pane {
- right: 0;
+ .pod .user-image {
+ height: 160px;
+ width: 160px;
}
- .pod .name {
- margin-top: 12px;
+ .pod .main-pane {
+ line-height: 20px;
+ padding: 10px;
+ position: static;
}
- .pod .user-image {
- height: 180px;
- width: 180px;
+ .pod .main-pane .name-container {
+ display: block;
+ position: static;
+ width: auto;
}
- .pod input[type='password'] {
- height: 45px; /* 1px shorter as to not overlap the pod's rounded corners */
- top: 1px;
+ .pod .main-pane .name-container .name,
+ .reauth-hint-container .reauth-name-hint {
+ color: inherit;
+ font-size: inherit;
+ margin: 0;
+ padding: 0;
+ text-align: initial;
+ width: 120px;
}
.pod .indicator-container {
- background-color: rgba(255, 255, 255, 0.85);
- border-radius: 16px;
- height: 32px;
- left: 8px;
- position: absolute;
- top: 8px;
- }
-
- html[dir=rtl] .pod .indicators {
+ bottom: 10px;
+ height: 20px;
left: auto;
- right: 8px;
+ position: absolute;
+ right: 10px;
+ top: auto;
+ width: 20px;
}
- .pod .indicator {
- background-position: center;
- background-repeat: no-repeat;
- background-size: 18px;
- display: none;
- float: left;
- height: 32px;
- width: 32px;
+ html[dir='rtl'] .pod .indicator-container {
+ left: 10px;
+ right: auto;
}
/* Using -webkit-mask on the indicators allows us to tweak the color. */
- .pod .indicator-container > div {
+ .pod .indicator-container > .indicator {
-webkit-mask-position: center;
-webkit-mask-repeat: no-repeat;
- -webkit-mask-size: 24px;
+ -webkit-mask-size: 16px;
+ background: var(--paper-grey-600);
+ display: none;
+ height: 100%;
}
.pod.locked .locked-indicator {
-webkit-mask-image: url(../../../../ui/webui/resources/images/lock.svg);
- background-color: var(--paper-grey-600);
- display: initial;
+ display: block;
}
.pod.legacy-supervised .legacy-supervised-indicator {
-webkit-mask-image:
url(../../../../ui/webui/resources/images/supervisor_account.svg);
- background-color: var(--google-blue-500);
- display: initial;
+ display: block;
}
.pod.child .child-indicator {
-webkit-mask-image:
url(../../../../ui/webui/resources/images/account_child_invert.svg);
- background-color: var(--google-blue-500);
- display: initial;
+ display: block;
}
- .main-pane {
- left: 0;
+ .action-box-area:focus ~ .user-image-gradient-area,
+ .action-box-area.hovered ~ .user-image-gradient-area {
+ background-image: linear-gradient(rgba(0, 0, 0, .2), transparent 100%);
+ display: initial;
+ height: 40px;
+ position: absolute;
top: 0;
+ width: 100%;
}
- html[dir=rtl] .main-pane {
- right: 0;
+ .action-box-area {
+ background-color: transparent;
}
- .name-container,
- .pod.focused:not(.multiprofiles-policy-applied) .auth-container {
- top: 180px;
- width: 180px;
+ .action-box-area.menu-moved-up {
+ transform: none;
}
- .pod.focused:not(.locked) .name-container {
- display: block;
+ .action-box-area .action-box-button {
+ display: none;
}
- .pod .name {
- color: var(--paper-grey-800);
- font-size: 15px;
- margin-top: 11px;
+ .action-box-area .action-box-icon {
+ color: white;
+ display: inline-flex;
+ margin-top: 4px;
}
.pod.focused:not(.locked) .auth-container {
display: none;
}
- .pod[auth-type='offlinePassword'].focused.locked .password-entry-container {
- display: flex;
- flex: auto;
+ .pod.focused:not(.multiprofiles-policy-applied) .auth-container {
+ left: 0;
}
- .action-box-area {
- background-color: var(--google-grey-100);
- height: 24px;
- /* Because of crbug.com/406529, the text in the .name div is janky if there's
- an opacity transition in this div. */
- transition: none;
- width: 24px;
+ .pod .auth-container input[type='password'] {
+ line-height: inherit;
+ padding: 10px;
+ top: 0;
+ width: 140px;
}
- .action-box-button,
- .action-box-button:hover,
- .action-box-area.active .action-box-button {
- background-image: none;
- border-left: 6px solid transparent;
- border-right: 6px solid transparent;
- border-top: 6px solid #989898;
- height: 0;
- left: 6px;
+ .pod .auth-container input[type='password']:focus {
+ outline: 0;
+ }
+
+ .pod[auth-type='onlineSignIn'] .reauth-hint-container {
+ flex-direction: row-reverse;
margin: 0;
- position: absolute;
- top: 9px;
- width: 0;
+ padding: 10px;
+ }
+
+ .reauth-hint-container .reauth-warning {
+ --iron-icon-height: 20px;
+ --iron-icon-width: 20px;
}
- .action-box-button:hover,
.action-box-area.active .action-box-button {
- border-top: 6px solid #4c4c4c;
+ display: none;
}
- .action-box-remove-user-warning .remove-warning-button {
- height: 30px;
+ .action-box-area.active ~ .action-box-menu:not(.menu-moved-up) {
+ top: 8px;
+ }
+
+ .action-box-area.active ~ .action-box-menu {
+ border: none;
+ box-shadow: 0 10px 20px 0 rgba(0, 0, 0, .19);
+ right: 8px;
+ width: 224px;
+ }
+
+ html[dir=rtl] .action-box-area.active ~ .action-box-menu {
+ left: 8px;
+ right: auto;
+ }
+
+ .action-box-menu-title {
+ color: inherit;
+ padding: 16px 12px;
+ }
+
+ .action-box-menu-title-name,
+ .action-box-menu-title-email {
+ height: auto;
+ }
+
+ .action-box-menu-title-email {
+ color: var(--paper-grey-600);
+ }
+
+ .action-box-menu-remove {
+ border-top: 1px solid rgba(0, 0, 0, .12);
+ line-height: 32px;
+ padding: 8px 12px;
+ }
+
+ .action-box-remove-user-warning {
+ border-top: 1px solid rgba(0, 0, 0, .12);
+ font-size: inherit;
+ line-height: 20px;
+ padding: 12px;
+ text-align: center;
}
- .action-box-remove-user-warning .remove-warning-button:focus {
- /* Override the default blue border inherited from
- button.custom-appearance:focus. */
- border: 1px solid transparent !important;
- box-shadow: inset 0 0 0 1px #fff;
+ .action-box-remove-user-warning > * {
+ text-align: initial;
+ word-wrap: break-word;
+ }
+
+ .total-count,
+ .pod:not(.synced) .action-box-remove-user-warning-text {
+ font-weight: 500;
+ }
+
+ .action-box-remove-user-warning .remove-warning-button {
+ --paper-button: {
+ background: var(--google-red-700);
+ color: white;
+ font-weight: 500;
+ };
+ --paper-button-flat-keyboard-focus: {
+ background: rgb(173, 50, 36);
+ font-weight: 500;
+ };
+ border-radius: 2px;
+ line-height: 32px;
+ min-width: 72px;
+ padding: 0 16px;
}
</style>
</template>
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.css b/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.css
deleted file mode 100644
index 625d78dd9c6..00000000000
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.css
+++ /dev/null
@@ -1,160 +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. */
-
-.tutorial-slide {
- -webkit-transition: opacity 200ms ease-in-out;
- background-color: white;
- border-radius: 2px;
- bottom: 0;
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25);
- height: 408px;
- left: 0;
- margin: auto;
- position: absolute;
- right: 0;
- top: 0;
- width: 320px;
- z-index: 100;
-}
-
-:host.single-pod #yourChrome,
-:host.single-pod #complete {
- -webkit-margin-start: 30px;
-}
-
-#guests {
- bottom: 20px;
- left: auto;
- margin: 0;
- right: 100px;
- top: auto;
-}
-
-:host-context([dir='rtl']) #guests {
- left: 100px;
- right: auto;
-}
-
-#friends,
-#notYou {
- bottom: 20px;
- left: auto;
- margin: 0;
- right: 20px;
- top: auto;
-}
-
-:host-context([dir='rtl']) #friends,
-:host-context([dir='rtl']) #notYou {
- left: 20px;
- right: auto;
-}
-
-#notYou {
- height: 100px;
- width: 240px;
-}
-
-.slide-contents {
- padding: 0 20px;
- text-align: center;
-}
-
-.slide-title {
- color: black;
- font-size: 20px;
- line-height: 20px;
- margin: 30px 0;
-}
-
-.slide-text {
- color: var(--google-grey-600);
- font-size: 15px;
- line-height: 20px;
-}
-
-.slide-buttons {
- bottom: 20px;
- position: absolute;
- text-align: center;
- width: 100%;
-}
-
-.slide-buttons [is='action-link'] {
- width: 100%;
-}
-
-.slide-buttons button {
- bottom: 0;
- height: 35px;
- padding: 0 15px;
- width: 138px;
-}
-
-.arrow-down {
- border-left: 15px solid transparent;
- border-right: 15px solid transparent;
- border-top: 15px solid white;
- bottom: -15px;
- height: 0;
- position: absolute;
- right: 40px;
- width: 0;
-}
-
-:host-context([dir='rtl']) .arrow-down {
- left: 40px;
- right: auto;
-}
-
-#guests .arrow-down {
- right: 110px;
-}
-
-:host-context([dir='rtl']) #guests .arrow-down {
- left: 110px;
- right: auto;
-}
-
-.slide-image {
- height: 182px;
-}
-
-#yourChrome .slide-image {
- background-color: rgb(241, 202, 58);
- background-image:
- url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_YOUR_CHROME);
-}
-
-#guests .slide-image {
- background-color: rgb(90, 196, 144);
- background-image: url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_GUESTS);
-}
-
-#friends .slide-image {
- background-color: var(--paper-light-blue-100);
- background-image:
- url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_FRIENDS);
-}
-
-#complete .slide-image {
- background-color: white;
- background-image:
- url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_COMPLETE);
-}
-
-#notYou #dismiss {
- position: absolute;
- right: 5px;
- top: 5px;
-}
-
-#notYou #slide-add-user {
- margin-top: 10px;
-}
-
-:host-context([dir='rtl']) #notYou #dismiss {
- left: 5px;
- right: auto;
-}
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.html b/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.html
index 25c81bc844c..0e4b65fb1a3 100644
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.html
+++ b/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.html
@@ -1,27 +1,180 @@
<link rel="import" href="chrome://md-user-manager/shared_styles.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.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/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="user-manager-tutorial">
- <link rel="import" type="css"
- href="chrome://md-user-manager/user_manager_tutorial.css">
- <link rel="import" type="css" href="chrome://resources/css/action_link.css">
<template>
- <style include="shared-styles"></style>
+ <style include="shared-styles">
+ .tutorial-slide {
+ -webkit-transition: opacity 200ms ease-in-out;
+ background-color: white;
+ border-radius: 2px;
+ bottom: 0;
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25);
+ height: 408px;
+ left: 0;
+ margin: auto;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 320px;
+ z-index: 100;
+ }
+
+ :host.single-pod #yourChrome,
+ :host.single-pod #complete {
+ -webkit-margin-start: 30px;
+ }
+
+ #guests {
+ bottom: 20px;
+ left: auto;
+ margin: 0;
+ right: 100px;
+ top: auto;
+ }
+
+ :host-context([dir='rtl']) #guests {
+ left: 100px;
+ right: auto;
+ }
+
+ #friends,
+ #notYou {
+ bottom: 20px;
+ left: auto;
+ margin: 0;
+ right: 20px;
+ top: auto;
+ }
+
+ :host-context([dir='rtl']) #friends,
+ :host-context([dir='rtl']) #notYou {
+ left: 20px;
+ right: auto;
+ }
+
+ #notYou {
+ height: 100px;
+ width: 240px;
+ }
+
+ .slide-contents {
+ padding: 0 20px;
+ text-align: center;
+ }
+
+ .slide-title {
+ color: black;
+ font-size: 20px;
+ line-height: 20px;
+ margin: 30px 0;
+ }
+
+ .slide-text {
+ color: var(--google-grey-600);
+ font-size: 15px;
+ line-height: 20px;
+ }
+
+ .slide-buttons {
+ bottom: 20px;
+ position: absolute;
+ text-align: center;
+ width: 100%;
+ }
+
+ .slide-buttons [is='action-link'] {
+ width: 100%;
+ }
+
+ .slide-buttons button {
+ bottom: 0;
+ height: 35px;
+ padding: 0 15px;
+ width: 138px;
+ }
+
+ .arrow-down {
+ border-left: 15px solid transparent;
+ border-right: 15px solid transparent;
+ border-top: 15px solid white;
+ bottom: -15px;
+ height: 0;
+ position: absolute;
+ right: 40px;
+ width: 0;
+ }
+
+ :host-context([dir='rtl']) .arrow-down {
+ left: 40px;
+ right: auto;
+ }
+
+ #guests .arrow-down {
+ right: 110px;
+ }
+
+ :host-context([dir='rtl']) #guests .arrow-down {
+ left: 110px;
+ right: auto;
+ }
+
+ .slide-image {
+ height: 182px;
+ }
+
+ #yourChrome .slide-image {
+ background-color: rgb(241, 202, 58);
+ background-image:
+ url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_YOUR_CHROME);
+ }
+
+ #guests .slide-image {
+ background-color: rgb(90, 196, 144);
+ background-image: url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_GUESTS);
+ }
+
+ #friends .slide-image {
+ background-color: var(--paper-light-blue-100);
+ background-image:
+ url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_FRIENDS);
+ }
+
+ #complete .slide-image {
+ background-color: white;
+ background-image:
+ url(chrome://theme/IDR_ICON_USER_MANAGER_TUTORIAL_COMPLETE);
+ }
+
+ #notYou #dismiss {
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ }
+
+ #notYou #slide-add-user {
+ margin-top: 10px;
+ }
+
+ :host-context([dir='rtl']) #notYou #dismiss {
+ left: 5px;
+ right: auto;
+ }
+ </style>
<template is="dom-if" if="[[!hidden_]]">
<template is="dom-if"
if="[[!isStepHidden_(currentStep_, steps_.YOUR_CHROME)]]">
<div class="tutorial-slide" id="[[steps_.YOUR_CHROME]]">
<div class="slide-image"></div>
<div class="slide-contents">
- <div class="slide-title">[[i18n('slideYourChromeTitle')]]</div>
- <div class="slide-text">[[i18n('slideYourChromeText')]]</div>
+ <div class="slide-title">$i18n{slideYourChromeTitle}</div>
+ <div class="slide-text">$i18n{slideYourChromeText}</div>
</div>
<div class="slide-buttons">
<paper-button on-tap="onNextTap_" data-next$="[[steps_.GUESTS]]">
- [[i18n('tutorialNext')]]
+ $i18n{tutorialNext}
</paper-button>
</div>
</div>
@@ -31,12 +184,12 @@
<div class="tutorial-slide" id="[[steps_.GUESTS]]">
<div class="slide-image"></div>
<div class="slide-contents">
- <div class="slide-title">[[i18n('slideGuestsTitle')]]</div>
- <div class="slide-text">[[i18n('slideGuestsText')]]</div>
+ <div class="slide-title">$i18n{slideGuestsTitle}</div>
+ <div class="slide-text">$i18n{slideGuestsText}</div>
</div>
<div class="slide-buttons">
<paper-button on-tap="onNextTap_" data-next$="[[steps_.FRIENDS]]">
- [[i18n('tutorialNext')]]
+ $i18n{tutorialNext}
</paper-button>
</div>
<div class="arrow-down"></div>
@@ -47,12 +200,12 @@
<div class="tutorial-slide" id="[[steps_.FRIENDS]]">
<div class="slide-image"></div>
<div class="slide-contents">
- <div class="slide-title">[[i18n('slideFriendsTitle')]]</div>
- <div class="slide-text">[[i18n('slideFriendsText')]]</div>
+ <div class="slide-title">$i18n{slideFriendsTitle}</div>
+ <div class="slide-text">$i18n{slideFriendsText}</div>
</div>
<div class="slide-buttons">
<paper-button on-tap="onNextTap_" data-next$="[[steps_.COMPLETE]]">
- [[i18n('tutorialNext')]]
+ $i18n{tutorialNext}
</paper-button>
</div>
<div class="arrow-down"></div>
@@ -63,27 +216,28 @@
<div class="tutorial-slide" id="[[steps_.COMPLETE]]">
<div class="slide-image"></div>
<div class="slide-contents">
- <div class="slide-title">[[i18n('slideCompleteTitle')]]</div>
- <div class="slide-text">[[i18n('slideCompleteText')]]</div>
+ <div class="slide-title">$i18n{slideCompleteTitle}</div>
+ <div class="slide-text">$i18n{slideCompleteText}</div>
</div>
<div class="slide-buttons">
<paper-button on-tap="onNextTap_" data-next$="[[steps_.NOT_YOU]]">
- [[i18n('tutorialDone')]]
+ $i18n{tutorialDone}
</paper-button>
</div>
</div>
</template>
<template is="dom-if" if="[[!isStepHidden_(currentStep_, 'notYou')]]">
<div class="tutorial-slide" id="notYou">
- <iron-icon id="dismiss" icon="close" on-tap="onDissmissTap_">
+ <iron-icon id="dismiss" icon="cr:close"
+ on-tap="onDissmissTap_">
</iron-icon>
<div class="slide-buttons">
<div class="slide-text">
- [[i18n('slideCompleteUserNotFound')]]
+ $i18n{slideCompleteUserNotFound}
</div>
<div id="slide-add-user">
<a id="addUser" is="action-link" on-tap="onAddUserTap_">
- [[i18n('slideCompleteAddUser')]]
+ $i18n{slideCompleteAddUser}
</a>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.js b/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.js
index 10ca08a20a8..a9da577e1e3 100644
--- a/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.js
+++ b/chromium/chrome/browser/resources/md_user_manager/user_manager_tutorial.js
@@ -20,10 +20,6 @@ var TutorialSteps = {
Polymer({
is: 'user-manager-tutorial',
- behaviors: [
- I18nBehavior,
- ],
-
properties: {
/**
* True if the tutorial is currently hidden.
diff --git a/chromium/chrome/browser/resources/media_router/OWNERS b/chromium/chrome/browser/resources/media_router/OWNERS
index 583b6f8fa12..efc4671e71c 100644
--- a/chromium/chrome/browser/resources/media_router/OWNERS
+++ b/chromium/chrome/browser/resources/media_router/OWNERS
@@ -1,9 +1,6 @@
-# Owners with committer privileges
apacible@chromium.org
imcheng@chromium.org
-kmarshall@chromium.org
mfoltz@chromium.org
-wez@chromium.org
-# Team members without committer privileges, for potential FYI reviews.
-haibinlu@chromium.org
+# Fallback OWNER, if others are not available.
+wez@chromium.org
diff --git a/chromium/chrome/browser/resources/media_router/compiled_resources.gyp b/chromium/chrome/browser/resources/media_router/compiled_resources.gyp
deleted file mode 100644
index 614b3699428..00000000000
--- a/chromium/chrome/browser/resources/media_router/compiled_resources.gyp
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
- 'targets': [
- {
- 'target_name': 'media_router',
- 'variables': {
- 'depends': [
- '../../../../third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/iron-a11y-keys-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/iron-form-element-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-icon/iron-icon-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-menu-behavior/iron-menu-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-meta/iron-meta-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-selector/iron-multi-selectable-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-selector/iron-selectable-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-selector/iron-selection-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/iron-validatable-behavior/iron-validatable-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-button-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-inky-focus-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-dropdown-menu/paper-dropdown-menu-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-button/paper-button-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-icon-button/paper-icon-button-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-menu/paper-menu-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-behavior-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-extracted.js',
- '../../../../third_party/polymer/v1_0/components-chromium/paper-toolbar/paper-toolbar-extracted.js',
- '../../../../ui/webui/resources/js/cr.js',
- '../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
- '../../../../ui/webui/resources/js/promise_resolver.js',
- '../../../../ui/webui/resources/js/util.js',
- 'media_router.js',
- 'media_router_data.js',
- 'media_router_ui_interface.js',
- 'elements/issue_banner/issue_banner.js',
- 'elements/route_details/route_details.js',
- 'elements/media_router_header/media_router_header.js',
- 'elements/media_router_container/media_router_container.js',
- 'elements/media_router_search_highlighter/media_router_search_highlighter.js',
- ],
- 'externs': [
- '<(EXTERNS_DIR)/chrome_send.js',
- 'externs.js',
- ],
- },
- 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
- }
- ],
-}
-
diff --git a/chromium/chrome/browser/resources/media_router/compiled_resources2.gyp b/chromium/chrome/browser/resources/media_router/compiled_resources2.gyp
new file mode 100644
index 00000000000..b6af24babff
--- /dev/null
+++ b/chromium/chrome/browser/resources/media_router/compiled_resources2.gyp
@@ -0,0 +1,38 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'externs',
+ 'includes': ['../../../../third_party/closure_compiler/include_js.gypi'],
+ },
+ {
+ 'target_name': 'media_router',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ 'media_router_ui_interface',
+ 'elements/media_router_header/compiled_resources2.gyp:media_router_header',
+ 'elements/media_router_container/compiled_resources2.gyp:media_router_container',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'media_router_data',
+ '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'],
+ },
+ {
+ 'target_name': 'media_router_ui_interface',
+ 'dependencies': [
+ '<(EXTERNS_GYP):chrome_send',
+ 'elements/media_router_header/compiled_resources2.gyp:media_router_header',
+ 'elements/media_router_container/compiled_resources2.gyp:media_router_container',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/chrome/browser/resources/media_router/elements/issue_banner/compiled_resources2.gyp b/chromium/chrome/browser/resources/media_router/elements/issue_banner/compiled_resources2.gyp
new file mode 100644
index 00000000000..621a1d48a21
--- /dev/null
+++ b/chromium/chrome/browser/resources/media_router/elements/issue_banner/compiled_resources2.gyp
@@ -0,0 +1,15 @@
+# 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': 'issue_banner',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:media_router_data',
+ '<(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/media_router/elements/issue_banner/issue_banner.css b/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css
index b85d2bff5e5..4215fece3b6 100644
--- a/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css
+++ b/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.css
@@ -30,8 +30,8 @@
.non-blocking {
background-color: var(--paper-grey-800);
- overflow: hidden;
padding: 16px;
+ width: inherit;
}
.non-blocking > #buttons {
@@ -50,7 +50,10 @@
}
.non-blocking > div > #title {
+ -webkit-margin-end: 12px;
+ -webkit-padding-end: 12px;
color: rgba(255, 255, 255, 0.87);
+ overflow: hidden;
}
paper-button {
diff --git a/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html b/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html
index 193f1a74cdf..d1e859d1e23 100644
--- a/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html
+++ b/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.html
@@ -1,6 +1,7 @@
<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/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="../../icons/media_router_icons.html">
<dom-module name="issue-banner">
<link rel="import" type="css" href="../../media_router_common.css">
<link rel="import" type="css" href="issue_banner.css">
@@ -8,7 +9,7 @@
<div class$="[[computeIssueClass_(issue)]]">
<div>
<div hidden$="[[computeIsBlockingIssueHidden_(issue)]]">
- <iron-icon icon="error-outline" id="blocking-icon">
+ <iron-icon icon="media-router:error-outline" id="blocking-icon">
</iron-icon>
</div>
<div id="title">[[issue.title]]</div>
diff --git a/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js b/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js
index f897b0e41d1..4698589dc75 100644
--- a/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js
+++ b/chromium/chrome/browser/resources/media_router/elements/issue_banner/issue_banner.js
@@ -25,33 +25,34 @@ Polymer({
/**
* The text shown in the default action button.
- * @private {string}
+ * @private {string|undefined}
*/
defaultActionButtonText_: {
type: String,
- value: '',
},
/**
* The issue to show.
- * @type {?media_router.Issue}
+ * @type {?media_router.Issue|undefined}
*/
issue: {
type: Object,
- value: null,
observer: 'updateActionButtonText_',
},
/**
* The text shown in the secondary action button.
- * @private {string}
+ * @private {string|undefined}
*/
secondaryActionButtonText_: {
type: String,
- value: '',
},
},
+ behaviors: [
+ I18nBehavior,
+ ],
+
/**
* @param {?media_router.Issue} issue
* @return {boolean} Whether or not to hide the blocking issue UI.
@@ -79,7 +80,7 @@ Polymer({
* @private
*/
computeOptionalActionHidden_: function(issue) {
- return !issue || !issue.secondaryActionType;
+ return !issue || issue.secondaryActionType === undefined;
},
/**
@@ -127,14 +128,14 @@ Polymer({
var defaultText = '';
var secondaryText = '';
if (this.issue) {
- defaultText = loadTimeData.getString(
- this.actionTypeToButtonTextResource_[
- this.issue.defaultActionType]);
-
- if (this.issue.secondaryActionType) {
- secondaryText = loadTimeData.getString(
- this.actionTypeToButtonTextResource_[
- this.issue.secondaryActionType]);
+ defaultText =
+ this.i18n(this.actionTypeToButtonTextResource_[
+ this.issue.defaultActionType]);
+
+ if (this.issue.secondaryActionType !== undefined) {
+ secondaryText =
+ this.i18n(this.actionTypeToButtonTextResource_[
+ this.issue.secondaryActionType]);
}
}
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_container/compiled_resources2.gyp b/chromium/chrome/browser/resources/media_router/elements/media_router_container/compiled_resources2.gyp
new file mode 100644
index 00000000000..967e3bb4865
--- /dev/null
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_container/compiled_resources2.gyp
@@ -0,0 +1,27 @@
+# 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': 'media_router_container',
+ 'dependencies': [
+ 'pseudo_sink_search_state',
+ '../../compiled_resources2.gyp:externs',
+ '../../compiled_resources2.gyp:media_router_data',
+ '../../elements/issue_banner/compiled_resources2.gyp:issue_banner',
+ '../../elements/media_router_header/compiled_resources2.gyp:media_router_header',
+ '../../elements/media_router_search_highlighter/compiled_resources2.gyp:media_router_search_highlighter',
+ '../../elements/route_details/compiled_resources2.gyp:route_details',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'pseudo_sink_search_state',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:media_router_data',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css b/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
index 99ccd760ff7..3b85a194123 100644
--- a/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
@@ -24,12 +24,16 @@
width: 100%;
}
+#content {
+ position: relative;
+}
+
#device-missing {
align-items: center;
background-color: white;
display: flex;
justify-content: center;
- margin: 60px 0;
+ padding: 60px 0;
}
#device-missing a {
@@ -144,6 +148,20 @@ paper-menu {
flex-grow: 1;
}
+#search-results-container {
+ bottom: 0;
+ left: 0;
+ overflow-x: hidden;
+ /* overflow-y is set to auto when the results are actually displayed to allow
+ * scrolling. It is set to hidden by default so the scrollbar isn't displayed
+ * while animating.
+ */
+ overflow-y: hidden;
+ position: absolute;
+ right: 0;
+ top: 100%;
+}
+
#searching-devices-spinner {
height: 30px;
width: 30px;
@@ -175,8 +193,8 @@ paper-menu {
/* TODO(crbug/589697): Handle overflow of very long domain names. */
}
-#sink-list {
- padding-bottom: 0;
+#sink-list-view {
+ position: relative;
}
.sink-name {
@@ -185,8 +203,18 @@ paper-menu {
text-overflow: ellipsis;
}
-#sink-search.bottom {
+#sink-search {
+ padding-bottom: 0;
+ padding-top: 4px;
+ position: absolute;
+ top: 100%;
+ width: 100%;
+ z-index: 1;
+}
+
+:host([search-use-bottom-padding]) #sink-search {
padding-bottom: 16px;
+ padding-top: 0;
}
/* Separate icon class is a consequence of box-sizing: border-box set by
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html b/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
index 2e976cd52d6..18e6da3707f 100644
--- a/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
@@ -1,17 +1,11 @@
<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/iron-icons/av-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-icons/hardware-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.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-input/paper-input.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-spinner/paper-spinner.html">
-<link rel="import" href="../issue_banner/issue_banner.html">
<link rel="import" href="../media_router_header/media_router_header.html">
-<link rel="import" href="../media_router_search_highlighter/media_router_search_highlighter.html">
<link rel="import" href="../route_details/route_details.html">
<link rel="import" href="../../icons/media_router_icons.html">
<dom-module id="media-router-container">
@@ -22,12 +16,12 @@
<template is="dom-if"
if="[[computeShowFirstRunFlow_(showFirstRunFlow, currentView_)]]">
<div id="first-run-flow">
- <div id="first-run-title">[[firstRunFlowTitle_]]</div>
+ <div id="first-run-title">[[i18n('firstRunFlowTitle')]]</div>
<div id="first-run-text">
- <span>[[firstRunFlowText_]]</span>
+ <span>[[i18n('firstRunFlowText')]]</span>
<a href="[[firstRunFlowLearnMoreUrl]]" target="_blank">
<span class="first-run-learn-more">
- [[firstRunFlowLearnMore_]]
+ [[i18n('learnMoreText')]]
</span>
</a>
</div>
@@ -38,10 +32,10 @@
</paper-checkbox>
</div>
<div>
- <span>[[firstRunFlowCloudPrefText_]]</span>
+ <span>[[getFirstRunFlowCloudPrefText_()]]</span>
<a href="[[firstRunFlowCloudPrefLearnMoreUrl]]" target="_blank">
<span class="first-run-learn-more">
- [[firstRunFlowLearnMore_]]
+ [[i18n('learnMoreText')]]
</span>
</a>
</div>
@@ -49,7 +43,7 @@
<div id="first-run-button-container">
<paper-button id="first-run-button" class="button"
on-tap="acknowledgeFirstRunFlow_">
- <span>[[firstRunFlowButtonText_]]</span>
+ <span>[[i18n('firstRunFlowButtonText')]]</span>
</paper-button>
</div>
</div>
@@ -75,7 +69,7 @@
</template>
<div id="share-screen-text"
hidden$="[[computeShareScreenSubheadingHidden_(castModeList)]]">
- <span>[[shareYourScreenSubheadingText_]]</span>
+ <span>[[i18n('shareYourScreenSubheadingText')]]</span>
</div>
<template is="dom-repeat" id="nonDefaultCastModeList"
items="[[computeNonDefaultCastModeList_(castModeList)]]">
@@ -90,9 +84,13 @@
</template>
<template is="dom-if"
if="[[!computeRouteDetailsHidden_(currentView_, issue)]]">
- <route-details id="route-details" is-off-the-record="[[isOffTheRecord]]"
- route="[[currentRoute_]]"
- on-close-route-click="onCloseRouteClick_">
+ <route-details id="route-details" route="[[currentRoute_]]"
+ shown-cast-mode-value="[[shownCastModeValue_]]"
+ sink="[[getSinkForRoute_(currentRoute_)]]"
+ is-any-sink-currently-launching=
+ "[[computeIsLaunching_(currentLaunchingSinkId_)]]"
+ on-close-route="onCloseRoute_"
+ on-replace-route-click="onReplaceRouteClick_">
</route-details>
</template>
<div id="sink-list-view"
@@ -104,103 +102,42 @@
</paper-spinner>
<a href="[[deviceMissingUrl]]" target="_blank"
hidden$="[[!computeSpinnerHidden_(justOpened_)]]">
- [[deviceMissingText_]]
+ [[i18n('deviceMissingText')]]
</a>
</div>
- <paper-menu id="sink-list" role="presentation"
- hidden$="[[computeSinkListHidden_(sinksToShow_, isUserSearching_)]]">
- <template is="dom-repeat" id="sinkList" items="[[sinksToShow_]]">
- <paper-item on-tap="onSinkClick_">
- <div class="sink-content">
- <div>
- <iron-icon icon="[[computeSinkIcon_(item)]]"
- hidden$="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.id)]]"
- class$="[[computeSinkIconClass_(item.id, sinkToRouteMap_)]]">
- </iron-icon>
- <template is="dom-if"
- if="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.id)]]">
- <paper-spinner class="sink-icon" active>
- </paper-spinner>
- </template>
- </div>
- <div>
- <div class="sink-text">
- <span dir="auto" class="sink-name" title="[[item.name]]">
- [[item.name]]
- </span>
- <template is="dom-if"
- if="[[!computeSinkDomainHidden_(item)]]">
- <span class="sink-domain" title="[[item.domain]]">
- [[item.domain]]
- </span>
- </template>
- </div>
- <template is="dom-if"
- if="[[!computeSinkSubtextHidden_(item, sinkToRouteMap_)]]">
- <div class="sink-text sink-subtext">
- <span>[[computeSinkSubtext_(item, sinkToRouteMap_)]]</span>
- </div>
- </template>
- </div>
- </div>
- </paper-item>
- </template>
- </paper-menu>
- <div id="sink-search" class$="[[computeSinkSearchClass_(currentView_)]]">
- <div class="sink-content">
- <div>
- <paper-icon-button id="sink-search-icon" icon="search"
- on-tap="searchButtonClick_" title="[[searchButtonTitle_]]">
- </paper-icon-button>
- </div>
- <div id="search-input-container">
- <paper-input id="sink-search-input" label="[[searchInputLabel_]]"
- no-label-float value="{{searchInputText_}}">
- </paper-input>
- </div>
- </div>
- </div>
- <template is="dom-if" if="[[isUserSearching_]]">
- <div id="no-search-matches"
- hidden$="[[computeNoMatchesHidden_(searchResultsToShow_, isUserSearching_)]]">
- <span>[[searchNoMatchesText_]]</span>
- </div>
- <paper-menu id="search-results" selected="0" role="presentation"
- hidden$="[[computeSearchResultsHidden_(isUserSearching_, searchResultsToShow_)]]">
- <template is="dom-repeat" id="searchResults"
- items="[[searchResultsToShow_]]">
- <paper-item class="search-item" on-tap="onSinkClick_">
+ <template is="dom-if" if="[[!computeSinkListHidden_(sinksToShow_)]]">
+ <paper-menu id="sink-list" role="presentation"
+ hidden$="[[hideSinkListForAnimation_]]">
+ <template is="dom-repeat" id="sinkList" items="[[sinksToShow_]]">
+ <paper-item on-tap="onSinkClick_">
<div class="sink-content">
<div>
- <iron-icon icon="[[computeSinkIcon_(item.sinkItem)]]"
- hidden$="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.sinkItem.id)]]"
- class$="[[computeSinkIconClass_(item.sinkItem.id, sinkToRouteMap_)]]">
+ <iron-icon icon="[[computeSinkIcon_(item)]]"
+ hidden$="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.id)]]"
+ class$="[[computeSinkIconClass_(item.id, sinkToRouteMap_)]]">
</iron-icon>
<template is="dom-if"
- if="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.sinkItem.id)]]">
+ if="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.id)]]">
<paper-spinner class="sink-icon" active>
</paper-spinner>
</template>
</div>
<div>
<div class="sink-text">
- <media-router-search-highlighter class="sink-name"
- data="[[computeSinkMatchingText_(item)]]"
- title="[[item.sinkItem.name]]">
- </media-router-search-highlighter>
+ <span dir="auto" class="sink-name" title="[[item.name]]">
+ [[item.name]]
+ </span>
<template is="dom-if"
- if="[[!computeSinkDomainHidden_(item.sinkItem)]]">
- <span class="sink-domain" title="[[item.sinkItem.domain]]">
- [[item.sinkItem.domain]]
+ if="[[!computeSinkDomainHidden_(item)]]">
+ <span class="sink-domain" title="[[item.domain]]">
+ [[item.domain]]
</span>
</template>
</div>
<template is="dom-if"
- if="[[!computeSinkSubtextHidden_(item.sinkItem, sinkToRouteMap_)]]">
+ if="[[!computeSinkSubtextHidden_(item, sinkToRouteMap_)]]">
<div class="sink-text sink-subtext">
- <span>
- [[computeSinkSubtext_(item.sinkItem, sinkToRouteMap_)]]
- </span>
+ <span>[[computeSinkSubtext_(item, sinkToRouteMap_)]]</span>
</div>
</template>
</div>
@@ -209,15 +146,82 @@
</template>
</paper-menu>
</template>
+ <template is="dom-if" if="[[searchEnabled_]]">
+ <div id="sink-search">
+ <div class="sink-content">
+ <div>
+ <paper-icon-button id="sink-search-icon" icon="media-router:search"
+ on-tap="searchButtonClick_" title="[[i18n('searchButtonTitle')]]">
+ </paper-icon-button>
+ </div>
+ <div id="search-input-container">
+ <paper-input id="sink-search-input" label="[[i18n('searchInputLabel')]]"
+ no-label-float value="{{searchInputText_}}">
+ </paper-input>
+ </div>
+ </div>
+ </div>
+ </template>
+ <template is="dom-if" if="[[!isSearchListHidden_]]">
+ <div id="search-results-container">
+ <div id="no-search-matches"
+ hidden$="[[computeNoMatchesHidden_(searchResultsToShow_, isSearchListHidden_)]]">
+ <span>[[i18n('searchNoMatchesText')]]</span>
+ </div>
+ <paper-menu id="search-results" selected="0"
+ hidden$="[[computeSearchResultsHidden_(searchResultsToShow_, isSearchListHidden_)]]">
+ <template is="dom-repeat" id="searchResults"
+ items="[[searchResultsToShow_]]">
+ <paper-item class="search-item" on-tap="onSinkClick_">
+ <div class="sink-content">
+ <div>
+ <iron-icon icon="[[computeSinkIcon_(item.sinkItem)]]"
+ hidden$="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.sinkItem.id)]]"
+ class$="[[computeSinkIconClass_(item.sinkItem.id, sinkToRouteMap_)]]">
+ </iron-icon>
+ <template is="dom-if"
+ if="[[computeSinkIsLaunching_(currentLaunchingSinkId_, item.sinkItem.id)]]">
+ <paper-spinner class="sink-icon" active>
+ </paper-spinner>
+ </template>
+ </div>
+ <div>
+ <div class="sink-text">
+ <media-router-search-highlighter class="sink-name"
+ data="[[computeSinkMatchingText_(item)]]"
+ title="[[item.sinkItem.name]]">
+ </media-router-search-highlighter>
+ <template is="dom-if"
+ if="[[!computeSinkDomainHidden_(item.sinkItem)]]">
+ <span class="sink-domain" title="[[item.sinkItem.domain]]">
+ [[item.sinkItem.domain]]
+ </span>
+ </template>
+ </div>
+ <template is="dom-if"
+ if="[[!computeSinkSubtextHidden_(item.sinkItem, sinkToRouteMap_)]]">
+ <div class="sink-text sink-subtext">
+ <span>
+ [[computeSinkSubtext_(item.sinkItem, sinkToRouteMap_)]]
+ </span>
+ </div>
+ </template>
+ </div>
+ </div>
+ </paper-item>
+ </template>
+ </paper-menu>
+ </div>
+ </template>
</div>
<template is="dom-if"
if="[[computeIssueBannerShown_(currentView_, issue)]]">
<issue-banner id="issue-banner" issue="[[issue]]"
- class$="[[computeIssueBannerClass_(issue)]]"
- on-issue-action-tap="showSinkList_">
+ class$="[[computeIssueBannerClass_(issue)]]">
</issue-banner>
</template>
</div>
</template>
+ <script src="pseudo_sink_search_state.js"></script>
<script src="media_router_container.js"></script>
</dom-module>
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 7aa9e20b2a8..8958dbeaaab 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
@@ -19,18 +19,31 @@ Polymer({
},
/**
+ * The last promise in a chain that will be fulfilled when the current
+ * animation has finished. It does not return a value; it is strictly a
+ * synchronization mechanism.
+ * @private {!Promise}
+ */
+ animationPromise_: {
+ type: Object,
+ value: function() {
+ return Promise.resolve();
+ },
+ },
+
+ /**
* The list of CastModes to show.
- * @type {!Array<!media_router.CastMode>}
+ * @type {!Array<!media_router.CastMode>|undefined}
*/
castModeList: {
type: Array,
- value: [],
observer: 'checkCurrentCastMode_',
},
/**
* The ID of the Sink currently being launched.
* @private {string}
+ * TODO(crbug.com/616604): Use per-sink route creation state.
*/
currentLaunchingSinkId_: {
type: String,
@@ -39,42 +52,27 @@ Polymer({
/**
* The current route.
- * @private {?media_router.Route}
+ * @private {?media_router.Route|undefined}
*/
currentRoute_: {
type: Object,
- value: null,
},
/**
* The current view to be shown.
- * @private {?media_router.MediaRouterView}
+ * @private {?media_router.MediaRouterView|undefined}
*/
currentView_: {
type: String,
- value: null,
observer: 'currentViewChanged_',
},
/**
- * The text for when there are no devices.
- * @private {string}
- */
- deviceMissingText_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('deviceMissing');
- },
- },
-
- /**
* The URL to open when the device missing link is clicked.
- * @type {string}
+ * @type {string|undefined}
*/
deviceMissingUrl: {
type: String,
- value: '',
},
/**
@@ -88,132 +86,75 @@ Polymer({
/**
* The time |this| element calls ready().
- * @private {number}
+ * @private {number|undefined}
*/
elementReadyTimeMs_: {
type: Number,
- value: 0,
},
/**
- * The text for the first run flow button.
- * @private {string}
+ * Animation player used for running filter transition animations.
+ * @private {?Animation}
*/
- firstRunFlowButtonText_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('firstRunFlowButton');
- },
- },
-
- /**
- * The text for the learn more link about cloud services in the first run
- * flow.
- * @private {string}
- */
- firstRunFlowLearnMore_: {
- type: String,
- readOnly: true,
- value: loadTimeData.getString('learnMoreText'),
+ filterTransitionPlayer_: {
+ type: Object,
+ value: null,
},
/**
* The URL to open when the cloud services pref learn more link is clicked.
- * @type {string}
+ * @type {string|undefined}
*/
firstRunFlowCloudPrefLearnMoreUrl: {
type: String,
- value: '',
- },
-
- /**
- * The text for the cloud services preference description in the first run
- * flow.
- * @private {string}
- */
- firstRunFlowCloudPrefText_: {
- type: String,
- readOnly: true,
- value: loadTimeData.valueExists('firstRunFlowCloudPrefText') ?
- loadTimeData.getString('firstRunFlowCloudPrefText') : '',
},
/**
* The URL to open when the first run flow learn more link is clicked.
- * @type {string}
+ * @type {string|undefined}
*/
firstRunFlowLearnMoreUrl: {
type: String,
- value: '',
- },
-
- /**
- * The text description for the first run flow.
- * @private {string}
- */
- firstRunFlowText_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('firstRunFlowText');
- },
- },
-
- /**
- * The header of the first run flow.
- * @private {string}
- */
- firstRunFlowTitle_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('firstRunFlowTitle');
- },
},
/**
* The header text for the sink list.
- * @type {string}
+ * @type {string|undefined}
*/
headerText: {
type: String,
- value: '',
},
/**
* The header text tooltip. This would be descriptive of the
* source origin, whether a host name, tab URL, etc.
- * @type {string}
+ * @type {string|undefined}
*/
headerTextTooltip: {
type: String,
- value: '',
},
/**
- * Whether the browser is currently incognito.
- * @type {boolean}
+ * An animation player that is used for running dialog height adjustments.
+ * @private {?Animation}
*/
- isOffTheRecord: {
- type: Boolean,
- value: false,
+ heightAdjustmentPlayer_: {
+ type: Object,
+ value: null,
},
/**
- * Whether the search input is currently focused. This is used to prevent
- * window focus/blur events from interfering with input-focus-dependent
- * operations.
+ * Whether the sink list is being hidden for animation purposes.
* @private {boolean}
*/
- isSearchFocused_: {
+ hideSinkListForAnimation_: {
type: Boolean,
value: false,
},
/**
- * Records the value of |isSearchFocused_| when a window blur event is
- * received. This used to handle search focus edge cases. See
+ * Records whether the search input is focused when a window blur event is
+ * received. This is used to handle search focus edge cases. See
* |setSearchFocusHandlers_| for details.
* @private {boolean}
*/
@@ -223,25 +164,12 @@ Polymer({
},
/**
- * Temporarily set when the window focus event handler needs to reset
- * |isSearchFocused_| to the correct value but needs to know whether the
- * search input focus handler will run. See |setSearchFocusHandlers_| for
- * details.
- * @private {boolean}
- */
- isSearchFocusedShouldBeSet_: {
- type: Boolean,
- value: false,
- },
-
- /**
- * Whether the user is currently searching for a sink.
+ * Whether the search list is currently hidden.
* @private {boolean}
*/
- isUserSearching_: {
+ isSearchListHidden_: {
type: Boolean,
- value: false,
- observer: 'isUserSearchingChanged_',
+ value: true,
},
/**
@@ -255,44 +183,41 @@ Polymer({
},
/**
- * The header text.
- * @private {string}
+ * Whether the MR UI was just opened.
+ * @private {boolean}
*/
- issueHeaderText_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('issueHeader');
- },
+ justOpened_: {
+ type: Boolean,
+ value: true,
},
/**
- * Whether the MR UI was just opened.
+ * Whether the sink with a pending route creation, whose ID is given by
+ * |currentLaunchingSinkId_|, is waiting for the current route to it to be
+ * closed so a new one can be started.
* @private {boolean}
*/
- justOpened_: {
+ launchingSinkAwaitingRouteClose_: {
type: Boolean,
- value: true,
+ value: false,
},
/**
* Whether the user's mouse is positioned over the dialog.
- * @private {boolean}
+ * @private {boolean|undefined}
*/
mouseIsPositionedOverDialog_: {
type: Boolean,
- value: false,
},
/**
* The ID of the route that is currently being created. This is set when
* route creation is resolved but not ready for its controls to be
* displayed.
- * @private {string}
+ * @private {string|undefined}
*/
pendingCreatedRouteId_: {
type: String,
- value: '',
},
/**
@@ -307,6 +232,24 @@ Polymer({
},
/**
+ * Pseudo sinks from MRPs that represent their ability to accept sink search
+ * requests.
+ * @private {!Array<!media_router.Sink>}
+ */
+ pseudoSinks_: {
+ type: Array,
+ value: [],
+ },
+
+ /**
+ * Helps manage the state of creating a sink and a route from a pseudo sink.
+ * @private {PseudoSinkSearchState|undefined}
+ */
+ pseudoSinkSearchState_: {
+ type: Object,
+ },
+
+ /**
* Whether the next character input should cause a filter action metric to
* be sent.
* @type {boolean}
@@ -319,45 +262,30 @@ Polymer({
/**
* The list of current routes.
- * @type {!Array<!media_router.Route>}
+ * @type {!Array<!media_router.Route>|undefined}
*/
routeList: {
type: Array,
- value: [],
observer: 'rebuildRouteMaps_',
},
/**
* Maps media_router.Route.id to corresponding media_router.Route.
- * @private {!Object<!string, !media_router.Route>}
+ * @private {!Object<!string, !media_router.Route>|undefined}
*/
routeMap_: {
type: Object,
- value: {},
- },
-
- /**
- * Title text for the search button.
- * @private {string}
- */
- searchButtonTitle_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('searchButtonTitle');
- },
},
/**
- * Label text for the user search input.
- * @private {string}
+ * Whether the search feature is enabled and we should show the search
+ * input.
+ * @private {boolean}
*/
- searchInputLabel_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('searchInputLabel');
- },
+ searchEnabled_: {
+ type: Boolean,
+ value: false,
+ observer: 'searchEnabledChanged_',
},
/**
@@ -371,76 +299,48 @@ Polymer({
},
/**
- * Text to display when a user search returns no matches.
- * @private {string}
- */
- searchNoMatchesText_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('searchNoMatches');
- },
- },
-
- /**
* Sinks to display that match |searchInputText_|.
- * @private {!Array<!media_router.Sink>}
+ * @private {!Array<!{sinkItem: !media_router.Sink,
+ * substrings: Array<!Array<number>>}>|undefined}
*/
searchResultsToShow_: {
type: Array,
- value: [],
- },
-
- /**
- * The header text when the cast mode list is shown.
- * @private {string}
- */
- selectCastModeHeaderText_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('selectCastModeHeader');
- },
},
/**
- * The subheading text for the non-cast-enabled app cast mode list.
- * @private {string}
+ * Whether the search input should be padded as if it were at the bottom of
+ * the dialog.
+ * @type {boolean}
*/
- shareYourScreenSubheadingText_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('shareYourScreenSubheading');
- },
+ searchUseBottomPadding: {
+ type: Boolean,
+ reflectToAttribute: true,
+ value: true,
},
/**
* Whether to show the user domain of sinks associated with identity.
- * @type {boolean}
+ * @type {boolean|undefined}
*/
showDomain: {
type: Boolean,
- value: false,
},
/**
* Whether to show the first run flow.
- * @type {boolean}
+ * @type {boolean|undefined}
*/
showFirstRunFlow: {
type: Boolean,
- value: false,
observer: 'updateElementPositioning_',
},
/**
* Whether to show the cloud preference setting in the first run flow.
- * @type {boolean}
+ * @type {boolean|undefined}
*/
showFirstRunFlowCloudPref: {
type: Boolean,
- value: false,
},
/**
@@ -463,12 +363,20 @@ Polymer({
},
/**
+ * Max height for the sink list.
+ * @private {number}
+ */
+ sinkListMaxHeight_: {
+ type: Number,
+ value: 0,
+ },
+
+ /**
* Maps media_router.Sink.id to corresponding media_router.Sink.
- * @private {!Object<!string, !media_router.Sink>}
+ * @private {!Object<!string, !media_router.Sink>|undefined}
*/
sinkMap_: {
type: Object,
- value: {},
},
/**
@@ -482,11 +390,11 @@ Polymer({
/**
* Sinks to show for the currently selected cast mode.
- * @private {!Array<!media_router.Sink>}
+ * @private {!Array<!media_router.Sink>|undefined}
*/
sinksToShow_: {
type: Array,
- value: [],
+ observer: 'updateElementPositioning_',
},
/**
@@ -508,13 +416,9 @@ Polymer({
},
},
- listeners: {
- 'focus': 'onFocus_',
- 'header-height-changed': 'updateElementPositioning_',
- 'header-or-arrow-click': 'toggleCastModeHidden_',
- 'mouseleave': 'onMouseLeave_',
- 'mouseenter': 'onMouseEnter_',
- },
+ behaviors: [
+ I18nBehavior,
+ ],
observers: [
'maybeUpdateStartSinkDisplayStartTime_(currentView_, sinksToShow_)',
@@ -522,29 +426,63 @@ Polymer({
ready: function() {
this.elementReadyTimeMs_ = performance.now();
-
- // If this is not on a Mac platform, remove the placeholder. See
- // onFocus_() for more details. ready() is only called once, so no need
- // to check if the placeholder exist before removing.
- if (!cr.isMac)
- this.$$('#focus-placeholder').remove();
-
- document.addEventListener('keydown', this.onKeydown_.bind(this));
- this.setSearchFocusHandlers_();
this.showSinkList_();
- },
-
- attached: function() {
- this.updateElementPositioning_();
- // Turn off the spinner after 3 seconds, then report the current number of
- // sinks.
- this.async(function() {
- this.justOpened_ = false;
- this.fire('report-sink-count', {
- sinkCount: this.allSinks.length,
- });
- }, 3000 /* 3 seconds */);
+ Polymer.RenderStatus.afterNextRender(this, function() {
+ // Import the elements that aren't needed at startup. This reduces
+ // initial load time. Delayed loading interferes with getting the
+ // offsetHeight of the first-run-flow element in updateElementPositioning_
+ // though, so we also make sure it is called after the last load.
+ var that = this;
+ var loadsRemaining = 3;
+ var onload = function() {
+ loadsRemaining--;
+ if (loadsRemaining > 0) {
+ return;
+ }
+ that.updateElementPositioning_();
+ if (that.currentView_ == media_router.MediaRouterView.SINK_LIST) {
+ that.putSearchAtBottom_();
+ }
+ };
+ this.importHref('chrome://resources/polymer/v1_0/neon-animation/' +
+ 'web-animations.html', onload);
+ this.importHref(this.resolveUrl(
+ '../issue_banner/issue_banner.html'), onload);
+ this.importHref(this.resolveUrl(
+ '../media_router_search_highlighter/' +
+ 'media_router_search_highlighter.html'), onload);
+
+ // If this is not on a Mac platform, remove the placeholder. See
+ // onFocus_() for more details. ready() is only called once, so no need
+ // to check if the placeholder exist before removing.
+ if (!cr.isMac)
+ this.$$('#focus-placeholder').remove();
+
+ document.addEventListener('keydown', this.onKeydown_.bind(this), true);
+ this.listen(this, 'focus', 'onFocus_');
+ this.listen(this, 'header-height-changed', 'updateElementPositioning_');
+ this.listen(this, 'header-or-arrow-click', 'toggleCastModeHidden_');
+ this.listen(this, 'mouseleave', 'onMouseLeave_');
+ this.listen(this, 'mouseenter', 'onMouseEnter_');
+
+ // Turn off the spinner after 3 seconds, then report the current number of
+ // sinks.
+ this.async(function() {
+ this.justOpened_ = false;
+ this.fire('report-sink-count', {
+ sinkCount: this.allSinks.length,
+ });
+ }, 3000 /* 3 seconds */);
+
+ // For Mac platforms, request data after a short delay after load. This
+ // appears to speed up initial data load time on Mac.
+ if (cr.isMac) {
+ this.async(function() {
+ this.fire('request-initial-data');
+ }, 25 /* 0.025 seconds */);
+ }
+ });
},
/**
@@ -668,6 +606,18 @@ Polymer({
},
/**
+ * Returns a duration in ms from a distance in pixels using a default speed of
+ * 1000 pixels per second.
+ * @param {number} distance Number of pixels that will be traveled.
+ * @private
+ */
+ computeAnimationDuration_: function(distance) {
+ // The duration of the animation can be found by abs(distance)/speed, where
+ // speed is fixed at 1000 pixels per second, or 1 pixel per millisecond.
+ return Math.abs(distance);
+ },
+
+ /**
* If |allSinks| supports only a single cast mode, returns that cast mode.
* Otherwise, returns AUTO_MODE. Only called if |userHasSelectedCastMode_| is
* |false|.
@@ -703,20 +653,17 @@ Polymer({
/**
* @param {!media_router.CastMode} castMode The cast mode to determine an
* icon for.
- * @return {string} The Polymer <iron-icon> icon to use. The format is
- * <iconset>:<icon>, where <iconset> is the set ID and <icon> is the name
- * of the icon. <iconset>: may be omitted if <icon> is from the default
- * set.
+ * @return {string} The icon to use.
* @private
*/
computeCastModeIcon_: function(castMode) {
switch (castMode.type) {
case media_router.CastModeType.DEFAULT:
- return 'av:web';
+ return 'media-router:web';
case media_router.CastModeType.TAB_MIRROR:
- return 'tab';
+ return 'media-router:tab';
case media_router.CastModeType.DESKTOP_MIRROR:
- return 'hardware:laptop';
+ return 'media-router:laptop';
default:
return '';
}
@@ -744,6 +691,18 @@ Polymer({
},
/**
+ * @param {?Element} element Element to compute padding for.
+ * @return {number} Computes the amount of vertical padding (top + bottom) on
+ * |element|.
+ * @private
+ */
+ computeElementVerticalPadding_: function(element) {
+ var paddingBottom, paddingTop;
+ [paddingBottom, paddingTop] = this.getElementVerticalPadding_(element);
+ return paddingBottom + paddingTop;
+ },
+
+ /**
* @param {?media_router.MediaRouterView} view The current view.
* @param {?media_router.Issue} issue The current issue.
* @return {boolean} Whether or not to hide the header.
@@ -758,17 +717,17 @@ Polymer({
/**
* @param {?media_router.MediaRouterView} view The current view.
* @param {string} headerText The header text for the sink list.
- * @return {string} The text for the header.
+ * @return {string|undefined} The text for the header.
* @private
*/
computeHeaderText_: function(view, headerText) {
switch (view) {
case media_router.MediaRouterView.CAST_MODE_LIST:
- return this.selectCastModeHeaderText_;
+ return this.i18n('selectCastModeHeaderText');
case media_router.MediaRouterView.ISSUE:
- return this.issueHeaderText_;
+ return this.i18n('issueHeaderText');
case media_router.MediaRouterView.ROUTE_DETAILS:
- return this.currentRoute_ ?
+ return this.currentRoute_ && this.sinkMap_[this.currentRoute_.sinkId] ?
this.sinkMap_[this.currentRoute_.sinkId].name : '';
case media_router.MediaRouterView.SINK_LIST:
case media_router.MediaRouterView.FILTER:
@@ -815,18 +774,20 @@ Polymer({
*/
computeIssueBannerShown_: function(view, issue) {
return !!issue && (view == media_router.MediaRouterView.SINK_LIST ||
+ view == media_router.MediaRouterView.FILTER ||
view == media_router.MediaRouterView.ISSUE);
},
/**
- * @param {!Array<!media_router.Sink>} searchResultsToShow The sinks currently
- * matching the search text.
- * @param {boolean} isUserSearching Whether the user is searching for sinks.
+ * @param {!Array<!{sinkItem: !media_router.Sink,
+ * substrings: Array<!Array<number>>}>} searchResultsToShow
+ * The sinks currently matching the search text.
+ * @param {boolean} isSearchListHidden Whether the search list is hidden.
* @return {boolean} Whether or not the 'no matches' message is hidden.
* @private
*/
- computeNoMatchesHidden_: function(searchResultsToShow, isUserSearching) {
- return !isUserSearching || this.searchInputText_.length == 0 ||
+ computeNoMatchesHidden_: function(searchResultsToShow, isSearchListHidden) {
+ return isSearchListHidden || this.searchInputText_.length == 0 ||
searchResultsToShow.length != 0;
},
@@ -892,13 +853,16 @@ Polymer({
/**
* Computes whether the search results list should be hidden.
- * @param {boolean} isUserSearching Whether the user is searching for sinks.
- * @param {!Array<!media_router.Sink>} searchResultsToShow The sinks currently
+ * @param {!Array<!{sinkItem: !media_router.Sink,
+ * substrings: Array<!Array<number>>}>} searchResultsToShow
+ * The sinks currently matching the search text.
+ * @param {boolean} isSearchListHidden Whether the search list is hidden.
* @return {boolean} Whether the search results list should be hidden.
* @private
*/
- computeSearchResultsHidden_: function(isUserSearching, searchResultsToShow) {
- return !isUserSearching || searchResultsToShow.length == 0;
+ computeSearchResultsHidden_: function(searchResultsToShow,
+ isSearchListHidden) {
+ return isSearchListHidden || searchResultsToShow.length == 0;
},
/**
@@ -924,10 +888,7 @@ Polymer({
/**
* @param {!media_router.Sink} sink The sink to determine an icon for.
- * @return {string} The Polymer <iron-icon> icon to use. The format is
- * <iconset>:<icon>, where <iconset> is the set ID and <icon> is the name
- * of the icon. <iconset>: may be ommitted if <icon> is from the default
- * set.
+ * @return {string} The icon to use.
* @private
*/
computeSinkIcon_: function(sink) {
@@ -935,15 +896,15 @@ Polymer({
case media_router.SinkIconType.CAST:
return 'media-router:chromecast';
case media_router.SinkIconType.CAST_AUDIO:
- return 'hardware:speaker';
+ return 'media-router:speaker';
case media_router.SinkIconType.CAST_AUDIO_GROUP:
- return 'hardware:speaker-group';
+ return 'media-router:speaker-group';
case media_router.SinkIconType.GENERIC:
- return 'hardware:tv';
+ return 'media-router:tv';
case media_router.SinkIconType.HANGOUT:
return 'media-router:hangout';
default:
- return 'hardware:tv';
+ return 'media-router:tv';
}
},
@@ -971,12 +932,11 @@ Polymer({
/**
* @param {!Array<!media_router.Sink>} sinksToShow The list of sinks.
- * @param {boolean} isUserSearching Whether the user is searching for sinks.
* @return {boolean} Whether or not to hide the sink list.
* @private
*/
- computeSinkListHidden_: function(sinksToShow, isUserSearching) {
- return sinksToShow.length == 0 || isUserSearching;
+ computeSinkListHidden_: function(sinksToShow) {
+ return sinksToShow.length == 0;
},
/**
@@ -1047,19 +1007,6 @@ Polymer({
},
/**
- * Computes the CSS class for #sink-search depending on whether it is the
- * first or last item in the list, as indicated by |currentView|.
- * @param {?media_router.MediaRouterView} currentView The current view of the
- * dialog.
- * @return {string} The CSS that correctly sets the padding of #sink-search
- * for the current view.
- * @private
- */
- computeSinkSearchClass_: function(currentView) {
- return (currentView == media_router.MediaRouterView.FILTER) ? '' : 'bottom';
- },
-
- /**
* Returns the subtext to be shown for |sink|. Only called if
* |computeSinkSubtextHidden_| returns false for the same |sink| and
* |sinkToRouteMap|.
@@ -1101,6 +1048,27 @@ Polymer({
},
/**
+ * Computes the height of the sink list view element when search results are
+ * being shown.
+ *
+ * @param {?Element} deviceMissing No devices message element.
+ * @param {?Element} noMatches No search matches element.
+ * @param {?Element} results Search results list element.
+ * @param {number} searchOffsetHeight Search input container element height.
+ * @param {number} maxHeight Max height of the list elements.
+ * @return {number} The height of the sink list view when search results are
+ * being shown.
+ * @private
+ */
+ computeTotalSearchHeight_: function(
+ deviceMissing, noMatches, results, searchOffsetHeight, maxHeight) {
+ var contentHeight = deviceMissing.offsetHeight +
+ ((noMatches.hasAttribute('hidden')) ?
+ results.offsetHeight : noMatches.offsetHeight);
+ return Math.min(contentHeight, maxHeight) + searchOffsetHeight;
+ },
+
+ /**
* Updates element positioning when the view changes and possibly triggers
* reporting of a user filter action. If there is no filter text, it defers
* the reporting until some text is entered, but otherwise it reports the
@@ -1130,7 +1098,6 @@ Polymer({
});
return;
}
- this.isUserSearching_ = true;
var searchResultsToShow = [];
for (var i = 0; i < this.sinksToShow_.length; ++i) {
@@ -1144,6 +1111,31 @@ Polymer({
substrings: matchSubstrings});
}
searchResultsToShow.sort(this.compareSearchMatches_);
+
+ var pendingPseudoSink = (this.pseudoSinkSearchState_) ?
+ this.pseudoSinkSearchState_.getPseudoSink() :
+ null;
+ // We may need to add pseudo sinks to the filter results. A pseudo sink will
+ // be shown if there is no real sink with the same icon and name exactly
+ // matching the filter text. The map() call transforms any pseudo sink
+ // objects that will be shown to the search result format, where we know
+ // that the entire sink name will be a match.
+ //
+ // The exception to this is when there is a pending pseudo sink search. Then
+ // the pseudo sink for the search will be treated like a real sink because
+ // it will actually be in |sinksToShow_| until a real sink is returned by
+ // search. So the filter here shouldn't treat it like a pseudo sink.
+ searchResultsToShow = this.pseudoSinks_.filter(function(pseudoSink) {
+ return (!pendingPseudoSink || pseudoSink.id != pendingPseudoSink.id) &&
+ !searchResultsToShow.find(function(searchResult) {
+ return searchResult.sinkItem.name == searchInputText &&
+ searchResult.sinkItem.iconType == pseudoSink.iconType;
+ });
+ }).map(function(pseudoSink) {
+ pseudoSink.name = searchInputText;
+ return {sinkItem: pseudoSink,
+ substrings: [[0, searchInputText.length - 1]]};
+ }).concat(searchResultsToShow);
this.searchResultsToShow_ = searchResultsToShow;
},
@@ -1162,6 +1154,49 @@ Polymer({
},
/**
+ * @param {?Element} element Element to compute padding for.
+ * @return {!Array<number>} Array containing the element's bottom padding
+ * value and the element's top padding value, in that order.
+ * @private
+ */
+ getElementVerticalPadding_: function(element) {
+ var style = window.getComputedStyle(element);
+ return [parseInt(style.getPropertyValue('padding-bottom'), 10) || 0,
+ parseInt(style.getPropertyValue('padding-top'), 10) || 0];
+ },
+
+ /**
+ * Retrieves the first run flow cloud preferences text, if it exists. On
+ * non-officially branded builds, the string is not defined.
+ *
+ * @return {string} Cloud preferences text.
+ */
+ getFirstRunFlowCloudPrefText_: function() {
+ return loadTimeData.valueExists('firstRunFlowCloudPrefText') ?
+ this.i18n('firstRunFlowCloudPrefText') : '';
+ },
+
+ /**
+ * @param {?media_router.Route} route Route to get the sink for.
+ * @return {?media_router.Sink} Sink associated with |route| or
+ * undefined if we don't have data for the sink.
+ */
+ getSinkForRoute_: function(route) {
+ return route ? this.sinkMap_[route.sinkId] : null;
+ },
+
+ /**
+ * @param {?Element} element Conditionally-templated element to check.
+ * @return {boolean} Whether |element| is considered present in the document
+ * as a conditionally-templated element. This does not check the |hidden|
+ * attribute.
+ */
+ hasConditionalElement_: function(element) {
+ return !!element &&
+ (!element.style.display || element.style.display != 'none');
+ },
+
+ /**
* Returns whether given string is undefined, null, empty, or whitespace only.
* @param {?string} str String to be tested.
* @return {boolean} |true| if the string is undefined, null, empty, or
@@ -1173,20 +1208,6 @@ Polymer({
},
/**
- * Updates sink list when user is searching.
- * @param {boolean} isUserSearching Whether the user is searching for sinks.
- */
- isUserSearchingChanged_: function(isUserSearching) {
- if (isUserSearching) {
- this.currentView_ = media_router.MediaRouterView.FILTER;
- this.updateElementPositioning_();
- this.filterSinks_(this.searchInputText_);
- } else {
- this.currentView_ = media_router.MediaRouterView.SINK_LIST;
- }
- },
-
- /**
* Reports a user filter action if |searchInputText_| is not empty and the
* filter action hasn't been reported since the view changed to the filter
* view.
@@ -1245,7 +1266,7 @@ Polymer({
// issue was non-blocking, this would be a no-op. It is expected that
// the only way to clear an issue is by user action; the IssueManager
// (C++ side) does not clear issues in the UI.
- this.currentView_ = media_router.MediaRouterView.SINK_LIST;
+ this.showSinkList_();
}
if (!!this.pendingCreatedRouteId_ && !!issue &&
@@ -1255,6 +1276,35 @@ Polymer({
},
/**
+ * If an element in the search results list has keyboard focus when we are
+ * transitioning from the filter view to the sink list view, give focus to the
+ * same sink in the sink list. Otherwise we leave the keyboard focus where it
+ * is.
+ * @private
+ */
+ maybeUpdateFocusOnFilterViewExit_: function() {
+ var searchSinks = this.$$('#search-results').querySelectorAll('paper-item');
+ var focusedElem = Array.prototype.find.call(searchSinks, function(sink) {
+ return sink.focused;
+ });
+ if (!focusedElem) {
+ return;
+ }
+ var focusedSink =
+ this.$$('#searchResults').itemForElement(focusedElem).sinkItem;
+ setTimeout(function() {
+ var sinkList = this.$$('#sinkList');
+ var sinks = this.$['sink-list-view'].querySelectorAll('paper-item');
+ Array.prototype.some.call(sinks, function(sink) {
+ if (sinkList.itemForElement(sink).id == focusedSink.id) {
+ sink.focus();
+ return true;
+ }
+ });
+ }.bind(this));
+ },
+
+ /**
* May update |populatedSinkListSeenTimeMs_| depending on |currentView| and
* |sinksToShow|.
* Called when |currentView_| or |sinksToShow_| is updated.
@@ -1278,6 +1328,230 @@ Polymer({
},
/**
+ * Animates the transition from the filter view, where the search field is at
+ * the top of the list, to the sink list view, where the search field is at
+ * the bottom of the list.
+ *
+ * If this is called while another animation is in progress, it queues itself
+ * to be run at the end of the current animation.
+ *
+ * @param {!function()} resolve Resolves the animation promise that is waiting
+ * on this animation.
+ * @private
+ */
+ moveSearchToBottom_: function(resolve) {
+ var deviceMissing = this.$['device-missing'];
+ var list = this.$$('#sink-list');
+ var resultsContainer = this.$$('#search-results-container');
+ var search = this.$$('#sink-search');
+ var view = this.$['sink-list-view'];
+
+ var hasList = this.hasConditionalElement_(list);
+ var initialHeight = view.offsetHeight;
+ // Force the view height to be max dialog height.
+ view.style['overflow'] = 'hidden';
+
+ var searchInitialOffsetHeight = search.offsetHeight;
+ var searchInitialPaddingBottom, searchInitialPaddingTop;
+ [searchInitialPaddingBottom, searchInitialPaddingTop] =
+ this.getElementVerticalPadding_(search);
+ var searchPadding = searchInitialPaddingBottom + searchInitialPaddingTop;
+ var searchHeight = search.offsetHeight - searchPadding;
+ this.searchUseBottomPadding = true;
+ var searchFinalPaddingBottom, searchFinalPaddingTop;
+ [searchFinalPaddingBottom, searchFinalPaddingTop] =
+ this.getElementVerticalPadding_(search);
+ var searchFinalOffsetHeight =
+ searchHeight + searchFinalPaddingBottom + searchFinalPaddingTop;
+
+ var resultsInitialTop = 0;
+ var finalHeight = 0;
+ // Get final view height ahead of animation.
+ if (hasList) {
+ list.style['position'] = 'absolute';
+ list.style['opacity'] = '0';
+ this.hideSinkListForAnimation_ = false;
+ finalHeight += list.offsetHeight;
+ list.style['position'] = 'relative';
+ } else {
+ resultsInitialTop +=
+ deviceMissing.offsetHeight + searchInitialOffsetHeight;
+ finalHeight += deviceMissing.offsetHeight;
+ }
+
+ var searchInitialTop = hasList ? 0 : deviceMissing.offsetHeight;
+ var searchFinalTop = hasList ? list.offsetHeight - search.offsetHeight :
+ deviceMissing.offsetHeight;
+ resultsContainer.style['position'] = 'absolute';
+ resultsContainer.style['overflow-y'] = '';
+
+ var duration =
+ this.computeAnimationDuration_(searchFinalTop - searchInitialTop);
+ var timing = {duration: duration, easing: 'ease-in-out', fill: 'forwards'};
+
+ // This GroupEffect does the reverse of |moveSearchToTop_|. It fades the
+ // sink list in while sliding the search input and search results list down.
+ // The dialog height is also adjusted smoothly to the sink list height.
+ var deviceMissingEffect = new KeyframeEffect(deviceMissing,
+ [{'marginBottom': searchInitialOffsetHeight},
+ {'marginBottom': searchFinalOffsetHeight}],
+ timing);
+ var listEffect = new KeyframeEffect(list,
+ [{'opacity': '0'}, {'opacity': '1'}],
+ timing);
+ var resultsEffect = new KeyframeEffect(resultsContainer,
+ [{'top': resultsInitialTop + 'px',
+ 'paddingTop': resultsContainer.style['padding-top']},
+ {'top': '100%', 'paddingTop': '0px'}],
+ timing);
+ var searchEffect = new KeyframeEffect(search,
+ [{'top': searchInitialTop + 'px', 'marginTop': '0px',
+ 'paddingBottom': searchInitialPaddingBottom + 'px',
+ 'paddingTop': searchInitialPaddingTop + 'px'},
+ {'top': '100%', 'marginTop': '-' + searchFinalOffsetHeight + 'px',
+ 'paddingBottom': searchFinalPaddingBottom + 'px',
+ 'paddingTop': searchFinalPaddingTop + 'px'}],
+ timing);
+ var viewEffect = new KeyframeEffect(view,
+ [{'height': initialHeight + 'px', 'paddingBottom': '0px'},
+ {'height': finalHeight + 'px',
+ 'paddingBottom': searchFinalOffsetHeight + 'px'}],
+ timing);
+ var player = document.timeline.play(new GroupEffect(hasList ?
+ [listEffect, resultsEffect, searchEffect, viewEffect] :
+ [deviceMissingEffect, resultsEffect, searchEffect, viewEffect]));
+
+ var that = this;
+ var finalizeAnimation = function() {
+ view.style['overflow'] = '';
+ that.putSearchAtBottom_();
+ that.filterTransitionPlayer_.cancel();
+ that.filterTransitionPlayer_ = null;
+ that.isSearchListHidden_ = true;
+ resolve();
+ };
+
+ player.finished.then(finalizeAnimation);
+ this.filterTransitionPlayer_ = player;
+ },
+
+ /**
+ * Animates the transition from the sink list view, where the search field is
+ * at the bottom of the list, to the filter view, where the search field is at
+ * the top of the list.
+ *
+ * If this is called while another animation is in progress, it queues itself
+ * to be run at the end of the current animation.
+ *
+ * @param {!function()} resolve Resolves the animation promise that is waiting
+ * on this animation.
+ * @private
+ */
+ moveSearchToTop_: function(resolve) {
+ var deviceMissing = this.$['device-missing'];
+ var list = this.$$('#sink-list');
+ var noMatches = this.$$('#no-search-matches');
+ var results = this.$$('#search-results');
+ var resultsContainer = this.$$('#search-results-container');
+ var search = this.$$('#sink-search');
+ var view = this.$['sink-list-view'];
+
+ // Saves current search container |offsetHeight| which includes bottom
+ // padding.
+ var searchInitialOffsetHeight = search.offsetHeight;
+ var hasList = this.hasConditionalElement_(list);
+ var searchInitialTop = hasList ?
+ list.offsetHeight - searchInitialOffsetHeight :
+ deviceMissing.offsetHeight;
+ var searchFinalTop = hasList ? 0 : deviceMissing.offsetHeight;
+ var searchInitialPaddingBottom, searchInitialPaddingTop;
+ [searchInitialPaddingBottom, searchInitialPaddingTop] =
+ this.getElementVerticalPadding_(search);
+ var searchPadding = searchInitialPaddingBottom + searchInitialPaddingTop;
+ var searchHeight = search.offsetHeight - searchPadding;
+ this.searchUseBottomPadding =
+ this.shouldSearchUseBottomPadding_(deviceMissing);
+ var searchFinalPaddingBottom, searchFinalPaddingTop;
+ [searchFinalPaddingBottom, searchFinalPaddingTop] =
+ this.getElementVerticalPadding_(search);
+ var searchFinalOffsetHeight =
+ searchHeight + searchFinalPaddingBottom + searchFinalPaddingTop;
+
+ // Omitting |search.offsetHeight| because it is handled by view animation
+ // separately.
+ var initialHeight =
+ hasList ? list.offsetHeight : deviceMissing.offsetHeight;
+ view.style['overflow'] = 'hidden';
+
+ var resultsPadding = this.computeElementVerticalPadding_(results);
+ var finalHeight = this.computeTotalSearchHeight_(
+ deviceMissing, noMatches, results, searchFinalOffsetHeight,
+ this.sinkListMaxHeight_ + resultsPadding);
+
+ var duration =
+ this.computeAnimationDuration_(searchFinalTop - searchInitialTop);
+ var timing = {duration: duration, easing: 'ease-in-out', fill: 'forwards'};
+
+ // This GroupEffect will cause the sink list to fade out while the search
+ // input and search results list slide up. The dialog will also resize
+ // smoothly to the new search result list height.
+ var deviceMissingEffect = new KeyframeEffect(deviceMissing,
+ [{'marginBottom': searchInitialOffsetHeight},
+ {'marginBottom': searchFinalOffsetHeight}],
+ timing);
+ var listEffect = new KeyframeEffect(list,
+ [{'opacity': '1'}, {'opacity': '0'}],
+ timing);
+ var resultsEffect = new KeyframeEffect(resultsContainer,
+ [{'top': '100%', 'paddingTop': '0px'},
+ {'top': searchFinalTop + 'px',
+ 'paddingTop': searchFinalOffsetHeight + 'px'}],
+ timing);
+ var searchEffect = new KeyframeEffect(search,
+ [{'top': '100%', 'marginTop': '-' + searchInitialOffsetHeight + 'px',
+ 'paddingBottom': searchInitialPaddingBottom + 'px',
+ 'paddingTop': searchInitialPaddingTop + 'px'},
+ {'top': searchFinalTop + 'px', 'marginTop': '0px',
+ 'paddingBottom': searchFinalPaddingBottom + 'px',
+ 'paddingTop': searchFinalPaddingTop + 'px'}],
+ timing);
+ var viewEffect = new KeyframeEffect(view,
+ [{'height': initialHeight + 'px',
+ 'paddingBottom': searchInitialOffsetHeight + 'px'},
+ {'height': finalHeight + 'px', 'paddingBottom': '0px'}],
+ timing);
+ var player = document.timeline.play(new GroupEffect(hasList ?
+ [listEffect, resultsEffect, searchEffect, viewEffect] :
+ [deviceMissingEffect, resultsEffect, searchEffect, viewEffect]));
+
+ var that = this;
+ var finalizeAnimation = function() {
+ // When we are moving the search results up into view, the user may type
+ // more text or delete text which may change the height of the search
+ // results list. In this case, the dialog height that the animation ends
+ // on will now be wrong. In order to correct this smoothly,
+ // |putSearchAtTop_| will queue another animation just to adjust the
+ // dialog height.
+ //
+ // The |filterTransitionPlayer_| will hold all of the animated elements in
+ // their final keyframe state until it is canceled or another player
+ // overrides it because we used |fill: 'forwards'| in all of the effects.
+ // So unlike |moveSearchToBottom_|, we don't know for sure whether we want
+ // to cancel |filterTransitionPlayer_| after |putSearchAtTop_| because
+ // another animation may have been run to correct the dialog height.
+ //
+ // If |putSearchAtTop_| has to adjust the dialog height, it also queues
+ // itself to run again when that animation is finished. When the height is
+ // finally correct at the end of an animation, it will cancel
+ // |filterTransitionPlayer_| itself.
+ that.putSearchAtTop_(resolve);
+ };
+
+ player.finished.then(finalizeAnimation);
+ this.filterTransitionPlayer_ = player;
+ },
+
+ /**
* Handles a cast mode selection. Updates |headerText|, |headerTextTooltip|,
* and |shownCastModeValue_|.
*
@@ -1310,15 +1584,15 @@ Polymer({
},
/**
- * Handles a close-route-click event. Shows the sink list and starts a timer
- * to close the dialog if there is no click within three seconds.
+ * Handles a close-route event. Shows the sink list and starts a timer to
+ * close the dialog if there is no click within three seconds.
*
* @param {!Event} event The event object.
* Parameters in |event|.detail:
* route - route to close.
* @private
*/
- onCloseRouteClick_: function(event) {
+ onCloseRoute_: function(event) {
/** @type {{route: media_router.Route}} */
var detail = event.detail;
this.showSinkList_();
@@ -1408,10 +1682,15 @@ Polymer({
// handled on the C++ side instead of the JS side on non-mac platforms,
// which uses toolkit-views. Handle the expected behavior on all platforms
// here.
- if (e.keyCode == media_router.KEYCODE_ESC && !e.shiftKey &&
+ if (e.key == media_router.KEY_ESC && !e.shiftKey &&
!e.ctrlKey && !e.altKey && !e.metaKey) {
// When searching, allow ESC as a mechanism to leave the filter view.
- if (this.isUserSearching_) {
+ if (this.currentView_ == media_router.MediaRouterView.FILTER) {
+ // If the user tabbed to an item in the search results, or otherwise has
+ // an item in the list focused, focus will seem to vanish when we
+ // transition back to the sink list. Instead we should move focus to the
+ // appropriate item in the sink list.
+ this.maybeUpdateFocusOnFilterViewExit_();
this.showSinkList_();
e.preventDefault();
} else {
@@ -1441,20 +1720,213 @@ Polymer({
},
/**
+ * Called when a search has completed up to route creation. |sinkId|
+ * identifies the sink that should be in |allSinks|, if a sink was found.
+ *
+ * @param {string} sinkId The ID of the sink that is the result of the
+ * currently pending search.
+ */
+ onReceiveSearchResult: function(sinkId) {
+ this.pseudoSinkSearchState_.receiveSinkResponse(sinkId);
+ this.currentLaunchingSinkId_ =
+ this.pseudoSinkSearchState_.checkForRealSink(this.allSinks);
+ this.rebuildSinksToShow_();
+ // If we're in filter view, make sure the |sinksToShow_| change is picked
+ // up.
+ if (this.currentView_ == media_router.MediaRouterView.FILTER) {
+ this.filterSinks_(this.searchInputText_);
+ }
+ },
+
+ /**
+ * Handles a replace-route-click event. Closes the currently displayed local
+ * route and shows the sink list. When the current route has been successfully
+ * removed from the route map, the container will launch a new route for the
+ * same sink.
+ *
+ * @param {!Event} event The event object.
+ * Parameters in |event|.detail:
+ * route - route to close.
+ * @private
+ */
+ onReplaceRouteClick_: function(event) {
+ /** @type {{route: !media_router.Route}} */
+ var detail = event.detail;
+ this.currentLaunchingSinkId_ = detail.route.sinkId;
+ this.launchingSinkAwaitingRouteClose_ = true;
+ this.fire('close-route', detail);
+ this.showSinkList_();
+ this.maybeReportUserFirstAction(
+ media_router.MediaRouterUserAction.REPLACE_LOCAL_ROUTE);
+ },
+
+ /**
* Called when a sink is clicked.
*
* @param {!Event} event The event object.
* @private
*/
onSinkClick_: function(event) {
- var clickedSink = (this.isUserSearching_) ?
+ var clickedSink =
+ (this.currentView_ == media_router.MediaRouterView.FILTER) ?
this.$$('#searchResults').itemForElement(event.target).sinkItem :
- this.$.sinkList.itemForElement(event.target);
+ this.$$('#sinkList').itemForElement(event.target);
this.showOrCreateRoute_(clickedSink);
this.fire('sink-click', {index: event['model'].index});
},
/**
+ * Sets the positioning of the sink list, search input, and search results so
+ * that everything is in the correct state for the sink list view.
+ *
+ * @private
+ */
+ putSearchAtBottom_: function() {
+ var search = this.$$('#sink-search');
+ if (!this.hasConditionalElement_(search)) {
+ return;
+ }
+ var deviceMissing = this.$['device-missing'];
+ var list = this.$$('#sink-list');
+ var resultsContainer = this.$$('#search-results-container');
+ var view = this.$['sink-list-view'];
+ this.searchUseBottomPadding = true;
+ search.style['top'] = '';
+ if (resultsContainer) {
+ resultsContainer.style['position'] = '';
+ resultsContainer.style['padding-top'] = '';
+ resultsContainer.style['top'] = '';
+ }
+ this.hideSinkListForAnimation_ = false;
+ var hasList = this.hasConditionalElement_(list);
+ if (hasList) {
+ search.style['margin-top'] = '-' + search.offsetHeight + 'px';
+ view.style['padding-bottom'] = search.offsetHeight + 'px';
+ list.style['opacity'] = '';
+ } else {
+ deviceMissing.style['margin-bottom'] = search.offsetHeight + 'px';
+ search.style['margin-top'] = '';
+ view.style['padding-bottom'] = '';
+ }
+ },
+
+ /**
+ * Sets the positioning of the sink list, search input, and search results so
+ * that everything is in the correct state for the filter view.
+ *
+ * If the user was searching while the |moveSearchToTop_| animation was
+ * happening then the dialog height that animation ends at could be different
+ * than the current height of the search results. If this is the case, this
+ * function first spawns a new animation that smoothly corrects the height
+ * problem. This is iterative, but once we enter a call where the heights
+ * match up, the elements will become static again.
+ *
+ * @param {!function()} resolve Resolves the animation promise that is waiting
+ * on this animation.
+ * @private
+ */
+ putSearchAtTop_: function(resolve) {
+ var deviceMissing = this.$['device-missing'];
+ var list = this.$$('#sink-list');
+ var noMatches = this.$$('#no-search-matches');
+ var results = this.$$('#search-results');
+ var resultsContainer = this.$$('#search-results-container');
+ var search = this.$$('#sink-search');
+ var view = this.$['sink-list-view'];
+
+ // If there is a height mismatch between where the animation calculated the
+ // height should be and where it is now because the search results changed
+ // during the animation, correct it with... another animation.
+ this.searchUseBottomPadding =
+ this.shouldSearchUseBottomPadding_(deviceMissing);
+ var resultsPadding = this.computeElementVerticalPadding_(results);
+ var finalHeight = this.computeTotalSearchHeight_(deviceMissing, noMatches,
+ results, search.offsetHeight, this.sinkListMaxHeight_ + resultsPadding);
+ if (finalHeight != view.offsetHeight) {
+ var viewEffect = new KeyframeEffect(view,
+ [{'height': view.offsetHeight + 'px'},
+ {'height': finalHeight + 'px'}],
+ {duration:
+ this.computeAnimationDuration_(finalHeight - view.offsetHeight),
+ easing: 'ease-in-out', fill: 'forwards'});
+ var player = document.timeline.play(viewEffect);
+ if (this.heightAdjustmentPlayer_) {
+ this.heightAdjustmentPlayer_.cancel();
+ }
+ this.heightAdjustmentPlayer_ = player;
+ player.finished.then(this.putSearchAtTop_.bind(this, resolve));
+ return;
+ }
+
+ var hasList = this.hasConditionalElement_(list);
+ search.style['margin-top'] = '';
+ deviceMissing.style['margin-bottom'] = search.offsetHeight + 'px';
+ var searchFinalTop = hasList ? 0 : deviceMissing.offsetHeight;
+ var resultsPaddingTop = hasList ? search.offsetHeight + 'px' : '0px';
+ search.style['top'] = searchFinalTop + 'px';
+ this.hideSinkListForAnimation_ = true;
+ resultsContainer.style['position'] = 'relative';
+ resultsContainer.style['padding-top'] = resultsPaddingTop;
+ resultsContainer.style['top'] = '';
+ resultsContainer.style['overflow-y'] = 'auto';
+
+ view.style['overflow'] = '';
+ view.style['padding-bottom'] = '';
+ if (this.filterTransitionPlayer_) {
+ this.filterTransitionPlayer_.cancel();
+ this.filterTransitionPlayer_ = null;
+ }
+
+ if (this.heightAdjustmentPlayer_) {
+ this.heightAdjustmentPlayer_.cancel();
+ this.heightAdjustmentPlayer_ = null;
+ }
+
+ resolve();
+ },
+
+ /**
+ * Queues a call to |moveSearchToBottom_| by adding it as a continuation to
+ * |animationPromise_| and updating |animationPromise_|.
+ */
+ queueMoveSearchToBottom_: function() {
+ var oldPromise = this.animationPromise_;
+ var that = this;
+ this.animationPromise_ = new Promise(function(resolve) {
+ oldPromise.then(that.moveSearchToBottom_.bind(that, resolve));
+ });
+ },
+
+ /**
+ * Queues a call to |moveSearchToTop_| by adding it as a continuation to
+ * |animationPromise_| and updating |animationPromise_|. The new promise will
+ * not resolve until |putSearchAtTop_| is finished, including any potential
+ * dialog height adjustment animations.
+ */
+ queueMoveSearchToTop_: function() {
+ var oldPromise = this.animationPromise_;
+ var that = this;
+ this.animationPromise_ = new Promise(function(resolve) {
+ oldPromise.then(function() {
+ that.isSearchListHidden_ = false;
+ setTimeout(that.moveSearchToTop_.bind(that, resolve));
+ });
+ });
+ },
+
+ /**
+ * Queues a call to |putSearchAtTop_| by adding it as a continuation to
+ * |animationPromise_| and updating |animationPromise_|.
+ */
+ queuePutSearchAtTop_: function() {
+ var that = this;
+ var oldPromise = this.animationPromise_;
+ this.animationPromise_ = new Promise(function(resolve) {
+ oldPromise.then(that.putSearchAtTop_.bind(that, resolve));
+ });
+ },
+
+ /**
* Called when |routeList| is updated. Rebuilds |routeMap_| and
* |sinkToRouteMap_|.
*
@@ -1499,6 +1971,14 @@ Polymer({
this.sinkToRouteMap_ = tempSinkToRouteMap;
this.rebuildSinksToShow_();
+
+ // A sink was waiting for its route to be closed and removed from the route
+ // map so a new route to it can be started.
+ if (this.launchingSinkAwaitingRouteClose_ &&
+ !(this.currentLaunchingSinkId_ in this.sinkToRouteMap_) &&
+ this.currentLaunchingSinkId_ in this.sinkMap_) {
+ this.showOrCreateRoute_(this.sinkMap_[this.currentLaunchingSinkId_]);
+ }
},
/**
@@ -1508,11 +1988,24 @@ Polymer({
* name.
*/
rebuildSinksToShow_: function() {
- var sinksToShow = [];
+ var sinksToShow = this.allSinks.filter(function(sink) {
+ return !sink.isPseudoSink;
+ }, this);
+ if (this.pseudoSinkSearchState_) {
+ var pendingPseudoSink = this.pseudoSinkSearchState_.getPseudoSink();
+ // Here we will treat the pseudo sink that launched the search as a real
+ // sink until one is returned by search. This way it isn't possible to
+ // ever reach a UI state where there is no spinner being shown in the sink
+ // list but |currentLaunchingSinkId_| is non-empty (thereby preventing any
+ // other sink from launching).
+ if (pendingPseudoSink.id == this.currentLaunchingSinkId_) {
+ sinksToShow.unshift(pendingPseudoSink);
+ }
+ }
if (this.userHasSelectedCastMode_) {
// If user explicitly selected a cast mode, then we show only sinks that
// are compatible with current cast mode or sinks that are active.
- sinksToShow = this.allSinks.filter(function(element) {
+ sinksToShow = sinksToShow.filter(function(element) {
return (element.castModes & this.shownCastModeValue_) ||
this.sinkToRouteMap_[element.id];
}, this);
@@ -1523,7 +2016,6 @@ Polymer({
// - Otherwise, the cast mode becomes auto mode.
// Either way, all sinks will be shown.
this.setShownCastMode_(this.computeCastMode_());
- sinksToShow = this.allSinks;
}
this.sinksToShow_ = sinksToShow;
@@ -1538,12 +2030,34 @@ Polymer({
this.sinkMap_ = {};
this.allSinks.forEach(function(sink) {
- this.sinkMap_[sink.id] = sink;
+ if (!sink.isPseudoSink) {
+ this.sinkMap_[sink.id] = sink;
+ }
}, this);
+ if (this.pseudoSinkSearchState_) {
+ this.currentLaunchingSinkId_ =
+ this.pseudoSinkSearchState_.checkForRealSink(this.allSinks);
+ }
+ this.pseudoSinks_ = this.allSinks.filter(function(sink) {
+ return sink.isPseudoSink && !!sink.domain;
+ });
this.rebuildSinksToShow_();
- if (this.isUserSearching_) {
- this.filterSinks_(this.searchInputText_);
+ this.searchEnabled_ = this.searchEnabled_ || this.pseudoSinks_.length > 0 ||
+ this.sinksToShow_.length >= media_router.MINIMUM_SINKS_FOR_SEARCH;
+ this.filterSinks_(this.searchInputText_ || '');
+ if (this.currentView_ != media_router.MediaRouterView.FILTER) {
+ // This code is in the unique position of seeing |animationPromise_| as
+ // null on startup. |allSinks| is initialized before |animationPromise_|
+ // and this listener runs when |allSinks| is initialized.
+ if (this.animationPromise_) {
+ this.animationPromise_ =
+ this.animationPromise_.then(this.putSearchAtBottom_.bind(this));
+ } else {
+ this.putSearchAtBottom_();
+ }
+ } else {
+ this.queuePutSearchAtTop_();
}
},
@@ -1556,6 +2070,7 @@ Polymer({
* @private
*/
resetRouteCreationProperties_: function(creationSuccess) {
+ this.pseudoSinkSearchState_ = null;
this.currentLaunchingSinkId_ = '';
this.pendingCreatedRouteId_ = '';
@@ -1570,71 +2085,26 @@ Polymer({
// already focused. In the case that user typed text, hit escape, then
// clicks the search button, a focus event will not fire and so its event
// handler from ready() will not run.
- this.isUserSearching_ = true;
+ this.showSearchResults_();
this.$$('#sink-search-input').focus();
},
/**
- * Sets various focus and blur event handlers to handle |isSearchFocused_| and
- * showing search results when the input is focused.
+ * Initializes the position of the search input if search becomes enabled.
+ * @param {boolean} searchEnabled The new value of |searchEnabled_|.
* @private
*/
- setSearchFocusHandlers_: function() {
- var search = this.$['sink-search-input'];
-
- // The window can see a blur event for two important cases: the window is
- // actually losing focus or keyboard focus is wrapping from the end of the
- // document to the beginning. To handle both cases, we save the state of
- // |isSearchFocused_| during the window blur event.
- //
- // The corresponding window focus event can do nothing if |isSearchFocused_|
- // was false during the blur event. If the search input is gaining focus now
- // it will work correctly. There are two cases when the input had focus
- // during the window blur event: the input still has focus and the input
- // lost focus. These cases are handled by the logic around
- // |isSearchFocusedShouldBeSet_| and |isSearchFocused_|.
- //
- // Because the window focus event will always happen first, it doesn't know
- // whether the input focus handler will later run or not. If it is not going
- // to run, then |isSearchFocused_| should be set to |false|, otherwise it
- // should be |true|. So the window focus handler just sets
- // |isSearchFocused_| to |false| and makes a note in
- // |isSearchFocusedShouldBeSet_| that |isSearchFocused_| should actually be
- // set to true if the search focus handler runs. The |setTimeout| in the
- // window focus handler clears this note as soon as all focus event handlers
- // have run.
- window.addEventListener('blur', function() {
- this.isSearchFocusedOnWindowBlur_ = this.isSearchFocused_;
- }.bind(this));
- window.addEventListener('focus', function() {
- if (this.isSearchFocusedOnWindowBlur_) {
- this.isSearchFocusedOnWindowBlur_ = false;
- this.isSearchFocusedShouldBeSet_ = true;
- this.isSearchFocused_ = false;
- setTimeout(function() {
- this.isSearchFocusedShouldBeSet_ = false;
- }.bind(this));
- }
- }.bind(this));
- search.addEventListener('blur', function() {
- // This lets normal blur cases work as expected, but doesn't get in the
- // way of the window blur handler capturing the "current" state. This is
- // the case because this will be run after all the blur handlers are done.
- setTimeout(function() { this.isSearchFocused_ = false; }.bind(this));
- }.bind(this));
- search.addEventListener('focus', function() {
- if (this.isSearchFocusedShouldBeSet_) {
- this.isSearchFocused_ = true;
- }
- if (!this.isSearchFocused_) {
- this.isSearchFocused_ = true;
- this.isUserSearching_ = true;
- }
- }.bind(this));
+ searchEnabledChanged_: function(searchEnabled) {
+ if (searchEnabled) {
+ this.async(function() {
+ this.setSearchFocusHandlers_();
+ this.putSearchAtBottom_();
+ });
+ }
},
/**
- * Filters the sink list when the input text changes and shows the search
+ * Filters the sink list when the input text changes and shows the search
* results if |searchInputText| is not empty.
* @param {string} searchInputText The currently entered search text.
* @private
@@ -1642,12 +2112,42 @@ Polymer({
searchInputTextChanged_: function(searchInputText) {
this.filterSinks_(searchInputText);
if (searchInputText.length != 0) {
- this.isUserSearching_ = true;
+ this.showSearchResults_();
this.maybeReportFilter_();
}
},
/**
+ * Sets various focus and blur event handlers to handle showing search results
+ * when the search input is focused.
+ * @private
+ */
+ setSearchFocusHandlers_: function() {
+ var searchInput = this.$$('#sink-search-input');
+ var that = this;
+
+ // The window can see a blur event for two important cases: the window is
+ // actually losing focus or keyboard focus is wrapping from the end of the
+ // document to the beginning. To handle both cases, we save whether the
+ // search input was focused during the window blur event.
+ //
+ // When the search input receives focus, it could be as part of window
+ // focus. If the search input was also focused on window blur, it shouldn't
+ // show search results if they aren't already being shown. Otherwise,
+ // focusing the search input should activate the FILTER view by calling
+ // |showSearchResults_()|.
+ window.addEventListener('blur', function() {
+ that.isSearchFocusedOnWindowBlur_ =
+ that.shadowRoot.activeElement == searchInput;
+ });
+ searchInput.addEventListener('focus', function() {
+ if (!that.isSearchFocusedOnWindowBlur_) {
+ that.showSearchResults_();
+ }
+ });
+ },
+
+ /**
* Updates the shown cast mode, and updates the header text fields
* according to the cast mode. If |castMode| type is AUTO, then set
* |userHasSelectedCastMode_| to false.
@@ -1666,6 +2166,16 @@ Polymer({
},
/**
+ * @param {?Element} deviceMissing Device missing message element.
+ * @return {boolean} Whether the search input should use vertical padding as
+ * if it were the lowest (at the very bottom) item in the dialog.
+ * @private
+ */
+ shouldSearchUseBottomPadding_: function(deviceMissing) {
+ return !deviceMissing.hasAttribute('hidden');
+ },
+
+ /**
* Shows the cast mode list.
*
* @private
@@ -1688,23 +2198,43 @@ Polymer({
this.fire('navigate-sink-list-to-details');
this.maybeReportUserFirstAction(
media_router.MediaRouterUserAction.STATUS_REMOTE);
- } else if (this.currentLaunchingSinkId_ == '') {
+ } else if ((this.launchingSinkAwaitingRouteClose_ &&
+ this.currentLaunchingSinkId_ == sink.id) ||
+ this.currentLaunchingSinkId_ == '') {
// Allow one launch at a time.
- this.fire('create-route', {
- sinkId: sink.id,
- // If user selected a cast mode, then we will create a route using that
- // cast mode. Otherwise, the UI is in "auto" cast mode and will use the
- // preferred cast mode compatible with the sink. The preferred cast mode
- // value is the least significant bit on the bitset.
- selectedCastModeValue:
- this.shownCastModeValue_ == media_router.CastModeType.AUTO ?
- sink.castModes & -sink.castModes : this.shownCastModeValue_
- });
- this.currentLaunchingSinkId_ = sink.id;
+ var selectedCastModeValue =
+ this.shownCastModeValue_ == media_router.CastModeType.AUTO ?
+ sink.castModes & -sink.castModes : this.shownCastModeValue_;
+ if (sink.isPseudoSink) {
+ this.pseudoSinkSearchState_ = new PseudoSinkSearchState(sink);
+ this.fire('search-sinks-and-create-route', {
+ id: sink.id,
+ name: sink.name,
+ domain: sink.domain,
+ selectedCastMode: selectedCastModeValue
+ });
+ } else {
+ this.fire('create-route', {
+ sinkId: sink.id,
+ // If user selected a cast mode, then we will create a route using
+ // that cast mode. Otherwise, the UI is in "auto" cast mode and will
+ // use the preferred cast mode compatible with the sink. The preferred
+ // cast mode value is the least significant bit on the bitset.
+ selectedCastModeValue: selectedCastModeValue
+ });
- var timeToSelectSink =
- performance.now() - this.populatedSinkListSeenTimeMs_;
- this.fire('report-sink-click-time', {timeMs: timeToSelectSink});
+ var timeToSelectSink =
+ performance.now() - this.populatedSinkListSeenTimeMs_;
+ this.fire('report-sink-click-time', {timeMs: timeToSelectSink});
+ }
+ if (!this.launchingSinkAwaitingRouteClose_) {
+ this.currentLaunchingSinkId_ = sink.id;
+ } else {
+ this.launchingSinkAwaitingRouteClose_ = false;
+ }
+ if (sink.isPseudoSink) {
+ this.rebuildSinksToShow_();
+ }
this.maybeReportUserFirstAction(
media_router.MediaRouterUserAction.START_LOCAL);
@@ -1723,13 +2253,30 @@ Polymer({
},
/**
+ * Shows the search results.
+ *
+ * @private
+ */
+ showSearchResults_: function() {
+ if (this.currentView_ != media_router.MediaRouterView.FILTER) {
+ this.currentView_ = media_router.MediaRouterView.FILTER;
+ this.queueMoveSearchToTop_();
+ }
+ },
+
+ /**
* Shows the sink list.
*
* @private
*/
showSinkList_: function() {
- this.currentView_ = media_router.MediaRouterView.SINK_LIST;
- this.isUserSearching_ = false;
+ if (this.currentView_ == media_router.MediaRouterView.FILTER) {
+ this.queueMoveSearchToBottom_();
+ this.currentView_ = media_router.MediaRouterView.SINK_LIST;
+ } else {
+ this.currentView_ = media_router.MediaRouterView.SINK_LIST;
+ this.putSearchAtBottom_();
+ }
},
/**
@@ -1776,17 +2323,33 @@ Polymer({
var issueHeight = this.$$('#issue-banner') &&
this.$$('#issue-banner').style.display != 'none' ?
this.$$('#issue-banner').offsetHeight : 0;
- var searchHeight = this.$$('#sink-search').offsetHeight;
+ var search = this.$$('#sink-search');
+ var hasSearch = this.hasConditionalElement_(search);
+ var searchHeight = hasSearch ? search.offsetHeight : 0;
+ var searchPadding =
+ hasSearch ? this.computeElementVerticalPadding_(search) : 0;
this.$['container-header'].style.marginTop = firstRunFlowHeight + 'px';
this.$['content'].style.marginTop =
firstRunFlowHeight + headerHeight + 'px';
- this.$['sink-list'].style.maxHeight =
- this.dialogHeight_ - headerHeight - firstRunFlowHeight -
- issueHeight - searchHeight + 'px';
- var searchResults = this.$$('#search-results');
- if (searchResults) {
- searchResults.style.maxHeight = this.$['sink-list'].style.maxHeight;
+
+ var sinkList = this.$$('#sink-list');
+ if (hasSearch && sinkList) {
+ // This would need to be reset to '' if search could be disabled again,
+ // but once it's enabled it can't be disabled again.
+ sinkList.style.paddingBottom = '0';
+ }
+ var sinkListPadding =
+ sinkList ? this.computeElementVerticalPadding_(sinkList) : 0;
+
+ this.sinkListMaxHeight_ = this.dialogHeight_ - headerHeight -
+ firstRunFlowHeight - issueHeight - searchHeight + searchPadding -
+ sinkListPadding;
+ if (sinkList) {
+ sinkList.style.maxHeight = this.sinkListMaxHeight_ + 'px';
+ var searchResults = this.$$('#search-results');
+ if (searchResults)
+ searchResults.style.maxHeight = this.sinkListMaxHeight_ + 'px';
}
});
},
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_container/pseudo_sink_search_state.js b/chromium/chrome/browser/resources/media_router/elements/media_router_container/pseudo_sink_search_state.js
new file mode 100644
index 00000000000..b0c97cccdfa
--- /dev/null
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_container/pseudo_sink_search_state.js
@@ -0,0 +1,73 @@
+// 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.
+
+/**
+ * This class holds state that is relevant to the search process from the UI's
+ * perspective. It primarily handles the spinner logic while waiting for a
+ * search to complete. The spinner first needs to start on the pseudo sink, but
+ * when a real sink arrives to replace it the spinner should transfer to the
+ * real sink.
+ *
+ * Additionally, this class provides a method for
+ * onCreateRouteResponseReceived() that maps the pseudo sink ID that started the
+ * search to the real sink that was produced by the search. This helps check
+ * whether a received route is valid.
+ *
+ * @param {!media_router.Sink} pseudoSink Pseudo sink that started the search.
+ * @constructor
+ */
+var PseudoSinkSearchState = function(pseudoSink) {
+ /**
+ * Pseudo sink that started the search.
+ * @private {!media_router.Sink}
+ */
+ this.pseudoSink_ = pseudoSink;
+
+ /**
+ * The ID of the sink that is found by search.
+ * @private {string}
+ */
+ this.realSinkId_ = '';
+
+ /**
+ * Whether we have received a sink in the sink list with ID |realSinkId_|.
+ * @private {boolean}
+ */
+ this.hasRealSink_ = false;
+};
+
+/**
+ * Record the real sink ID returned from the Media Router.
+ * @param {string} sinkId Real sink ID that is the result of the search.
+ */
+PseudoSinkSearchState.prototype.receiveSinkResponse = function(sinkId) {
+ this.realSinkId_ = sinkId;
+};
+
+/**
+ * Checks whether we have a sink in |sinkList| that is our search result then
+ * computes the value for |currentLaunchingSinkId_| based on the state of the
+ * search. It should be the pseudo sink ID until the real sink arrives, then the
+ * real sink ID.
+ * @param {!Array<!media_router.Sink>} sinkList List of all sinks to check.
+ * @return {string} New value for |currentLaunchingSinkId_|.
+ */
+PseudoSinkSearchState.prototype.checkForRealSink = function(sinkList) {
+ if (!this.hasRealSink_) {
+ this.hasRealSink_ = !!this.realSinkId_ && sinkList.some(function(sink) {
+ return (sink.id == this.realSinkId_);
+ }, this);
+ return !this.hasRealSink_ ? this.pseudoSink_.id : this.realSinkId_;
+ }
+ return this.realSinkId_;
+};
+
+/**
+ * Returns the pseudo sink for the current search. This is used to enforce
+ * freezing its name in filter view and displaying it in the sink list view.
+ * @return {!media_router.Sink}
+ */
+PseudoSinkSearchState.prototype.getPseudoSink = function() {
+ return this.pseudoSink_;
+};
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_header/compiled_resources2.gyp b/chromium/chrome/browser/resources/media_router/elements/media_router_header/compiled_resources2.gyp
new file mode 100644
index 00000000000..40cfdea2b9f
--- /dev/null
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_header/compiled_resources2.gyp
@@ -0,0 +1,16 @@
+# 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': 'media_router_header',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:media_router_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css b/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css
index fc21ebe30e2..8c24a05bd70 100644
--- a/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.css
@@ -20,6 +20,10 @@
-webkit-padding-end: 4px;
}
+.cast-mode-list {
+ background-color: var(--paper-teal-700);
+}
+
#close-button {
-webkit-margin-start: auto;
height: 31px;
@@ -32,53 +36,53 @@
-webkit-padding-start: 24px;
}
+.filter {
+ background-color: var(--paper-deep-purple-500);
+}
+
+#header {
+ -webkit-padding-start: 8px;
+ align-items: center;
+ color: white;
+}
+
#header-and-arrow-container {
display: flex;
- height: 36px;
overflow: hidden;
white-space: nowrap;
}
#header-text {
-webkit-padding-end: 4px;
- color: white;
font-size: 1.175em;
- margin: 8px 0 0 0;
+ margin: 8px;
overflow: hidden;
text-overflow: ellipsis;
}
-paper-icon-button {
- display: inline-block;
-}
-
-paper-toolbar {
- -webkit-padding-start: 8px;
+.issue {
+ background-color: var(--paper-red-700);
}
-paper-toolbar::shadow .toolbar-tools {
- padding: 0;
-}
-
-paper-toolbar.cast-mode-list {
- background-color: var(--paper-teal-700);
-}
-
-paper-toolbar.filter {
- background-color: var(--paper-deep-purple-500);
+paper-icon-button {
+ display: inline-block;
}
-paper-toolbar.issue {
- background-color: var(--google-red-700);
+#main-container {
+ display: flex;
+ padding-top: 10px;
}
-paper-toolbar.route-details,
-paper-toolbar.sink-list {
+.route-details,
+.sink-list {
background-color: var(--paper-blue-700);
}
#user-email-container {
- -webkit-padding-start: 12px;
+ -webkit-padding-start: 8px;
+ bottom: 0;
font-size: 0.917em;
+ left: auto;
padding-bottom: 12px;
+ position: absolute;
}
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html b/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html
index 2be6c2eeed4..d4d69a7d886 100644
--- a/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html
@@ -1,39 +1,41 @@
<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/paper-icon-button/paper-icon-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toolbar/paper-toolbar.html">
+<link rel="import" href="../../icons/media_router_icons.html">
<dom-module name="media-router-header">
<link rel="import" type="css" href="../../media_router_common.css">
<link rel="import" type="css" href="media_router_header.css">
<template>
- <paper-toolbar id="header-toolbar" class$="[[view]]">
- <div id="back-button-container">
- <paper-icon-button id="back-button" icon="[[arrowDropIcon_]]"
- on-tap="onBackButtonClick_" title="[[backButtonTitle_]]"
- hidden$="[[computeBackButtonHidden_(view)]]">
- </paper-icon-button>
- </div>
- <div id="header-and-arrow-container" on-tap="onHeaderOrArrowClick_">
- <span id="header-text" title="[[tooltip]]">
- [[headingText]]</span>
- <div id="arrow-drop-container">
- <paper-icon-button icon="[[computeArrowDropIcon_(view)]]"
- id="arrow-drop-icon" disabled$="[[arrowDropIconDisabled]]"
- hidden$="[[computeArrowDropIconHidden_(view)]]"
- title="[[computeArrowDropTitle_(view)]]">
+ <div id="header" class$="[[view]]">
+ <div id="main-container">
+ <template is="dom-if" if="[[computeBackButtonShown_(view)]]">
+ <div id="back-button-container">
+ <paper-icon-button id="back-button" icon="[[arrowDropIcon_]]"
+ on-tap="onBackButtonClick_" title="[[i18n('backButtonTitle')]]">
+ </paper-icon-button>
+ </div>
+ </template>
+ <div id="header-and-arrow-container" on-tap="onHeaderOrArrowClick_">
+ <span id="header-text" title="[[tooltip]]">
+ [[headingText]]</span>
+ <div id="arrow-drop-container">
+ <paper-icon-button icon="[[computeArrowDropIcon_(view)]]"
+ id="arrow-drop-icon" disabled$="[[arrowDropIconDisabled]]"
+ hidden$="[[computeArrowDropIconHidden_(view)]]"
+ title="[[computeArrowDropTitle_(view)]]">
+ </paper-icon-button>
+ </div>
+ </div>
+ <div id="close-button-container">
+ <paper-icon-button icon="media-router:close" id="close-button"
+ on-tap="onCloseButtonClick_" title="[[i18n('closeButtonTitle')]]">
</paper-icon-button>
</div>
</div>
- <div id="close-button-container">
- <paper-icon-button icon="close" id="close-button"
- on-tap="onCloseButtonClick_" title="[[closeButtonTitle_]]">
- </paper-icon-button>
- </div>
<template is="dom-if" if="[[showEmail]]">
- <div id="user-email-container" class="bottom fit">
- <span>[[userEmail]]</span>
- </div>
+ <div id="user-email-container">[[userEmail]]</div>
</template>
- </paper-toolbar>
+ </div>
</template>
<script src="media_router_header.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js b/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js
index fba24a5cb16..599c99f86dc 100644
--- a/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js
@@ -10,11 +10,10 @@ Polymer({
/**
* The name of the icon used as the back button. This is set once, when
* the |this| is ready.
- * @private {string}
+ * @private {string|undefined}
*/
arrowDropIcon_: {
type: String,
- value: '',
},
/**
@@ -27,36 +26,11 @@ Polymer({
},
/**
- * Title text for the back button.
- * @private {string}
- */
- backButtonTitle_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('backButtonTitle');
- },
- },
-
- /**
- * Title text for the close button.
- * @private {string}
- */
- closeButtonTitle_: {
- type: String,
- readOnly: true,
- value: function() {
- return loadTimeData.getString('closeButtonTitle');
- },
- },
-
- /**
* The header text to show.
- * @type {string}
+ * @type {string|undefined}
*/
headingText: {
type: String,
- value: '',
},
/**
@@ -81,61 +55,62 @@ Polymer({
/**
* Whether to show the user email in the header.
- * @type {boolean}
+ * @type {boolean|undefined}
*/
showEmail: {
type: Boolean,
- value: false,
observer: 'maybeChangeHeaderHeight_',
},
/**
* The text to show in the tooltip.
- * @type {string}
+ * @type {string|undefined}
*/
tooltip: {
type: String,
- value: '',
},
/**
* The user email if they are signed in.
- * @type {string}
+ * @type {string|undefined}
*/
userEmail: {
type: String,
- value: '',
},
/**
* The current view that this header should reflect.
- * @type {?media_router.MediaRouterView}
+ * @type {?media_router.MediaRouterView|undefined}
*/
view: {
type: String,
- value: null,
observer: 'updateHeaderCursorStyle_',
},
},
- listeners: {
- 'focus': 'onFocus_',
+ behaviors: [
+ I18nBehavior,
+ ],
+
+ ready: function() {
+ this.$$('#header').style.height = this.headerWithoutEmailHeight_ + 'px';
},
attached: function() {
// isRTL() only works after i18n_template.js runs to set <html dir>.
// Set the back button icon based on text direction.
- this.arrowDropIcon_ = isRTL() ? 'arrow-forward' : 'arrow-back';
+ this.arrowDropIcon_ = isRTL() ?
+ 'media-router:arrow-forward' : 'media-router:arrow-back';
},
/**
* @param {?media_router.MediaRouterView} view The current view.
- * @return {string} The current arrow-drop-* icon to use.
+ * @return {string} The icon to use.
* @private
*/
computeArrowDropIcon_: function(view) {
return view == media_router.MediaRouterView.CAST_MODE_LIST ?
- 'arrow-drop-up' : 'arrow-drop-down';
+ 'media-router:arrow-drop-up' : 'media-router:arrow-drop-down';
},
/**
@@ -155,18 +130,18 @@ Polymer({
*/
computeArrowDropTitle_: function(view) {
return view == media_router.MediaRouterView.CAST_MODE_LIST ?
- loadTimeData.getString('viewDeviceListButtonTitle') :
- loadTimeData.getString('viewCastModeListButtonTitle');
+ this.i18n('viewDeviceListButtonTitle') :
+ this.i18n('viewCastModeListButtonTitle');
},
/**
* @param {?media_router.MediaRouterView} view The current view.
- * @return {boolean} Whether or not the back button should be hidden.
+ * @return {boolean} Whether or not the back button should be shown.
* @private
*/
- computeBackButtonHidden_: function(view) {
- return view != media_router.MediaRouterView.ROUTE_DETAILS &&
- view != media_router.MediaRouterView.FILTER;
+ computeBackButtonShown_: function(view) {
+ return view == media_router.MediaRouterView.ROUTE_DETAILS ||
+ view == media_router.MediaRouterView.FILTER;
},
/**
@@ -221,15 +196,14 @@ Polymer({
* @private
*/
maybeChangeHeaderHeight_: function(newValue, oldValue) {
- if (!!oldValue == !!newValue) {
+ if (oldValue == newValue)
return;
- }
// Ensures conditional templates are stamped.
this.async(function() {
var currentHeight = this.offsetHeight;
- this.$$('#header-toolbar').style.height =
+ this.$$('#header').style.height =
this.showEmail && !this.isEmptyOrWhitespace_(this.userEmail) ?
this.headerWithEmailHeight_ + 'px' :
this.headerWithoutEmailHeight_ + 'px';
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/compiled_resources2.gyp b/chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/compiled_resources2.gyp
new file mode 100644
index 00000000000..18e64ac7790
--- /dev/null
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/compiled_resources2.gyp
@@ -0,0 +1,14 @@
+# 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': 'media_router_search_highlighter',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/media_router_search_highlighter.js b/chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/media_router_search_highlighter.js
index 317907f2843..a38aa7f9ef6 100644
--- a/chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/media_router_search_highlighter.js
+++ b/chromium/chrome/browser/resources/media_router/elements/media_router_search_highlighter/media_router_search_highlighter.js
@@ -24,11 +24,11 @@ Polymer({
* null corresponds to an empty string when the arrays are being combined.
* So both examples reproduce the text 'living room', but with different
* words highlighted.
- * @type {{highlightedText: !Array<?string>, plainText: !Array<?string>}}
+ * @type {{highlightedText: !Array<?string>,
+ * plainText: !Array<?string>}|undefined}
*/
data: {
type: Object,
- value: null,
observer: 'dataChanged_',
},
@@ -36,11 +36,10 @@ Polymer({
* The text that this element is displaying as a plain string. The primary
* purpose for this property is to make getting this element's textContent
* easy for testing.
- * @type {?string}
+ * @type {string|undefined}
*/
text: {
type: String,
- value: null,
readOnly: true,
notify: false,
},
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_details/compiled_resources2.gyp b/chromium/chrome/browser/resources/media_router/elements/route_details/compiled_resources2.gyp
new file mode 100644
index 00000000000..92f14fd00cc
--- /dev/null
+++ b/chromium/chrome/browser/resources/media_router/elements/route_details/compiled_resources2.gyp
@@ -0,0 +1,16 @@
+# 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': 'route_details',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:media_router_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(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/media_router/elements/route_details/route_details.css b/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.css
index a1801c3ec5e..eaff052bf52 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
@@ -35,7 +35,3 @@
margin-top: 16px;
overflow: hidden;
}
-
-#start-casting-to-route-button {
- @apply(--layout-flex);
-}
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.html b/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.html
index a60128320c8..703f464c7d4 100644
--- a/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.html
+++ b/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.html
@@ -1,4 +1,5 @@
<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/paper-button/paper-button.html">
<dom-module id="route-details">
<link rel="import" type="css" href="../../media_router_common.css">
@@ -13,14 +14,14 @@
<div id="route-action-buttons" class="layout">
<paper-button flat class="route-button button"
id="start-casting-to-route-button"
- hidden$="[[!route.canJoin]]"
+ hidden$="[[computeCastButtonHidden_(route, replaceRouteAvailable_)]]"
on-tap="startCastingToRoute_">
- <span>[[startCastingButtonText_]]</span>
+ <span>[[i18n('startCastingButtonText')]]</span>
</paper-button>
<paper-button flat class="route-button button"
id="close-route-button"
on-tap="closeRoute_">
- <span>[[stopCastingButtonText_]]</span>
+ <span>[[i18n('stopCastingButtonText')]]</span>
</paper-button>
<div>
</template>
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.js b/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.js
index af5d4b11a81..ed6461731b3 100644
--- a/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.js
+++ b/chromium/chrome/browser/resources/media_router/elements/route_details/route_details.js
@@ -10,50 +10,57 @@ Polymer({
properties: {
/**
* The text for the current casting activity status.
- * @private {string}
+ * @private {string|undefined}
*/
activityStatus_: {
type: String,
- value: '',
},
/**
- * Whether the browser is currently incognito.
+ * Whether a sink is currently launching in the container.
* @type {boolean}
*/
- isOffTheRecord: {
+ isAnySinkCurrentlyLaunching: {
type: Boolean,
value: false,
},
/**
+ * Whether the external container will accept replace-route-click events.
+ * @private {boolean}
+ */
+ replaceRouteAvailable_: {
+ type: Boolean,
+ computed: 'computeReplaceRouteAvailable_(route, sink,' +
+ 'isAnySinkCurrentlyLaunching, shownCastModeValue)',
+ },
+
+ /**
* The route to show.
- * @type {?media_router.Route}
+ * @type {?media_router.Route|undefined}
*/
route: {
type: Object,
- value: null,
observer: 'maybeLoadCustomController_',
},
/**
- * The text for the start casting button.
- * @private {string}
+ * The cast mode shown to the user. Initially set to auto mode. (See
+ * media_router.CastMode documentation for details on auto mode.)
+ * @type {number}
*/
- startCastingButtonText_: {
- type: String,
- readOnly: true,
- value: loadTimeData.getString('startCastingButton'),
+ shownCastModeValue: {
+ type: Number,
+ value: media_router.AUTO_CAST_MODE.type,
},
/**
- * The text for the stop casting button.
- * @private {string}
+ * Sink associated with |route|.
+ * @type {?media_router.Sink}
*/
- stopCastingButtonText_: {
- type: String,
- readOnly: true,
- value: function() { return loadTimeData.getString('stopCastingButton'); },
+ sink: {
+ type: Object,
+ value: null,
},
/**
@@ -68,24 +75,74 @@ Polymer({
},
},
+ behaviors: [
+ I18nBehavior,
+ ],
+
/**
- * Fires a close-route-click event. This is called when the button to close
+ * Fires a close-route event. This is called when the button to close
* the current route is clicked.
*
* @private
*/
closeRoute_: function() {
- this.fire('close-route-click', {route: this.route});
+ this.fire('close-route', {route: this.route});
},
/**
- * Fires a start-casting-to-route-click event. This is called when the button
- * to start casting to the current route is clicked.
+ * @param {?media_router.Route|undefined} route
+ * @param {boolean} replaceRouteAvailable
+ * @return {boolean} Whether to show the button that allows casting to the
+ * current route or the current route's sink.
+ */
+ computeCastButtonHidden_: function(route, replaceRouteAvailable) {
+ return !((route && route.canJoin) || replaceRouteAvailable);
+ },
+
+ /**
+ * @param {?media_router.Route|undefined} route The current route for the
+ * route details view.
+ * @param {?media_router.Sink|undefined} sink Sink associated with |route|.
+ * @param {boolean} isAnySinkCurrentlyLaunching Whether a sink is launching
+ * now.
+ * @param {number} shownCastModeValue Currently selected cast mode value or
+ * AUTO if no value has been explicitly selected.
+ * @return {boolean} Whether the replace route function should be available
+ * when displaying |currentRoute| in the route details view. Replace route
+ * should not be available when the source that would be cast from when
+ * creating a new route would be the same as the route's current source.
+ * @private
+ */
+ computeReplaceRouteAvailable_: function(
+ route, sink, isAnySinkCurrentlyLaunching, shownCastModeValue) {
+ if (isAnySinkCurrentlyLaunching || !route || !sink) {
+ return false;
+ }
+ if (!route.currentCastMode) {
+ return true;
+ }
+ var selectedCastMode = shownCastModeValue;
+ if (selectedCastMode == media_router.CastModeType.AUTO) {
+ selectedCastMode = sink.castModes & -sink.castModes;
+ }
+ return ((selectedCastMode & sink.castModes) != 0) &&
+ (selectedCastMode != route.currentCastMode);
+ },
+
+ /**
+ * Fires a join-route-click event if the current route is joinable, otherwise
+ * it fires a replace-route-click event, which stops the current route and
+ * immediately launches a new route to the same sink. This is called when the
+ * button to start casting to the current route is clicked.
*
* @private
*/
startCastingToRoute_: function() {
- this.fire('start-casting-to-route-click', {route: this.route});
+ if (this.route.canJoin) {
+ this.fire('join-route-click', {route: this.route});
+ } else {
+ this.fire('replace-route-click', {route: this.route});
+ }
},
/**
@@ -101,8 +158,7 @@ Polymer({
this.route.description) :
'';
- if (!this.route || !this.route.customControllerPath ||
- this.isOffTheRecord) {
+ if (!this.route || !this.route.customControllerPath) {
this.isCustomControllerHidden_ = true;
return;
}
diff --git a/chromium/chrome/browser/resources/media_router/externs.js b/chromium/chrome/browser/resources/media_router/externs.js
index c81db5b89b9..577907d3b94 100644
--- a/chromium/chrome/browser/resources/media_router/externs.js
+++ b/chromium/chrome/browser/resources/media_router/externs.js
@@ -19,3 +19,47 @@ var InputDeviceCapabilities;
/** @type {?InputDeviceCapabilities} */
Event.prototype.sourceCapabilities;
+
+/**
+ * @interface
+ */
+var AnimationEffect = function() {};
+
+/**
+ * @param {Element} target
+ * @param {!Array<!Object>} frames
+ * @param {(number|Object)=} timing
+ * @constructor
+ * @implements {AnimationEffect}
+ */
+var KeyframeEffect = function(target, frames, timing) {};
+
+/**
+ * @param {!Array<!AnimationEffect>} group
+ * @constructor
+ * @implements {AnimationEffect}
+ */
+var GroupEffect = function(group) {};
+
+/**
+ * @interface
+ */
+var Animation = function() {};
+
+/**
+ * @return {undefined}
+ */
+Animation.prototype.cancel = function() {};
+
+/**
+ * @type {!Promise}
+ */
+Animation.prototype.finished;
+
+document.timeline = {};
+
+/**
+ * @param {!AnimationEffect} effect
+ * @return {!Animation}
+ */
+document.timeline.play = function(effect) {};
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 bb2d4628eaf..900284ef515 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
@@ -1,7 +1,29 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<!-- The following icons are duplicated to avoid pulling in unused icons,
+ e.g. the entire cr_elements/icons.html file. -->
+<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 name="media-router" size="24">
<svg><defs>
+ <!-- third_party/polymer/v1_0/components-chromium/iron-icons/iron-icons.html -->
+ <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g>
+ <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
+ <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g>
+ <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"></path></g>
+ <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
+ <g id="error-outline"><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g>
+ <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
+ <g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"></path></g>
+
+ <!-- third_party/polymer/v1_0/components-chromium/iron-icons/av-icons.html -->
+ <g id="web"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z"></path></g>
+
+ <!-- third_party/polymer/v1_0/components-chromium/iron-icons/hardware-icons.html -->
+ <g id="laptop"><path d="M20 18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"></path></g>
+ <g id="speaker"><path d="M17 2H7c-1.1 0-2 .9-2 2v16c0 1.1.9 1.99 2 1.99L17 22c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 2c1.1 0 2 .9 2 2s-.9 2-2 2c-1.11 0-2-.9-2-2s.89-2 2-2zm0 16c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"></path></g>
+ <g id="speaker-group"><path d="M18.2 1H9.8C8.81 1 8 1.81 8 2.8v14.4c0 .99.81 1.79 1.8 1.79l8.4.01c.99 0 1.8-.81 1.8-1.8V2.8c0-.99-.81-1.8-1.8-1.8zM14 3c1.1 0 2 .89 2 2s-.9 2-2 2-2-.89-2-2 .9-2 2-2zm0 13.5c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"></path><circle cx="14" cy="12.5" r="2.5"></circle><path d="M6 5H4v16c0 1.1.89 2 2 2h10v-2H6V5z"></path></g>
+ <g id="tv"><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>
+
+ <!-- Icons below are swapped out in branded builds. -->
<!-- copy of third_party/polymer/v1_0/components-chromium/iron-icons/hardware-icons.html hardware:tv icon -->
<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 -->
diff --git a/chromium/chrome/browser/resources/media_router/media_router.css b/chromium/chrome/browser/resources/media_router/media_router.css
index f0fffb5b19b..db8b9c05c05 100644
--- a/chromium/chrome/browser/resources/media_router/media_router.css
+++ b/chromium/chrome/browser/resources/media_router/media_router.css
@@ -9,7 +9,6 @@ body {
}
#media-router-container {
- -webkit-margin-start: 1px;
background-color: white;
box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14),
0 1px 8px 0 rgba(0, 0, 0, 0.12),
@@ -17,5 +16,5 @@ body {
display: flex;
flex-direction: column;
margin-bottom: 1px;
- width: calc(100% - 2px);
+ width: calc(100% - 1px);
}
diff --git a/chromium/chrome/browser/resources/media_router/media_router.js b/chromium/chrome/browser/resources/media_router/media_router.js
index 916a427fe6a..afcee95142e 100644
--- a/chromium/chrome/browser/resources/media_router/media_router.js
+++ b/chromium/chrome/browser/resources/media_router/media_router.js
@@ -20,7 +20,9 @@ cr.define('media_router', function() {
* router content, such as the media sink and media route lists.
*/
function initialize() {
- media_router.browserApi.requestInitialData();
+ // For non-Mac platforms, request data immediately after initialization.
+ if (!cr.isMac)
+ onRequestInitialData();
container = /** @type {!MediaRouterContainerElement} */
($('media-router-container'));
@@ -34,9 +36,10 @@ cr.define('media_router', function() {
container.addEventListener('back-click', onNavigateToSinkList);
container.addEventListener('cast-mode-selected', onCastModeSelected);
container.addEventListener('close-dialog', onCloseDialog);
- container.addEventListener('close-route-click', onCloseRouteClick);
+ container.addEventListener('close-route', onCloseRoute);
container.addEventListener('create-route', onCreateRoute);
container.addEventListener('issue-action-click', onIssueActionClick);
+ container.addEventListener('join-route-click', onJoinRouteClick);
container.addEventListener('navigate-sink-list-to-details',
onNavigateToDetails);
container.addEventListener('navigate-to-cast-mode-list',
@@ -51,15 +54,35 @@ cr.define('media_router', function() {
container.addEventListener('report-sink-count', onSinkCountReported);
container.addEventListener('report-resolved-route',
onReportRouteCreationOutcome);
+ container.addEventListener('request-initial-data',
+ onRequestInitialData);
+ container.addEventListener('search-sinks-and-create-route',
+ onSearchSinksAndCreateRoute);
container.addEventListener('show-initial-state', onShowInitialState);
container.addEventListener('sink-click', onSinkClick);
- container.addEventListener('start-casting-to-route-click',
- onStartCastingToRouteClick);
window.addEventListener('blur', onWindowBlur);
}
/**
+ * Requests that the Media Router searches for a sink with criteria
+ * |event.detail.name|.
+ * @param {!Event} event
+ * Parameters in |event|.detail:
+ * id - id of the pseudo sink generating the request.
+ * name - sink search criteria.
+ * domain - user's current domain.
+ * selectedCastMode - type of cast mode selected by the user.
+ */
+ function onSearchSinksAndCreateRoute(event) {
+ /** @type {{id: string, domain: string, name: string,
+ * selectedCastMode: number}} */
+ var detail = event.detail;
+ media_router.browserApi.searchSinksAndCreateRoute(
+ detail.id, detail.name, detail.domain, detail.selectedCastMode);
+ }
+
+ /**
* Reports the selected cast mode.
* Called when the user selects a cast mode from the picker.
*
@@ -190,7 +213,7 @@ cr.define('media_router', function() {
* Parameters in |event|.detail:
* route - The route to close.
*/
- function onCloseRouteClick(event) {
+ function onCloseRoute(event) {
/** @type {{route: !media_router.Route}} */
var detail = event.detail;
media_router.browserApi.closeRoute(detail.route);
@@ -198,13 +221,14 @@ cr.define('media_router', function() {
/**
* Starts casting to an existing route.
- * Called when the user requests to start casting to a media route.
+ * Called when the user requests to start casting to a media route that is
+ * joinable.
*
* @param {!Event} event
* Parameters in |event|.detail:
* route - The route to connect to if possible.
*/
- function onStartCastingToRouteClick(event) {
+ function onJoinRouteClick(event) {
/** @type {{route: !media_router.Route}} */
var detail = event.detail;
media_router.browserApi.joinRoute(detail.route);
@@ -270,6 +294,13 @@ cr.define('media_router', function() {
}
/**
+ * Requests for initial data to load into the dialog.
+ */
+ function onRequestInitialData() {
+ media_router.browserApi.requestInitialData();
+ }
+
+ /**
* Reports the initial state of the dialog after it is opened.
* Called after initial data is populated.
*
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 15b07e726c7..7e3897001fa 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_data.js
+++ b/chromium/chrome/browser/resources/media_router/media_router_data.js
@@ -24,10 +24,10 @@ media_router.CastModeType = {
};
/**
- * The ESC key maps to keycode '27'.
- * @const {number}
+ * The ESC key maps to KeyboardEvent.key value 'Escape'.
+ * @const {string}
*/
-media_router.KEYCODE_ESC = 27;
+media_router.KEY_ESC = 'Escape';
/**
* This corresponds to the C++ MediaRouterMetrics
@@ -50,6 +50,7 @@ media_router.MediaRouterUserAction = {
STOP_LOCAL: 2,
CLOSE: 3,
STATUS_REMOTE: 4,
+ REPLACE_LOCAL_ROUTE: 5,
};
/**
@@ -66,6 +67,14 @@ media_router.MediaRouterView = {
};
/**
+ * The minimum number of sinks to have to enable the search input strictly for
+ * filtering (i.e. the Media Router doesn't support search so the search input
+ * only filters existing sinks).
+ * @const {number}
+ */
+media_router.MINIMUM_SINKS_FOR_SEARCH = 20;
+
+/**
* This corresponds to the C++ MediaSink IconType.
* @enum {number}
*/
@@ -119,7 +128,7 @@ cr.define('media_router', function() {
* @param {string} title The issue title.
* @param {string} message The issue message.
* @param {number} defaultActionType The type of default action.
- * @param {?number} secondaryActionType The type of optional action.
+ * @param {number|undefined} secondaryActionType The type of optional action.
* @param {?string} routeId The route ID to which this issue
* pertains. If not set, this is a global issue.
* @param {boolean} isBlocking True if this issue blocks other UI.
@@ -142,7 +151,7 @@ cr.define('media_router', function() {
/** @type {number} */
this.defaultActionType = defaultActionType;
- /** @type {?number} */
+ /** @type {number|undefined} */
this.secondaryActionType = secondaryActionType;
/** @type {?string} */
@@ -189,6 +198,9 @@ cr.define('media_router', function() {
/** @type {boolean} */
this.canJoin = canJoin;
+ /** @type {number|undefined} */
+ this.currentCastMode = undefined;
+
/** @type {?string} */
this.customControllerPath = customControllerPath;
};
@@ -227,6 +239,9 @@ cr.define('media_router', function() {
/** @type {number} */
this.castModes = castModes;
+
+ /** @type {boolean} */
+ this.isPseudoSink = false;
};
diff --git a/chromium/chrome/browser/resources/media_router/media_router_ui_interface.js b/chromium/chrome/browser/resources/media_router/media_router_ui_interface.js
index 4d34d68bbef..abc8cbb2536 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_ui_interface.js
+++ b/chromium/chrome/browser/resources/media_router/media_router_ui_interface.js
@@ -27,6 +27,15 @@ cr.define('media_router.ui', function() {
}
/**
+ * Handles the search response by forwarding |sinkId| to the container.
+ *
+ * @param {string} sinkId The ID of the sink found by search.
+ */
+ function receiveSearchResult(sinkId) {
+ container.onReceiveSearchResult(sinkId);
+ }
+
+ /**
* Sets the cast mode list.
*
* @param {!Array<!media_router.CastMode>} castModeList
@@ -85,24 +94,20 @@ cr.define('media_router.ui', function() {
* sinks: !Array<!media_router.Sink>,
* showEmail: boolean,
* userEmail: string,
- * showDomain: boolean,
- * userDomain: string
+ * showDomain: boolean
* },
* routes: !Array<!media_router.Route>,
- * castModes: !Array<!media_router.CastMode>,
- * isOffTheRecord: boolean}} data
+ * castModes: !Array<!media_router.CastMode>}} data
* Parameters in data:
* deviceMissingUrl - url to be opened on "Device missing?" clicked.
* sinksAndIdentity - list of sinks to be displayed and user identity.
* routes - list of routes that are associated with the sinks.
* castModes - list of available cast modes.
- * isOffTheRecord - whether or not the browser is currently incognito.
*/
function setInitialData(data) {
container.deviceMissingUrl = data['deviceMissingUrl'];
container.castModeList = data['castModes'];
this.setSinkListAndIdentity(data['sinksAndIdentity']);
- container.isOffTheRecord = data['isOffTheRecord'];
container.routeList = data['routes'];
container.maybeShowRouteDetailsOnOpen();
media_router.browserApi.onInitialDataReceived();
@@ -134,21 +139,18 @@ cr.define('media_router.ui', function() {
* @param {{sinks: !Array<!media_router.Sink>,
* showEmail: boolean,
* userEmail: string,
- * showDomain: boolean,
- * userDomain: string,}} data
+ * showDomain: boolean}} data
* Parameters in data:
* sinks - list of sinks to be displayed.
* showEmail - true if the user email should be shown.
* userEmail - email of the user if the user is signed in.
* showDomain - true if the user domain should be shown.
- * userDomain - domain of the user if the user is signed in.
*/
function setSinkListAndIdentity(data) {
- container.allSinks = data['sinks'];
container.showDomain = data['showDomain'];
- container.userDomain = data['userDomain'];
- header.showEmail = data['showEmail'];
+ container.allSinks = data['sinks'];
header.userEmail = data['userEmail'];
+ header.showEmail = data['showEmail'];
}
/**
@@ -162,6 +164,7 @@ cr.define('media_router.ui', function() {
return {
onCreateRouteResponseReceived: onCreateRouteResponseReceived,
+ receiveSearchResult: receiveSearchResult,
setCastModeList: setCastModeList,
setElements: setElements,
setFirstRunFlowData: setFirstRunFlowData,
@@ -360,6 +363,27 @@ cr.define('media_router.browserApi', function() {
[{sinkId: sinkId, selectedCastMode: selectedCastMode}]);
}
+ /**
+ * Requests that the media router search all providers for a sink matching
+ * |searchCriteria| that can be used with the media source associated with the
+ * cast mode |selectedCastMode|. If such a sink is found, a route is also
+ * created between the sink and the media source.
+ *
+ * @param {string} sinkId Sink ID of the pseudo sink generating the request.
+ * @param {string} searchCriteria Search criteria for the route providers.
+ * @param {string} domain User's current hosted domain.
+ * @param {number} selectedCastMode The value of the cast mode to be used with
+ * the sink.
+ */
+ function searchSinksAndCreateRoute(
+ sinkId, searchCriteria, domain, selectedCastMode) {
+ chrome.send('searchSinksAndCreateRoute',
+ [{sinkId: sinkId,
+ searchCriteria: searchCriteria,
+ domain: domain,
+ selectedCastMode: selectedCastMode}]);
+ }
+
return {
acknowledgeFirstRunFlow: acknowledgeFirstRunFlow,
actOnIssue: actOnIssue,
@@ -381,5 +405,6 @@ cr.define('media_router.browserApi', function() {
reportTimeToInitialActionClose: reportTimeToInitialActionClose,
requestInitialData: requestInitialData,
requestRoute: requestRoute,
+ searchSinksAndCreateRoute: searchSinksAndCreateRoute,
};
});
diff --git a/chromium/chrome/browser/resources/net_internals/alt_svc_view.html b/chromium/chrome/browser/resources/net_internals/alt_svc_view.html
index 876725fa028..0e906fcd197 100644
--- a/chromium/chrome/browser/resources/net_internals/alt_svc_view.html
+++ b/chromium/chrome/browser/resources/net_internals/alt_svc_view.html
@@ -6,13 +6,13 @@
<table class="styled-table">
<thead>
<tr>
- <th>Host</th>
+ <th>Server</th>
<th>Alternative Service</th>
</tr>
</thead>
<tbody>
<tr jsselect="altSvcMappings">
- <td jscontent="host_port_pair"></td>
+ <td jscontent="server"></td>
<td jscontent="alternative_service"></td>
</tr>
</tbody>
diff --git a/chromium/chrome/browser/resources/net_internals/index.html b/chromium/chrome/browser/resources/net_internals/index.html
index 00b350f1ea9..309e9af16d6 100644
--- a/chromium/chrome/browser/resources/net_internals/index.html
+++ b/chromium/chrome/browser/resources/net_internals/index.html
@@ -1,4 +1,4 @@
-<!DOCTYPE HTML>
+<!DOCTYPE HTML>
<html>
<!--
Copyright (c) 2012 The Chromium Authors. All rights reserved.
@@ -25,6 +25,9 @@ found in the LICENSE file.
<body id=import-view-drop-target>
<include src="top_bar_view.html">
+ <div id="tab-list">
+ </div>
+
<div id=main-tab-contents>
<include src="proxy_view.html">
<include src="dns_view.html">
diff --git a/chromium/chrome/browser/resources/net_internals/log_util.js b/chromium/chrome/browser/resources/net_internals/log_util.js
index 2ca415e0a4f..54a060713be 100644
--- a/chromium/chrome/browser/resources/net_internals/log_util.js
+++ b/chromium/chrome/browser/resources/net_internals/log_util.js
@@ -259,7 +259,7 @@ log_util = (function() {
errorString += 'Caught error while calling onLoadLogFinish: ' +
error + '\n\n';
}
- tabSwitcher.showMenuItem(tabId, showView);
+ tabSwitcher.showTabLink(tabId, showView);
}
return errorString + 'Log loaded.';
diff --git a/chromium/chrome/browser/resources/net_internals/main.css b/chromium/chrome/browser/resources/net_internals/main.css
index b8a005c0c30..a96a7f1a143 100644
--- a/chromium/chrome/browser/resources/net_internals/main.css
+++ b/chromium/chrome/browser/resources/net_internals/main.css
@@ -76,6 +76,34 @@ table.styled-table,
padding-right: 4px;
}
+#tab-list {
+ border-right: 1px solid rgb(170,170,170);
+ display: inline-block;
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding: 0;
+}
+
+#tab-list a {
+ display: inline-block;
+ font-size: 16px;
+ margin: 0;
+ padding: 2px 10px;
+ text-decoration: none;
+ white-space: nowrap;
+ width: 100%;
+}
+
+#tab-list a,
+#tab-list a:visited {
+ color: rgb(140,140,140);
+}
+
+#tab-list .selected,
+#tab-list a:hover {
+ color: black;
+}
+
.styled-table th {
background: rgb(224,236,255);
}
diff --git a/chromium/chrome/browser/resources/net_internals/main.js b/chromium/chrome/browser/resources/net_internals/main.js
index 0034a981d73..33d62934561 100644
--- a/chromium/chrome/browser/resources/net_internals/main.js
+++ b/chromium/chrome/browser/resources/net_internals/main.js
@@ -155,9 +155,7 @@ var MainView = (function() {
this.tabIdToHash_ = {};
this.hashToTabId_ = {};
- this.tabSwitcher_ = new TabSwitcherView(
- $(TopBarView.TAB_DROPDOWN_MENU_ID),
- this.onTabSwitched_.bind(this));
+ this.tabSwitcher_ = new TabSwitcherView(this.onTabSwitched_.bind(this));
// Helper function to add a tab given the class for a view singleton.
var addTab = function(viewClass) {
@@ -174,7 +172,7 @@ var MainView = (function() {
throw Error('Tab hashes must start with a #');
}
- this.tabSwitcher_.addTab(tabId, view, tabName);
+ this.tabSwitcher_.addTab(tabId, view, tabName, tabHash);
this.tabIdToHash_[tabId] = tabHash;
this.hashToTabId_[tabHash] = tabId;
}.bind(this);
@@ -201,7 +199,7 @@ var MainView = (function() {
addTab(PrerenderView);
addTab(CrosView);
- this.tabSwitcher_.showMenuItem(CrosView.TAB_ID, cr.isChromeOS);
+ this.tabSwitcher_.showTabLink(CrosView.TAB_ID, cr.isChromeOS);
},
/**
diff --git a/chromium/chrome/browser/resources/net_internals/status_view.html b/chromium/chrome/browser/resources/net_internals/status_view.html
index 021b103c47e..ba28840aeb1 100644
--- a/chromium/chrome/browser/resources/net_internals/status_view.html
+++ b/chromium/chrome/browser/resources/net_internals/status_view.html
@@ -5,7 +5,7 @@ found in the LICENSE file.
-->
<!-- Status bar at top of screen when in capture mode. -->
-<div id=capture-status-view style="display:none">
+<div id=capture-status-view>
<span style='-webkit-flex-grow: 1'>
<a href='#capture' class=capture-status-view-link>capturing</a>
<a href='#events' class=capture-status-view-link>events
diff --git a/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js b/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js
index 9abdc87b5aa..fadc3d7af04 100644
--- a/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js
+++ b/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js
@@ -17,27 +17,31 @@ var TabSwitcherView = (function() {
// We inherit from View.
var superClass = View;
+ var TAB_LIST_ID = 'tab-list';
+
/**
* @constructor
*
- * @param {DOMSelectNode} dropdownMenu The menu for switching between tabs.
- * The TabSwitcherView will attach an onchange event to
- * the dropdown menu, and control the selected index.
* @param {?Function} opt_onTabSwitched Optional callback to run when the
* active tab changes. Called as
* opt_onTabSwitched(oldTabId, newTabId).
*/
- function TabSwitcherView(dropdownMenu, opt_onTabSwitched) {
+ function TabSwitcherView(opt_onTabSwitched) {
assertFirstConstructorCall(TabSwitcherView);
this.tabIdToView_ = {};
+ this.tabIdToLink_ = {};
+ // Ordered list of views.
+ this.viewList_ = [];
this.activeTabId_ = null;
- this.dropdownMenu_ = dropdownMenu;
- this.dropdownMenu_.onchange = this.onMenuSelectionChanged_.bind(this);
-
this.onTabSwitched_ = opt_onTabSwitched;
+ // The ideal width of the tab list. If width is reduced below this, the
+ // tab list will be shrunk, but it will be returned to this width once it
+ // can be.
+ this.tabListWidth_ = $(TAB_LIST_ID).offsetWidth;
+
superClass.call(this);
}
@@ -52,10 +56,22 @@ var TabSwitcherView = (function() {
setGeometry: function(left, top, width, height) {
superClass.prototype.setGeometry.call(this, left, top, width, height);
- // Position each of the tabs content areas.
+ var tabListNode = $(TAB_LIST_ID);
+
+ // Set position of the tab list. Can't use DivView because DivView sets
+ // a fixed width at creation time, and need to set the width of the tab
+ // list only after its been populated.
+ var tabListWidth = this.tabListWidth_;
+ if (tabListWidth > width)
+ tabListWidth = width;
+ tabListNode.style.position = 'absolute';
+ setNodePosition(tabListNode, left, top, tabListWidth, height);
+
+ // Position each of the tab's content areas.
for (var tabId in this.tabIdToView_) {
var view = this.tabIdToView_[tabId];
- view.setGeometry(left, top, width, height);
+ view.setGeometry(left + tabListWidth, top, width - tabListWidth,
+ height);
}
},
@@ -69,46 +85,43 @@ var TabSwitcherView = (function() {
// ---------------------------------------------
/**
- * Adds a new tab (initially hidden).
+ * Adds a new tab (initially hidden). To ensure correct tab list sizing,
+ * may only be called before first layout.
*
* @param {string} tabId The ID to refer to the tab by.
* @param {!View} view The tab's actual contents.
* @param {string} name The name for the menu item that selects the tab.
*/
- addTab: function(tabId, view, name) {
+ addTab: function(tabId, view, name, hash) {
if (!tabId) {
throw Error('Must specify a non-false tabId');
}
this.tabIdToView_[tabId] = view;
+ this.viewList_.push(view);
+
+ var node = addNodeWithText($(TAB_LIST_ID), 'a', name);
+ node.href = hash;
+ this.tabIdToLink_[tabId] = node;
+ addNode($(TAB_LIST_ID), 'br');
// Tab content views start off hidden.
view.show(false);
- // Add it to the dropdown menu.
- var menuItem = addNode(this.dropdownMenu_, 'option');
- menuItem.value = tabId;
- menuItem.textContent = name;
+ this.tabListWidth_ = $(TAB_LIST_ID).offsetWidth;
},
- showMenuItem: function(tabId, isVisible) {
+ showTabLink: function(tabId, isVisible) {
var wasActive = this.activeTabId_ == tabId;
- // Hide the menuitem from the list. Note it needs to be 'disabled' to
- // prevent it being selectable from keyboard.
- var menuitem = this.getMenuItemNode_(tabId);
- setNodeDisplay(menuitem, isVisible);
- menuitem.disabled = !isVisible;
+ setNodeDisplay(this.tabIdToLink_[tabId], isVisible);
if (wasActive && !isVisible) {
- // If the active tab is being hidden in the dropdown menu, then
- // switch to the first tab which is still visible.
- for (var i = 0; i < this.dropdownMenu_.options.length; ++i) {
- var option = this.dropdownMenu_.options[i];
- if (option.style.display != 'none') {
+ // If the link for active tab is being hidden, then switch to the first
+ // tab which is still visible.
+ for (var view in this.viewList_) {
+ if (view.isVisible())
this.switchToTab(option.value);
- break;
- }
}
}
},
@@ -145,32 +158,19 @@ var TabSwitcherView = (function() {
var oldTabId = this.activeTabId_;
this.activeTabId_ = tabId;
- this.dropdownMenu_.value = tabId;
-
- // Hide the previously visible tab contents.
- if (oldTabId)
+ if (oldTabId) {
+ this.tabIdToLink_[oldTabId].classList.remove('selected');
+ // Hide the previously visible tab contents.
this.getTabView(oldTabId).show(false);
+ }
+
+ this.tabIdToLink_[tabId].classList.add('selected');
newView.show(this.isVisible());
if (this.onTabSwitched_)
this.onTabSwitched_(oldTabId, tabId);
},
-
- getMenuItemNode_: function(tabId) {
- for (var i = 0; i < this.dropdownMenu_.options.length; ++i) {
- var option = this.dropdownMenu_.options[i];
- if (option.value == tabId) {
- return option;
- }
- }
- return null;
- },
-
- onMenuSelectionChanged_: function(event) {
- var tabId = this.dropdownMenu_.value;
- this.switchToTab(tabId);
- },
};
return TabSwitcherView;
diff --git a/chromium/chrome/browser/resources/net_internals/top_bar_view.html b/chromium/chrome/browser/resources/net_internals/top_bar_view.html
index 35e9a084838..5698ad7dd15 100644
--- a/chromium/chrome/browser/resources/net_internals/top_bar_view.html
+++ b/chromium/chrome/browser/resources/net_internals/top_bar_view.html
@@ -8,43 +8,6 @@ found in the LICENSE file.
<style>
-/**
- * This SELECT dropdown is styled so the dropdown arrow is hidden. This is
- * necessary because it looks bad on Windows. Instead, an arrow is added
- * manually by overlaying U+25BC over the dropdown and making it un-clickable.
- **/
-#top-bar-view-tab-selecter {
- -webkit-appearance: none;
- background: white;
- border-radius: 6px;
- border: 1px solid #aaa;
- font-size: 13px;
- height: 25px;
- outline: none;
- padding: 0 18px 2px 0.5em;
-}
-
-.top-bar-view-arrow {
- display: inline-block;
- margin-right: 10px;
- position:relative;
-}
-
-.top-bar-view-arrow::after {
- color: black;
- content: '\25bc';
- font-size: 9px;
- line-height: 23px;
- pointer-events: none;
- position: absolute;
- right: 12px;
- top: 1px;
-}
-
-#top-bar-view-tab-selecter:focus {
- box-shadow: 0 0 3px 4px rgba(255, 238, 0, 0.50);
-}
-
#top-bar-view {
-webkit-align-items: center;
border-bottom: 1px solid gray;
@@ -55,9 +18,6 @@ found in the LICENSE file.
</style>
<div id=top-bar-view>
- <span class=top-bar-view-arrow>
- <select aria-label="Tab selector" id=top-bar-view-tab-selecter></select>
- </span>
<div style="-webkit-flex-grow: 1">
<include src="status_view.html">
</div>
diff --git a/chromium/chrome/browser/resources/net_internals/top_bar_view.js b/chromium/chrome/browser/resources/net_internals/top_bar_view.js
index 6eb503a21af..095417bfe3b 100644
--- a/chromium/chrome/browser/resources/net_internals/top_bar_view.js
+++ b/chromium/chrome/browser/resources/net_internals/top_bar_view.js
@@ -32,7 +32,6 @@ var TopBarView = (function() {
}
TopBarView.BOX_ID = 'top-bar-view';
- TopBarView.TAB_DROPDOWN_MENU_ID = 'top-bar-view-tab-selecter';
cr.addSingletonGetter(TopBarView);
diff --git a/chromium/chrome/browser/resources/ntp4/incognito_and_guest_tab.css b/chromium/chrome/browser/resources/ntp4/incognito_and_guest_tab.css
index 567f7192f41..c8728977164 100644
--- a/chromium/chrome/browser/resources/ntp4/incognito_and_guest_tab.css
+++ b/chromium/chrome/browser/resources/ntp4/incognito_and_guest_tab.css
@@ -11,7 +11,7 @@ body {
h1 {
font-size: 200%;
- font-weight: 300;
+ font-weight: 400;
margin-bottom: .77em;
}
diff --git a/chromium/chrome/browser/resources/options/browser_options.html b/chromium/chrome/browser/resources/options/browser_options.html
index 7f73b07bea4..84b37586b79 100644
--- a/chromium/chrome/browser/resources/options/browser_options.html
+++ b/chromium/chrome/browser/resources/options/browser_options.html
@@ -519,11 +519,18 @@
<section id="bluetooth-devices" hidden>
<h3 i18n-content="bluetooth"></h3>
<div id="bluetooth-options-div">
- <div class="checkbox">
+ <div class="checkbox controlled-setting-with-label">
<label>
<input type="checkbox" id="enable-bluetooth"
metric="Options_BluetoothEnabled">
- <span i18n-content="enableBluetooth">
+ <span>
+ <span i18n-content="enableBluetooth"></span>
+ <span id="bluetooth-controlled-setting-indicator"
+ class="controlled-setting-indicator"
+ pref="cros.device.allow_bluetooth"
+ hidden="true">
+ </span>
+ </span>
</label>
</div>
<div class="settings-list bluetooth-device-list" hidden>
@@ -968,6 +975,19 @@
</label>
</div>
</div>
+ <div class="option-name" id="accessibility_mono_audio">
+ <div class="checkbox controlled-setting-with-label">
+ <label>
+ <input pref="settings.a11y.mono_audio" type="checkbox"
+ metric="Options_AccessibilityMonoAudio">
+ <span>
+ <span i18n-content="accessibilityMonoAudio"></span>
+ <span class="controlled-setting-indicator"
+ pref="settings.a11y.mono_audio"></span>
+ </span>
+ </label>
+ </div>
+ </div>
<div id="experimental-accessibility-features" hidden>
<div class="option-name">
<div class="checkbox controlled-setting-with-label">
diff --git a/chromium/chrome/browser/resources/options/browser_options.js b/chromium/chrome/browser/resources/options/browser_options.js
index b35d0047b71..2bc11d18080 100644
--- a/chromium/chrome/browser/resources/options/browser_options.js
+++ b/chromium/chrome/browser/resources/options/browser_options.js
@@ -2127,7 +2127,10 @@ cr.define('options', function() {
* @private
*/
onBluetoothAdapterStateChanged_: function(state) {
- if (!state || !state.available) {
+ var disallowBluetooth = !loadTimeData.getBoolean('allowBluetooth');
+ // If allowBluetooth is false, state.available will always be false, so
+ // assume Bluetooth is available but disabled by policy.
+ if (!state || (!state.available && !disallowBluetooth)) {
this.bluetoothAdapterState_ = null;
$('bluetooth-devices').hidden = true;
return;
@@ -2136,6 +2139,19 @@ cr.define('options', function() {
this.bluetoothAdapterState_ = state;
this.setBluetoothState_(state.powered);
+ var enableBluetoothEl = $('enable-bluetooth');
+ if (disallowBluetooth) {
+ enableBluetoothEl.setAttribute('pref', 'cros.device.allow_bluetooth');
+ enableBluetoothEl.setAttribute('controlled-by', 'policy');
+ enableBluetoothEl.disabled = true;
+ $('bluetooth-controlled-setting-indicator').hidden = false;
+ return;
+ }
+ enableBluetoothEl.removeAttribute('pref');
+ enableBluetoothEl.removeAttribute('controlled-by');
+ enableBluetoothEl.disabled = false;
+ $('bluetooth-controlled-setting-indicator').hidden = true;
+
// Flush the device lists.
$('bluetooth-paired-devices-list').clear();
$('bluetooth-unpaired-devices-list').clear();
diff --git a/chromium/chrome/browser/resources/options/browser_options_profile_list.js b/chromium/chrome/browser/resources/options/browser_options_profile_list.js
index 96adf2fec7b..b4d6faf8efc 100644
--- a/chromium/chrome/browser/resources/options/browser_options_profile_list.js
+++ b/chromium/chrome/browser/resources/options/browser_options_profile_list.js
@@ -50,7 +50,8 @@ cr.define('options.browser_options', function() {
var iconEl = this.ownerDocument.createElement('img');
iconEl.className = 'profile-img';
- iconEl.style.content = getProfileAvatarIcon(profileInfo.iconURL);
+ iconEl.style.content = cr.icon.getProfileAvatarIcon(
+ profileInfo.iconURL);
iconEl.alt = '';
containerEl.appendChild(iconEl);
diff --git a/chromium/chrome/browser/resources/options/browser_options_startup_page_list.js b/chromium/chrome/browser/resources/options/browser_options_startup_page_list.js
index 329c3e781ab..9fb30c9df2a 100644
--- a/chromium/chrome/browser/resources/options/browser_options_startup_page_list.js
+++ b/chromium/chrome/browser/resources/options/browser_options_startup_page_list.js
@@ -57,7 +57,8 @@ cr.define('options.browser_options', function() {
titleEl.classList.add('weakrtl');
titleEl.textContent = pageInfo.title;
if (!this.isPlaceholder) {
- titleEl.style.backgroundImage = getFaviconImageSet(pageInfo.url);
+ titleEl.style.backgroundImage = cr.icon.getFaviconImageSet(
+ pageInfo.url);
titleEl.title = pageInfo.tooltip;
}
diff --git a/chromium/chrome/browser/resources/options/compiled_resources.gyp b/chromium/chrome/browser/resources/options/compiled_resources.gyp
index ba84fb7d451..b43eb255e66 100644
--- a/chromium/chrome/browser/resources/options/compiled_resources.gyp
+++ b/chromium/chrome/browser/resources/options/compiled_resources.gyp
@@ -37,6 +37,7 @@
'../../../../ui/webui/resources/js/cr/ui/touch_handler.js',
'../../../../ui/webui/resources/js/cr/ui/tree.js',
'../../../../ui/webui/resources/js/event_tracker.js',
+ '../../../../ui/webui/resources/js/icon.js',
'../../../../ui/webui/resources/js/load_time_data.js',
'../../../../ui/webui/resources/js/parse_html_subset.js',
'../../../../ui/webui/resources/js/promise_resolver.js',
diff --git a/chromium/chrome/browser/resources/options/home_page_overlay.js b/chromium/chrome/browser/resources/options/home_page_overlay.js
index d314fa93c3b..4829d085ebb 100644
--- a/chromium/chrome/browser/resources/options/home_page_overlay.js
+++ b/chromium/chrome/browser/resources/options/home_page_overlay.js
@@ -92,7 +92,8 @@ cr.define('options', function() {
*/
updateFavicon_: function() {
var urlField = $('homepage-url-field');
- urlField.style.backgroundImage = getFaviconImageSet(urlField.value);
+ urlField.style.backgroundImage = cr.icon.getFaviconImageSet(
+ urlField.value);
},
/**
diff --git a/chromium/chrome/browser/resources/options/language_options.css b/chromium/chrome/browser/resources/options/language_options.css
index 89265c8806c..71aa0b1bc90 100644
--- a/chromium/chrome/browser/resources/options/language_options.css
+++ b/chromium/chrome/browser/resources/options/language_options.css
@@ -44,7 +44,7 @@
#language-options-languages,
#language-options-details {
border: 1px solid #ccc;
- height: 400px;
+ height: 380px;
padding: 0;
vertical-align: top;
}
@@ -91,13 +91,6 @@
margin-top: 0.65em;
}
-.language-options-ime-menu-desc {
- -webkit-margin-start: 22px;
- font-size: 80%;
- margin-top: -6px;
- padding-bottom: 2px;
-}
-
#language-options-list {
-webkit-box-flex: 1;
outline: none;
diff --git a/chromium/chrome/browser/resources/options/language_options.html b/chromium/chrome/browser/resources/options/language_options.html
index a0c774ba1be..5d4dfe4cb38 100644
--- a/chromium/chrome/browser/resources/options/language_options.html
+++ b/chromium/chrome/browser/resources/options/language_options.html
@@ -112,15 +112,10 @@
class="standalone-action-link"
i18n-content="languageDictionaryOverlayTitle"></a>
<div id="language-options-ime-menu-template" hidden>
- <div class="checkbox" >
- <label>
- <input type="checkbox" id="activate-ime-menu">
- <span i18n-content="activateImeMenu"></span>
- </label>
- </div>
- <div class="language-options-ime-menu-desc">
- <span i18n-content="activateImeMenuDesc"></span>
- </div>
+ <label>
+ <input type="checkbox" id="activate-ime-menu" class="checkbox">
+ <span i18n-content="activateImeMenu"></span>
+ </label>
</div>
</if>
<if expr="not chromeos and not is_macosx">
diff --git a/chromium/chrome/browser/resources/options/manage_profile_overlay.js b/chromium/chrome/browser/resources/options/manage_profile_overlay.js
index 851c76f18d0..43e9d5280fb 100644
--- a/chromium/chrome/browser/resources/options/manage_profile_overlay.js
+++ b/chromium/chrome/browser/resources/options/manage_profile_overlay.js
@@ -567,7 +567,7 @@ cr.define('options', function() {
$('manage-profile-overlay-delete').hidden = false;
$('manage-profile-overlay-disconnect-managed').hidden = true;
$('delete-profile-icon').style.content =
- getProfileAvatarIcon(profileInfo.iconURL);
+ cr.icon.getProfileAvatarIcon(profileInfo.iconURL);
$('delete-profile-text').textContent =
loadTimeData.getStringF('deleteProfileMessage',
elide(profileInfo.name, /* maxLength */ 50));
diff --git a/chromium/chrome/browser/resources/options/options.html b/chromium/chrome/browser/resources/options/options.html
index 6d62f0026c7..2b1b3f19a86 100644
--- a/chromium/chrome/browser/resources/options/options.html
+++ b/chromium/chrome/browser/resources/options/options.html
@@ -99,6 +99,7 @@
<script src="chrome://resources/js/cr/ui/tree.js"></script>
<script src="chrome://resources/js/cr/ui/page_manager/page_manager.js"></script>
<script src="chrome://resources/js/cr/ui/page_manager/page.js"></script>
+<script src="chrome://resources/js/icon.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/parse_html_subset.js"></script>
<script src="chrome://resources/js/util.js"></script>
diff --git a/chromium/chrome/browser/resources/options/password_manager.css b/chromium/chrome/browser/resources/options/password_manager.css
index fe210f307a8..18314ef98e8 100644
--- a/chromium/chrome/browser/resources/options/password_manager.css
+++ b/chromium/chrome/browser/resources/options/password_manager.css
@@ -25,4 +25,4 @@ html[dir=rtl] #password-search-column {
#passwords-title {
display: inline-block;
-} \ No newline at end of file
+}
diff --git a/chromium/chrome/browser/resources/options/password_manager.html b/chromium/chrome/browser/resources/options/password_manager.html
index 3e2584572b7..81ff66ba63f 100644
--- a/chromium/chrome/browser/resources/options/password_manager.html
+++ b/chromium/chrome/browser/resources/options/password_manager.html
@@ -2,38 +2,50 @@
<div class="close-button"></div>
<h1 i18n-content="passwordsPage"></h1>
<div class="content-area">
- <div id="auto-signin-block" class="checkbox" hidden>
- <label>
- <input pref="credentials_enable_autosignin" type="checkbox">
- <span i18n-content="autoSigninTitle"></span>
- </label>
- <div class="setting-extra-description">
- <span i18n-content="autoSigninDescription"></span>
+ <div class="password-manager-home">
+ <div id="auto-signin-block" class="checkbox" hidden>
+ <label>
+ <input pref="credentials_enable_autosignin" type="checkbox">
+ <span i18n-content="autoSigninTitle"></span>
+ </label>
+ <div class="setting-extra-description">
+ <span i18n-content="autoSigninDescription"></span>
+ </div>
</div>
- </div>
- <div id="password-list-headers">
- <div id="passwords-title">
- <h3 i18n-content="savedPasswordsTitle"></h3>
+ <div id="password-list-headers">
+ <div id="passwords-title">
+ <h3 i18n-content="savedPasswordsTitle"></h3>
+ </div>
+ <div id="password-search-column">
+ <input id="password-search-box" type="search"
+ i18n-values="placeholder:passwordSearchPlaceholder" incremental>
+ </div>
</div>
- <div id="password-search-column">
- <input id="password-search-box" type="search"
- i18n-values="placeholder:passwordSearchPlaceholder" incremental>
+ <list id="saved-passwords-list" class="settings-list"></list>
+ <div id="saved-passwords-list-empty-placeholder"
+ class="settings-list-empty" hidden>
+ <span i18n-content="passwordsNoPasswordsDescription"></span>
+ <a target="_blank" i18n-content="learnMore"
+ i18n-values="href:passwordManagerLearnMoreURL"></a>
+ </div>
+ <div class="action-area">
+ <div class="button-strip">
+ <button id="password-manager-import" class="password-manager-home"
+ i18n-content="passwordManagerImportPasswordButtonText" hidden>
+ </button>
+ <button id="password-manager-export" class="password-manager-home"
+ i18n-content="passwordManagerExportPasswordButtonText" hidden>
+ </button>
+ </div>
+ </div>
+ <h3 i18n-content="passwordExceptionsTitle"></h3>
+ <list id="password-exceptions-list" class="settings-list"></list>
+ <div id="password-exceptions-list-empty-placeholder" hidden
+ class="settings-list-empty">
+ <span i18n-content="passwordsNoExceptionsDescription"></span>
+ <a id="exceptions-learn-more" target="_blank" i18n-content="learnMore"
+ i18n-values="href:passwordManagerLearnMoreURL"></a>
</div>
- </div>
- <list id="saved-passwords-list" class="settings-list"></list>
- <div id="saved-passwords-list-empty-placeholder"
- class="settings-list-empty" hidden>
- <span i18n-content="passwordsNoPasswordsDescription"></span>
- <a target="_blank" i18n-content="learnMore"
- i18n-values="href:passwordManagerLearnMoreURL"></a>
- </div>
- <h3 i18n-content="passwordExceptionsTitle"></h3>
- <list id="password-exceptions-list" class="settings-list"></list>
- <div id="password-exceptions-list-empty-placeholder" hidden
- class="settings-list-empty">
- <span i18n-content="passwordsNoExceptionsDescription"></span>
- <a id="exceptions-learn-more" target="_blank" i18n-content="learnMore"
- i18n-values="href:passwordManagerLearnMoreURL"></a>
</div>
</div>
<div class="action-area">
@@ -46,7 +58,8 @@
</span>
<div class="spacer-div"></div>
<div class="button-strip">
- <button id="password-manager-confirm" i18n-content="done"></button>
+ <button id="password-manager-confirm" class="password-manager-home"
+ i18n-content="done"></button>
</div>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/options/password_manager.js b/chromium/chrome/browser/resources/options/password_manager.js
index a6ee22c8f03..0cf7d229b8f 100644
--- a/chromium/chrome/browser/resources/options/password_manager.js
+++ b/chromium/chrome/browser/resources/options/password_manager.js
@@ -66,6 +66,14 @@ cr.define('options', function() {
PageManager.closeOverlay();
};
+ $('password-manager-import').onclick = function() {
+ chrome.send('importPassword');
+ };
+
+ $('password-manager-export').onclick = function() {
+ chrome.send('exportPassword');
+ };
+
$('password-search-box').addEventListener('search',
this.handleSearchQueryChange_.bind(this));
@@ -270,6 +278,20 @@ cr.define('options', function() {
var item = this.savedPasswordsList_.getListItemByIndex(index);
item.showPassword(password);
},
+
+ /**
+ * @param {boolean} visible Whether the link should be visible.
+ * @private
+ */
+ setManageAccountLinkVisibility_: function(visible) {
+ $('manage-passwords-span').hidden = !visible;
+ },
+
+ /** @private */
+ showImportExportButton_: function() {
+ $('password-manager-import').hidden = false;
+ $('password-manager-export').hidden = false;
+ },
};
/**
@@ -277,9 +299,9 @@ cr.define('options', function() {
* @param {number} rowIndex indicating the row to remove.
*/
PasswordManager.removeSavedPassword = function(rowIndex) {
- chrome.send('removeSavedPassword', [String(rowIndex)]);
- chrome.send('coreOptionsUserMetricsAction',
- ['Options_PasswordManagerDeletePassword']);
+ chrome.send('removeSavedPassword', [String(rowIndex)]);
+ chrome.send('coreOptionsUserMetricsAction',
+ ['Options_PasswordManagerDeletePassword']);
};
/**
@@ -287,7 +309,7 @@ cr.define('options', function() {
* @param {number} rowIndex indicating the row to remove.
*/
PasswordManager.removePasswordException = function(rowIndex) {
- chrome.send('removePasswordException', [String(rowIndex)]);
+ chrome.send('removePasswordException', [String(rowIndex)]);
};
PasswordManager.requestShowPassword = function(index) {
@@ -298,7 +320,8 @@ cr.define('options', function() {
cr.makePublic(PasswordManager, [
'setSavedPasswordsList',
'setPasswordExceptionsList',
- 'showPassword'
+ 'showImportExportButton',
+ 'showPassword',
]);
// Export
diff --git a/chromium/chrome/browser/resources/options/password_manager_list.js b/chromium/chrome/browser/resources/options/password_manager_list.js
index e30894ea7f0..aa3f8eb1ed0 100644
--- a/chromium/chrome/browser/resources/options/password_manager_list.js
+++ b/chromium/chrome/browser/resources/options/password_manager_list.js
@@ -97,7 +97,7 @@ cr.define('options.passwordManager', function() {
var urlDiv = cr.doc.createElement('div');
urlDiv.className = 'favicon-cell url';
urlDiv.setAttribute('title', getTitleForPasswordOrigin(item));
- urlDiv.style.backgroundImage = getFaviconImageSet(
+ urlDiv.style.backgroundImage = cr.icon.getFaviconImageSet(
'origin/' + item.url, 16);
item.urlLink = createUrlLink(item, urlDiv);
diff --git a/chromium/chrome/browser/resources/options/profiles_icon_grid.js b/chromium/chrome/browser/resources/options/profiles_icon_grid.js
index f8e7b61d13b..6e2d17b45dc 100644
--- a/chromium/chrome/browser/resources/options/profiles_icon_grid.js
+++ b/chromium/chrome/browser/resources/options/profiles_icon_grid.js
@@ -37,7 +37,7 @@ cr.define('options', function() {
ListItem.prototype.decorate.call(this);
var imageEl = cr.doc.createElement('img');
imageEl.className = 'profile-icon';
- imageEl.style.content = getProfileAvatarIcon(this.iconURL_);
+ imageEl.style.content = cr.icon.getProfileAvatarIcon(this.iconURL_);
this.appendChild(imageEl);
this.className = 'profile-icon-grid-item';
diff --git a/chromium/chrome/browser/resources/options/search_engine_manager_engine_list.js b/chromium/chrome/browser/resources/options/search_engine_manager_engine_list.js
index 024e62f8d09..3d2f8f9854f 100644
--- a/chromium/chrome/browser/resources/options/search_engine_manager_engine_list.js
+++ b/chromium/chrome/browser/resources/options/search_engine_manager_engine_list.js
@@ -123,9 +123,11 @@ cr.define('options.search_engines', function() {
var faviconDivEl = this.ownerDocument.createElement('div');
faviconDivEl.className = 'favicon';
if (!this.isPlaceholder) {
- faviconDivEl.style.backgroundImage = imageset(
- 'chrome://favicon/size/16@scalefactorx/iconurl/' + engine.iconURL);
+ faviconDivEl.style.backgroundImage = cr.icon.getFaviconImageSet(
+ // Force default icon if no iconURL is available.
+ engine.iconURL || '');
}
+
nameColEl.appendChild(faviconDivEl);
var nameEl = this.createEditableTextCell(engine.displayName);
diff --git a/chromium/chrome/browser/resources/options/supervised_user_list.js b/chromium/chrome/browser/resources/options/supervised_user_list.js
index 2777a3659a9..40e9a1c1e74 100644
--- a/chromium/chrome/browser/resources/options/supervised_user_list.js
+++ b/chromium/chrome/browser/resources/options/supervised_user_list.js
@@ -63,7 +63,8 @@ cr.define('options.supervisedUserOptions', function() {
// Add the avatar.
var iconElement = this.ownerDocument.createElement('img');
iconElement.className = 'profile-img';
- iconElement.style.content = getProfileAvatarIcon(supervisedUser.iconURL);
+ iconElement.style.content = cr.icon.getProfileAvatarIcon(
+ supervisedUser.iconURL);
this.appendChild(iconElement);
// Add the profile name.
diff --git a/chromium/chrome/browser/resources/options/sync_setup_overlay.html b/chromium/chrome/browser/resources/options/sync_setup_overlay.html
index 161e90dc753..ab179c1a2f7 100644
--- a/chromium/chrome/browser/resources/options/sync_setup_overlay.html
+++ b/chromium/chrome/browser/resources/options/sync_setup_overlay.html
@@ -97,13 +97,6 @@
</span>
</label>
</div>
- <div id="wifi-credentials-item" class="sync-type-checkbox checkbox">
- <label>
- <input id="wifi-credentials-checkbox" type="checkbox">
- <span i18n-content="wifiCredentials" il8n-values="title:wifiCredentials">
- </span>
- </label>
- </div>
</div>
</div>
<div id="payments-integration-setting-area" class="checkbox">
diff --git a/chromium/chrome/browser/resources/options/sync_setup_overlay.js b/chromium/chrome/browser/resources/options/sync_setup_overlay.js
index 84d12edbff4..f9d2524f2f7 100644
--- a/chromium/chrome/browser/resources/options/sync_setup_overlay.js
+++ b/chromium/chrome/browser/resources/options/sync_setup_overlay.js
@@ -31,7 +31,6 @@ cr.exportPath('options');
* preferencesSynced: boolean,
* showPassphrase: boolean,
* syncAllDataTypes: boolean,
- * syncNothing: boolean,
* tabsEnforced: boolean,
* tabsRegistered: boolean,
* tabsSynced: boolean,
@@ -41,9 +40,7 @@ cr.exportPath('options');
* typedUrlsEnforced: boolean,
* typedUrlsRegistered: boolean,
* typedUrlsSynced: boolean,
- * usePassphrase: boolean,
- * wifiCredentialsEnforced: (boolean|undefined),
- * wifiCredentialsSynced: (boolean|undefined)}}
+ * usePassphrase: boolean}}
*/
var SyncConfig;
@@ -55,7 +52,6 @@ var SyncConfig;
options.DataTypeSelection = {
SYNC_EVERYTHING: 0,
CHOOSE_WHAT_TO_SYNC: 1,
- SYNC_NOTHING: 2
};
cr.define('options', function() {
@@ -339,12 +335,9 @@ cr.define('options', function() {
// sync_setup_handler.cc:GetConfiguration().
var syncAll = $('sync-select-datatypes').selectedIndex ==
options.DataTypeSelection.SYNC_EVERYTHING;
- var syncNothing = $('sync-select-datatypes').selectedIndex ==
- options.DataTypeSelection.SYNC_NOTHING;
var autofillSynced = syncAll || $('autofill-checkbox').checked;
var result = JSON.stringify({
'syncAllDataTypes': syncAll,
- 'syncNothing': syncNothing,
'bookmarksSynced': syncAll || $('bookmarks-checkbox').checked,
'preferencesSynced': syncAll || $('preferences-checkbox').checked,
'themesSynced': syncAll || $('themes-checkbox').checked,
@@ -354,8 +347,6 @@ cr.define('options', function() {
'typedUrlsSynced': syncAll || $('typed-urls-checkbox').checked,
'appsSynced': syncAll || $('apps-checkbox').checked,
'tabsSynced': syncAll || $('tabs-checkbox').checked,
- 'wifiCredentialsSynced':
- syncAll || $('wifi-credentials-checkbox').checked,
'paymentsIntegrationEnabled': syncAll ||
(autofillSynced && $('payments-integration-checkbox').checked),
'encryptAllData': encryptAllData,
@@ -481,16 +472,6 @@ cr.define('options', function() {
} else {
$('tabs-item').hidden = true;
}
- if (args.wifiCredentialsRegistered) {
- $('wifi-credentials-checkbox').checked = args.wifiCredentialsSynced;
- this.dataTypeBoxesChecked_['wifi-credentials-checkbox'] =
- args.wifiCredentialsSynced;
- this.dataTypeBoxesDisabled_['wifi-credentials-checkbox'] =
- args.wifiCredentialsEnforced;
- $('wifi-credentials-item').hidden = false;
- } else {
- $('wifi-credentials-item').hidden = true;
- }
$('choose-data-types-body').onchange =
this.handleDataTypeChange_.bind(this);
@@ -553,20 +534,15 @@ cr.define('options', function() {
// between its drop-down menu items as follows:
// "Sync everything": Show encryption and passphrase sections, and disable
// and check all data type checkboxes.
- // "Sync nothing": Hide encryption and passphrase sections, and disable
- // and uncheck all data type checkboxes.
// "Choose what to sync": Show encryption and passphrase sections, enable
// data type checkboxes, and restore their checked state to the last time
// the "Choose what to sync" was selected while the dialog was still up.
datatypeSelect.onchange = function() {
- if (this.selectedIndex == options.DataTypeSelection.SYNC_NOTHING) {
- self.showSyncNothingPage_();
+ self.showCustomizePage_(self.syncConfigureArgs_, this.selectedIndex);
+ if (this.selectedIndex == options.DataTypeSelection.SYNC_EVERYTHING) {
+ self.checkAllDataTypeCheckboxes_(true);
} else {
- self.showCustomizePage_(self.syncConfigureArgs_, this.selectedIndex);
- if (this.selectedIndex == options.DataTypeSelection.SYNC_EVERYTHING)
- self.checkAllDataTypeCheckboxes_(true);
- else
- self.restoreDataTypeCheckboxes_();
+ self.restoreDataTypeCheckboxes_();
}
};
@@ -631,31 +607,6 @@ cr.define('options', function() {
},
/**
- * Reveals the UI for when the user chooses not to sync any data types.
- * This happens when the user signs in and selects "Sync nothing" in the
- * advanced sync settings dialog.
- * @private
- */
- showSyncNothingPage_: function() {
- // Reset the selection to 'Sync nothing'.
- $('sync-select-datatypes').selectedIndex =
- options.DataTypeSelection.SYNC_NOTHING;
-
- // Uncheck and disable the individual data type checkboxes.
- this.checkAllDataTypeCheckboxes_(false);
- this.setDataTypeCheckboxesEnabled_(false);
-
- // Hide the encryption section.
- $('customize-sync-encryption-new').hidden = true;
- $('personalize-google-services').hidden = true;
- $('sync-custom-passphrase-container').hidden = true;
- $('sync-existing-passphrase-container').hidden = true;
-
- // Hide the "use default settings" link.
- $('use-default-link').hidden = true;
- },
-
- /**
* Reveals the UI for entering a custom passphrase during initial setup.
* This happens if the user has previously enabled a custom passphrase on a
* different machine.
diff --git a/chromium/chrome/browser/resources/pdf/elements/icons.html b/chromium/chrome/browser/resources/pdf/elements/icons.html
new file mode 100644
index 00000000000..3442301b929
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/elements/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="pdf">
+ <svg>
+ <defs>
+ <!--
+ 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="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g>
+ <g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"></path></g>
+ <g id="bookmark-border"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g>
+ <g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"></path></g>
+ <g id="remove"><path d="M19 13H5v-2h14v2z"></path></g>
+ <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>
+ </defs>
+ </svg>
+</iron-iconset-svg>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html
index 008eef63037..8195f0ebb1c 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.html
@@ -1,13 +1,14 @@
<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/paper-styles.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<dom-module id="viewer-bookmark" attributes="bookmark">
<link rel="import" type="css" href="viewer-bookmark.css">
<template>
<div id="item" on-click="onClick">
<paper-ripple></paper-ripple>
- <paper-icon-button id="expand" icon="chevron-right"
+ <paper-icon-button id="expand" icon="cr:chevron-right"
on-click="toggleChildren">
</paper-icon-button>
<span id="title" tabindex="0">{{bookmark.title}}</span>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html
index dfe225d2c53..63024e07bb9 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html
@@ -1,13 +1,13 @@
<link rel="import" href="chrome://resources/polymer/v1_0/polymer/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/iron-icons/image-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/neon-animation/animations/slide-up-animation.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/transform-animation.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.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-progress/paper-progress.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toolbar/paper-toolbar.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="../icons.html">
<link rel="import" href="../viewer-bookmarks-content/viewer-bookmarks-content.html">
<link rel="import" href="../viewer-page-selector/viewer-page-selector.html">
<link rel="import" href="../viewer-toolbar-dropdown/viewer-toolbar-dropdown.html">
@@ -30,25 +30,25 @@
</div>
<div id="buttons" class="invisible">
- <paper-icon-button id="rotate-right" icon="image:rotate-right"
+ <paper-icon-button id="rotate-right" icon="pdf:rotate-right"
on-click="rotateRight"
i18n-values="aria-label:tooltipRotateCW;title:tooltipRotateCW">
</paper-icon-button>
- <paper-icon-button id="download" icon="file-download"
+ <paper-icon-button id="download" icon="cr:file-download"
on-click="download"
i18n-values="aria-label:tooltipDownload;title:tooltipDownload">
</paper-icon-button>
- <paper-icon-button id="print" icon="print"
+ <paper-icon-button id="print" icon="cr:print"
on-click="print"
i18n-values="aria-label:tooltipPrint;title:tooltipPrint">
</paper-icon-button>
<viewer-toolbar-dropdown id="bookmarks"
hidden$="[[!bookmarks.length]]"
- open-icon="bookmark"
- closed-icon="bookmark-border"
+ open-icon="pdf:bookmark"
+ closed-icon="pdf:bookmark-border"
i18n-values="header:bookmarks">
<viewer-bookmarks-content bookmarks="{{bookmarks}}">
</viewer-bookmarks-content>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
index d07bfc8209d..a2c9359f0d1 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html
@@ -2,6 +2,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-material/paper-material.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<dom-module id="viewer-toolbar-dropdown">
<link rel="import" type="css" href="../shared-icon-style.css">
@@ -11,7 +12,7 @@
<paper-icon-button id="main-icon" icon="[[dropdownIcon]]"
aria-label="{{header}}" title="{{header}}">
</paper-icon-button>
- <iron-icon icon="arrow-drop-down" id="arrow"></iron-icon>
+ <iron-icon icon="cr:arrow-drop-down" id="arrow"></iron-icon>
</div>
<div id="container">
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html
index fbc51b550d6..a1dfb54c129 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html
@@ -1,5 +1,4 @@
<link rel="import" href="chrome://resources/polymer/v1_0/polymer/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-fab/paper-fab.html">
<dom-module id="viewer-zoom-button">
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html
index b1ee0d994f8..94dcd3beccd 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="../icons.html">
<link rel="import" href="viewer-zoom-button.html">
<dom-module id="viewer-zoom-toolbar">
@@ -7,12 +8,12 @@
<template>
<div id="zoom-buttons">
- <viewer-zoom-button id="fit-button" icons="fullscreen-exit fullscreen"
- on-fabclick="fitToggle" delay="100">
+ <viewer-zoom-button id="fit-button" on-fabclick="fitToggle" delay="100"
+ icons="pdf:fullscreen-exit cr:fullscreen">
</viewer-zoom-button>
- <viewer-zoom-button id="zoom-in-button" icons="add"
+ <viewer-zoom-button id="zoom-in-button" icons="pdf:add"
on-fabclick="zoomIn" delay="50"></viewer-zoom-button>
- <viewer-zoom-button id="zoom-out-button" icons="remove"
+ <viewer-zoom-button id="zoom-out-button" icons="pdf:remove"
on-fabclick="zoomOut" delay="0"></viewer-zoom-button>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
index 62d3421fe8a..f61d0768b4b 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": 14,
+ "x-version": 15,
"google-talk": {
"mime_types": [
],
@@ -80,9 +80,9 @@
],
"versions": [
{
- "version": "21.0.0.242",
+ "version": "22.0.0.192",
"status": "up_to_date",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb16-15.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb16-18.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 eaee4e7c5dc..e430c4d3e89 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": 20,
+ "x-version": 21,
"google-talk": {
"mime_types": [
],
@@ -115,9 +115,9 @@
],
"versions": [
{
- "version": "21.0.0.242",
+ "version": "22.0.0.192",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb16-15.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb16-18.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 e5e91cd106c..42329d653de 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": 29,
+ "x-version": 30,
"google-talk": {
"mime_types": [
],
@@ -137,9 +137,9 @@
],
"versions": [
{
- "version": "21.0.0.242",
+ "version": "22.0.0.192",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb16-15.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb16-18.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/plugins.js b/chromium/chrome/browser/resources/plugins.js
index 3301f2f8525..19b21195729 100644
--- a/chromium/chrome/browser/resources/plugins.js
+++ b/chromium/chrome/browser/resources/plugins.js
@@ -287,17 +287,16 @@ function initializeProxies() {
var serviceProvider = modules[4];
browserProxy = connection.bindHandleToProxy(
- serviceProvider.connectToService(
- pluginsMojom.PluginsHandlerMojo.name),
- pluginsMojom.PluginsHandlerMojo);
+ serviceProvider.connectToService(pluginsMojom.PluginsPageHandler.name),
+ pluginsMojom.PluginsPageHandler);
// Connect pipe handle to JS code.
var pipe = core.createMessagePipe();
pluginsPageStub = connection.bindHandleToStub(
- pipe.handle0, pluginsMojom.PluginsPageMojo);
+ pipe.handle0, pluginsMojom.PluginsPage);
pageProxy = {
- __proto__: pluginsMojom.PluginsPageMojo.stubClass.prototype,
+ __proto__: pluginsMojom.PluginsPage.stubClass.prototype,
onPluginsUpdated: function(plugins) {
returnPluginsData({plugins: plugins});
},
diff --git a/chromium/chrome/browser/resources/popular_sites_internals.html b/chromium/chrome/browser/resources/popular_sites_internals.html
index 97b3a311fea..66313dab560 100644
--- a/chromium/chrome/browser/resources/popular_sites_internals.html
+++ b/chromium/chrome/browser/resources/popular_sites_internals.html
@@ -32,16 +32,16 @@ found in the LICENSE file.
<td class="value"><input id="url-input" type="text"></td>
</tr>
<tr>
- <td class="detail">Country</td>
- <td class="value"><input id="country-input" type="text"></td>
+ <td class="detail">Override Country</td>
+ <td class="value"><input id="override-country" type="text"></td>
</tr>
<tr>
- <td class="detail">Version</td>
- <td class="value"><input id="version-input" type="text"></td>
+ <td class="detail">Override Version</td>
+ <td class="value"><input id="override-version" type="text"></td>
</tr>
<tr>
<td class="detail">
- <input id="submit-download" type="submit" value="Download">
+ <input id="submit-update" type="submit" value="Update">
</td>
<td id="download-result" class="value"></td>
</tr>
diff --git a/chromium/chrome/browser/resources/popular_sites_internals.js b/chromium/chrome/browser/resources/popular_sites_internals.js
index 96f470d1302..e4f9db0b61d 100644
--- a/chromium/chrome/browser/resources/popular_sites_internals.js
+++ b/chromium/chrome/browser/resources/popular_sites_internals.js
@@ -6,15 +6,15 @@ cr.define('chrome.popular_sites_internals', function() {
'use strict';
function initialize() {
- function submitDownload(event) {
+ function submitUpdate(event) {
$('download-result').textContent = '';
- chrome.send('download', [$('url-input').value,
- $('country-input').value,
- $('version-input').value]);
+ chrome.send('update', [$('url-input').value,
+ $('override-country').value,
+ $('override-version').value]);
event.preventDefault();
}
- $('submit-download').addEventListener('click', submitDownload);
+ $('submit-update').addEventListener('click', submitUpdate);
function viewJson(event) {
$('json-value').textContent = '';
@@ -27,6 +27,11 @@ cr.define('chrome.popular_sites_internals', function() {
chrome.send('registerForEvents');
}
+ function receiveOverrides(country, version) {
+ $('override-country').value = country;
+ $('override-version').value = version;
+ }
+
function receiveDownloadResult(result) {
$('download-result').textContent = result;
}
@@ -44,6 +49,7 @@ cr.define('chrome.popular_sites_internals', function() {
// Return an object with all of the exports.
return {
initialize: initialize,
+ receiveOverrides: receiveOverrides,
receiveDownloadResult: receiveDownloadResult,
receiveSites: receiveSites,
receiveJson: receiveJson,
diff --git a/chromium/chrome/browser/resources/safe_browsing/BUILD.gn b/chromium/chrome/browser/resources/safe_browsing/BUILD.gn
new file mode 100644
index 00000000000..679335803db
--- /dev/null
+++ b/chromium/chrome/browser/resources/safe_browsing/BUILD.gn
@@ -0,0 +1,62 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generate the binary proto form of "file_types" from the ascii proto.
+action("make_file_types_protobuf") {
+ script = "gen_file_type_proto.py"
+
+ # The output goes in $target_gen_dir since that's where
+ # chrome/browser/browser_resources.grd will look for it.
+
+ input_filename = "download_file_types.asciipb"
+ output_filename = "$target_gen_dir/download_file_types.pb"
+ python_path_root = "$root_build_dir/pyproto"
+ python_path_safe_browsing = "$python_path_root/chrome/common/safe_browsing"
+
+ # Pick an architecture to generate for. These string match those
+ # in the python script.
+ if (is_android) {
+ target_arch = "android"
+ } else if (is_chromeos) {
+ target_arch = "chromeos"
+ } else if (is_win) {
+ target_arch = "win"
+ } else if (is_mac) {
+ target_arch = "mac"
+ } else if (is_linux) {
+ target_arch = "linux"
+ } else {
+ # This will cause the script to fail.
+ target_arch = "unknown_target_arch"
+ }
+
+ inputs = [
+ script,
+ input_filename,
+ ]
+
+ # This script requires the generated python proto code
+ deps = [
+ "//chrome/common/safe_browsing:proto",
+ "//third_party/protobuf:py_proto",
+ ]
+
+ outputs = [
+ output_filename,
+ ]
+
+ args = [
+ "-w",
+ "-t",
+ target_arch,
+ "-i",
+ rebase_path(input_filename, root_build_dir),
+ "-o",
+ rebase_path(output_filename, root_build_dir),
+ "-p",
+ rebase_path(python_path_root, root_build_dir),
+ "-p",
+ rebase_path(python_path_safe_browsing, root_build_dir),
+ ]
+}
diff --git a/chromium/chrome/browser/resources/safe_browsing/OWNERS b/chromium/chrome/browser/resources/safe_browsing/OWNERS
new file mode 100644
index 00000000000..6ce5418948c
--- /dev/null
+++ b/chromium/chrome/browser/resources/safe_browsing/OWNERS
@@ -0,0 +1,2 @@
+asanka@chromium.org
+nparker@chromium.org
diff --git a/chromium/chrome/browser/resources/safe_browsing/README.md b/chromium/chrome/browser/resources/safe_browsing/README.md
new file mode 100644
index 00000000000..503b0169f7d
--- /dev/null
+++ b/chromium/chrome/browser/resources/safe_browsing/README.md
@@ -0,0 +1,105 @@
+# Behavior of Download File Types in Chrome
+
+This describes how to adjust file-type download behavior in
+Chrome including interactions with Safe Browsing. The metadata described
+here, and stored in `download_file_types.asciipb`, will be both baked into
+Chrome released and pushable to Chrome between releases. http://crbug.com/596555
+
+Rendered version of this file: https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/resources/safe_browsing/README.md
+
+
+## Procedure for adding a new type
+ * Edit `download_file_types.asciipb`, edit `download_stats.cc` (necessary
+ until it gets replaced), and update `histograms.xml`
+ * Get it reviewed, submit.
+ * Push via component update (PROCEDURE TBD)
+
+## Guidelines for a DownloadFileType entry:
+See `download_file_types.proto` for all fields.
+
+ * `extension`: (required) Value must be unique within the config. It should be
+ lowercase ASCII and not contain a dot. If there _is_ a duplicate,
+ first one wins. Only the `default_file_type` should leave this unset.
+
+ * `uma_value`: (required) must be unique and match one in the
+ `SBClientDownloadExtensions` enum in `histograms.xml`.
+
+ * `is_archive`: `True` if this filetype is a container for other files.
+ Leave it unset for `false`.
+
+ * `ping_setting`: (required). This controls what sort of ping is sent
+ to Safe Browsing and if a verdict is checked before the user can
+ access the file.
+
+ * `SAMPLED_PING`: Don't send a full Safe Browsing ping, but
+ send a no-PII "light-ping" for a random sample of SBER users.
+ This should be the default for unknown types. The verdict won't
+ be used.
+ * `NO_PING`: Don’t send any pings. This file is whitelisted. All
+ NOT_DANGEROUS files should normally use this.
+ * `FULL_PING`: Send full pings and use the verdict. All dangerous
+ file should use this.
+
+ * `platform_settings`: (repeated) Zero or more settings to differentiate
+ behavior by platform. Keep them sorted by platform. At build time,
+ this list will be filtered to contain exactly one setting by chosing
+ as follows before writing out the binary proto.
+
+ 1. If there's an entry matching the built platform,
+ that will be preferred. Otherwise,
+
+ 2. If there's a "PLATFORM_ANY" (i.e. `platform` is not set),
+ that will be used. Otherwise,
+
+ 3. The `default_file_type`'s settings will be filled in.
+
+ * `platform_settings.danger_level`: (required)
+ * `NOT_DANGEROUS`: Safe to download and open, even if the download
+ was accidental.
+ * `DANGEROUS`: Always warn the user that this file may harm their
+ computer. We let them continue or discard the file. If Safe
+ Browsing returns a SAFE verdict, we still warn the user.
+ * `ALLOW_ON_USER_GESTURE`: Warn the user normally but skip the warning
+ if there was a user gesture or the user visited this site before
+ midnight last night (i.e. is a repeat visit). If Safe Browsing
+ returns a SAFE verdict for this file, it won't show a warning.
+
+ * `platform_settings.auto_open_hint`: (required).
+ * `ALLOW_AUTO_OPEN`: File type can be opened automatically if the user
+ selected that option from the download tray on a previous download
+ of this type.
+ * `DISALLOW_AUTO_OPEN`: Never let the file automatically open.
+ Files that should be disallowed from auto-opening include those that
+ execute arbitrary or harmful code with user privileges, or change
+ configuration of the system to cause harmful behavior immediately
+ or at some time in the future. We *do* allow auto-open for files
+ that upon opening sufficiently warn the user about the fact that it
+ was downloaded from the internet and can do damage. **Note**:
+ Some file types (e.g.: .local and .manifest) aren't dangerous
+ to open. However, their presence on the file system may cause
+ potentially dangerous changes in behavior for other programs. We
+ allow automatically opening these file types, but always warn when
+ they are downloaded.
+
+ * TODO(nparker): Support this: `platform_settings.unpacker`:
+ optional. Specifies which archive unpacker internal to Chrome
+ should be used. If potentially dangerous file types are found,
+ Chrome will send a full-ping for the entire file. Otherwise, it'll
+ follow the ping settings. Can be one of UNPACKER_ZIP or UNPACKER_DMG.
+
+## Guidelines for the top level DownloadFileTypeConfig entry:
+ * `version_id`: Must be increased (+1) every time the file is checked in.
+ Will be logged to UMA.
+
+ * `sampled_ping_probability`: For what fraction of extended-reporting
+ users' downloads with unknown extensions (or
+ ping_setting=SAMPLED_PING) should we send light-pings? [0.0 .. 1.0]
+
+ * `file_types`: The big list of all known file types. Keep them
+ sorted by extension.
+
+ * `default_file_type`: Settings used if a downloaded file is not in
+ the above list. `extension` is ignored, but other settings are used.
+ The ping_setting should be SAMPLED_PING for all platforms. Only the
+ first platform_setting is used.
+
diff --git a/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
new file mode 100644
index 00000000000..a87180fa611
--- /dev/null
+++ b/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -0,0 +1,2514 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# See README.md before editing this file.
+# Keep sorted by extension within logical groupings where possible.
+
+##
+## Top level settings
+##
+version_id: 1
+sampled_ping_probability: 0.0
+default_file_type {
+ uma_value: 18
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+
+##
+## General cross-platform file types
+##
+
+# Files that are not dangerous but for which we want to track via UMA.
+file_types {
+ extension: "bin"
+ uma_value: 159
+ ping_setting: SAMPLED_PING
+}
+file_types {
+ # PDFs are opened internally, so they are considered safe.
+ extension: "pdf"
+ uma_value: 14
+ ping_setting: SAMPLED_PING
+}
+file_types {
+ extension: "rtf"
+ uma_value: 244
+ ping_setting: SAMPLED_PING
+}
+
+# Flash files downloaded locally can sometimes access the local filesystem
+file_types {
+ extension: "swf"
+ uma_value: 68
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "spl"
+ uma_value: 69
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Chrome extensions should be obtained through the web store. Allowed to
+# open automatically because Chrome displays a prompt prior to
+# installation.
+file_types {
+ extension: "crx"
+ uma_value: 19
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+
+# Archive file types. Not inherently dangerous, but could contain dangerous
+# files.
+file_types {
+ extension: "001"
+ uma_value: 171
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "7z"
+ uma_value: 52
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "ace"
+ uma_value: 172
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "arc"
+ uma_value: 173
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "arj"
+ uma_value: 58
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "b64"
+ uma_value: 174
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "balz"
+ uma_value: 175
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "bhx"
+ uma_value: 176
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "bz"
+ uma_value: 177
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "bz2"
+ uma_value: 56
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "bzip2"
+ uma_value: 148
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "cab"
+ uma_value: 2
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "cpio"
+ uma_value: 64
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "fat"
+ uma_value: 178
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "gz"
+ uma_value: 54
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "gzip"
+ uma_value: 149
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "hfs"
+ uma_value: 179
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "hqx"
+ uma_value: 180
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "iso"
+ uma_value: 181
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "lha"
+ uma_value: 60
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "lpaq1"
+ uma_value: 182
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "lpaq5"
+ uma_value: 183
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "lpaq8"
+ uma_value: 184
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "lzh"
+ uma_value: 59
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "lzma"
+ uma_value: 63
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "mim"
+ uma_value: 185
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "ntfs"
+ uma_value: 186
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "paq8f"
+ uma_value: 187
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "paq8jd"
+ uma_value: 188
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "paq8l"
+ uma_value: 189
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "paq8o"
+ uma_value: 190
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "pea"
+ uma_value: 191
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "quad"
+ uma_value: 194
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r00"
+ uma_value: 195
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r01"
+ uma_value: 196
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r02"
+ uma_value: 197
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r03"
+ uma_value: 198
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r04"
+ uma_value: 199
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r05"
+ uma_value: 200
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r06"
+ uma_value: 201
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r07"
+ uma_value: 202
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r08"
+ uma_value: 203
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r09"
+ uma_value: 204
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r10"
+ uma_value: 205
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r11"
+ uma_value: 206
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r12"
+ uma_value: 207
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r13"
+ uma_value: 208
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r14"
+ uma_value: 209
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r15"
+ uma_value: 210
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r16"
+ uma_value: 211
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r17"
+ uma_value: 212
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r18"
+ uma_value: 213
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r19"
+ uma_value: 214
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r20"
+ uma_value: 215
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r21"
+ uma_value: 216
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r22"
+ uma_value: 217
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r23"
+ uma_value: 218
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r24"
+ uma_value: 219
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r25"
+ uma_value: 220
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r26"
+ uma_value: 221
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r27"
+ uma_value: 222
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r28"
+ uma_value: 223
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "r29"
+ uma_value: 224
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "rar"
+ uma_value: 8
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "squashfs"
+ uma_value: 226
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "swm"
+ uma_value: 227
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "tar"
+ uma_value: 57
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "taz"
+ uma_value: 150
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "tbz"
+ uma_value: 151
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "tbz2"
+ uma_value: 152
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "tgz"
+ uma_value: 55
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "tpz"
+ uma_value: 228
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "txz"
+ uma_value: 229
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "tz"
+ uma_value: 230
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "udf"
+ uma_value: 231
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "uu"
+ uma_value: 232
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "uue"
+ uma_value: 233
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "vhd"
+ uma_value: 234
+ is_archive: true
+ ping_setting: FULL_PING
+
+}
+file_types {
+ # Opens in IE, drops MOTW
+ extension: "vhdx"
+ uma_value: 245
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "vmdk"
+ uma_value: 235
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "wim"
+ uma_value: 61
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "wrc"
+ uma_value: 236
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "xar"
+ uma_value: 237
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "xxe"
+ uma_value: 238
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "xz"
+ uma_value: 53
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "z"
+ uma_value: 62
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "zip"
+ uma_value: 7
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "zipx"
+ uma_value: 239
+ is_archive: true
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "zpaq"
+ uma_value: 240
+ is_archive: true
+ ping_setting: FULL_PING
+}
+
+# Java
+file_types {
+ extension: "class"
+ uma_value: 13
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_CHROME_OS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "jar"
+ uma_value: 12
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_CHROME_OS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "jnlp"
+ uma_value: 128
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_CHROME_OS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+
+# Cross-platform scripting languages (non-shell)
+file_types {
+ extension: "pl"
+ uma_value: 129
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "py"
+ uma_value: 130
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "pyc"
+ uma_value: 131
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "pyw"
+ uma_value: 132
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "rb"
+ uma_value: 133
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Other cross-platform files
+file_types {
+ # Extensible Firmware Interface executable
+ extension: "efi"
+ uma_value: 146
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "torrent"
+ uma_value: 23
+ ping_setting: FULL_PING
+}
+
+##
+## Windows-specific files
+##
+## Some file descriptions are based on
+## https://support.office.com/article/Blocked-attachments-in-Outlook-3811cddc-17c3-4279-a30c-060ba0207372
+
+# Windows installer files
+file_types {
+ extension: "msi"
+ uma_value: 1
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "msp"
+ uma_value: 33
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "mst"
+ uma_value: 34
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Microsoft Access files
+file_types {
+ # Project extension [MS Access]
+ extension: "ade"
+ uma_value: 98
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Project [MS Access]
+ extension: "adp"
+ uma_value: 99
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Module shortcut [MS Access]
+ extension: "mad"
+ uma_value: 100
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Form shortcut [MS Access]
+ extension: "maf"
+ uma_value: 101
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Diagram Shortcut [MS Access]
+ extension: "mag"
+ uma_value: 102
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Macro Shortcut [MS Access]
+ extension: "mam"
+ uma_value: 103
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Query Shortcut [MS Access]
+ extension: "maq"
+ uma_value: 104
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Report Shortcut [MS Access]
+ extension: "mar"
+ uma_value: 105
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Stored Procedures [MS Access]
+ extension: "mas"
+ uma_value: 106
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Table Shortcut [MS Access]
+ extension: "mat"
+ uma_value: 107
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # View Shortcut [MS Access]
+ extension: "mav"
+ uma_value: 108
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Data Access Page [MS Access]
+ extension: "maw"
+ uma_value: 109
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Access Add-In [MS Access]
+ extension: "mda"
+ uma_value: 110
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Database [MS Access]
+ extension: "mdb"
+ uma_value: 111
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Database [MS Access]
+ extension: "mde"
+ uma_value: 112
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Add-In Data [MS Access]
+ extension: "mdt"
+ uma_value: 113
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Workgroup Information [MS Access]
+ extension: "mdw"
+ uma_value: 114
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Wizard Template [MS Access]
+ extension: "mdz"
+ uma_value: 115
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # ActiveX Control
+ extension: "ocx"
+ uma_value: 90
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Office Profile Settings File.
+ extension: "ops"
+ uma_value: 91
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Portable Application Installer File.
+ extension: "paf"
+ uma_value: 166
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Visual Test
+ extension: "pcd"
+ uma_value: 92
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Program Information File. Originally intended to configure execution
+ # environment for legacy DOS files. They aren't meant to contain
+ # executable code. But Windows may execute a PIF file that is sniffed as a
+ # PE file.
+ extension: "pif"
+ uma_value: 10
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Developer Studio Build Log.
+ extension: "plg"
+ uma_value: 93
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows System File.
+ extension: "prf"
+ uma_value: 94
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Program File
+ extension: "prg"
+ uma_value: 95
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Exchange Address Book File. Microsoft Outlook Personal Folder
+ # File.
+ extension: "pst"
+ uma_value: 96
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+
+# Extensions that will open in IE even when chrome is set as default browser.
+file_types {
+ extension: "partial"
+ uma_value: 153
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "xrm-ms"
+ uma_value: 156
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "rels"
+ uma_value: 241
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "svg"
+ uma_value: 154
+ ping_setting: FULL_PING
+}
+file_types {
+ extension: "xml"
+ uma_value: 155
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "xsl"
+ uma_value: 157
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Windows PowerShell files
+file_types {
+ extension: "ps1"
+ uma_value: 43
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "ps1xml"
+ uma_value: 44
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "ps2"
+ uma_value: 45
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "ps2xml"
+ uma_value: 46
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "psc1"
+ uma_value: 47
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "psc2"
+ uma_value: 48
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Internet Shortcuts (new since IE9). Both .url and .website are .ini
+# files that describe a shortcut that points to a URL. They can point at
+# anything. Dropping a download of this type and opening it automatically
+# can in effect sidestep origin restrictions etc.
+file_types {
+ extension: "url"
+ uma_value: 25
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "website"
+ uma_value: 24
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# VBScript files. May open with Windows Script Host and execute with
+# user privileges.
+file_types {
+ # JavaScript file. May open using Windows Script Host with user level
+ # privileges.
+ extension: "js"
+ uma_value: 28
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # JScript encoded script file. Usually produced by running Microsoft Script
+ # Encoder over a .js file.
+ # See https://msdn.microsoft.com/library/d14c8zsc.aspx
+ extension: "jse"
+ uma_value: 29
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "vb"
+ uma_value: 15
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "vbe"
+ uma_value: 26
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "vbs"
+ uma_value: 27
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Some sites claim .vbscript is a valid extension for vbs files.
+ extension: "vbscript"
+ uma_value: 169
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Windows script Host related
+file_types {
+ extension: "ws"
+ uma_value: 123
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "wsc"
+ uma_value: 124
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "wsf"
+ uma_value: 51
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "wsh"
+ uma_value: 125
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Microsoft Shell files
+file_types {
+ extension: "msh"
+ uma_value: 37
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "msh1"
+ uma_value: 38
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "msh2"
+ uma_value: 40
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "mshxml"
+ uma_value: 42
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "msh1xml"
+ uma_value: 39
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "msh2xml"
+ uma_value: 41
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Other Windows files
+file_types {
+ extension: "ad"
+ uma_value: 262
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Executable Application
+ extension: "app"
+ uma_value: 66
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft ClickOnce depolyment manifest. By default, opens with
+ # dfshim.dll which should prompt the user before running untrusted code.
+ extension: "application"
+ uma_value: 70
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # ClickOnce application reference. Basically a .lnk for ClickOnce apps.
+ extension: "appref-ms"
+ uma_value: 144
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Active Server Pages source file.
+ extension: "asp"
+ uma_value: 71
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Advanced Stream Redirector. Contains a playlist of media files.
+ extension: "asx"
+ uma_value: 72
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Visual Basic source file. Opens by default in an editor
+ extension: "bas"
+ uma_value: 35
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Command Script
+ extension: "bat"
+ uma_value: 6
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "cfg"
+ uma_value: 73
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows Compiled HTML Help files.
+ extension: "chi"
+ uma_value: 74
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows Compiled HTML Help files.
+ extension: "chm"
+ uma_value: 75
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Command script
+ extension: "cmd"
+ uma_value: 65
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows legacy executable
+ extension: "com"
+ uma_value: 11
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Control panel tool. Executable
+ extension: "cpl"
+ uma_value: 76
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Signed certificate file.
+ extension: "crt"
+ uma_value: 97
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows executable. It can gain control of an executable launched from the
+ # same directory, so it can do bad things without ever being clicked on.
+ extension: "dll"
+ uma_value: 9
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows executable
+ extension: "drv"
+ uma_value: 5
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Opens in Outlook. Not common, but could be exploited (CVE-2015-6172)
+ extension: "eml"
+ uma_value: 243
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Executable
+ extension: "exe"
+ uma_value: 0
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Font file, uses Portable Executable or New Executable format. Not
+ # supposed to contain executable code.
+ extension: "fon"
+ uma_value: 147
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft FoxPro Compiled Source.
+ extension: "fxp"
+ uma_value: 77
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows Sidebar Gadget (Vista & Win 7). ZIP archive containing html + js.
+ # Deprecated by Microsoft. Can run arbitrary code with user privileges.
+ # (https://technet.microsoft.com/library/security/2719662)
+ extension: "gadget"
+ uma_value: 145
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # MSProgramGroup (?)
+ extension: "grp"
+ uma_value: 17
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows legacy help file format.
+ extension: "hlp"
+ uma_value: 78
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # HTML Application. Executes as a fully trusted application.
+ extension: "hta"
+ uma_value: 36
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Hypertext Template File. See https://support.microsoft.com/kb/181689.
+ extension: "htt"
+ uma_value: 79
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Device installation information.
+ extension: "inf"
+ uma_value: 80
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Generic configuration file.
+ extension: "ini"
+ uma_value: 81
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft IIS Internet Communication Settings.
+ extension: "ins"
+ uma_value: 82
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # InstallShield Compiled Script
+ extension: "inx"
+ uma_value: 160
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # InstallShield Uninstaller Script
+ extension: "isu"
+ uma_value: 162
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft IIS Internet Service Provider Settings.
+ extension: "isp"
+ uma_value: 83
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows Task Scheduler Job file. No handler is registered by default, so
+ # this is probably normally not dangerous unless saved into the task
+ # scheduler directory.
+ extension: "job"
+ uma_value: 163
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Shortcuts. May open anything.
+ extension: "lnk"
+ uma_value: 84
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # .local files affect DLL search path for .exe file with same base name.
+ extension: "local"
+ uma_value: 85
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # While being a generic name, having a .manifest file with the same
+ # basename as .exe file (foo.exe + foo.exe.manifest) changes the DLL search
+ # order for the .exe file. Downloading this kind of file to the users'
+ # download directory is almost always the wrong thing to do.
+ extension: "manifest"
+ uma_value: 86
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Media Attachment Unit.
+ extension: "mau"
+ uma_value: 87
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Multipart HTML
+ extension: "mht"
+ uma_value: 30
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Multipart HTML
+ extension: "mhtml"
+ uma_value: 31
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "mmc"
+ uma_value: 88
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "mof"
+ uma_value: 89
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Management Console Snap-in. Contains executable code.
+ extension: "msc"
+ uma_value: 32
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Opens in Outlook. Not common, but could be exploited (CVE-2015-6172)
+ extension: "msg"
+ uma_value: 242
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Registry file. Opening may cause registry settings to change. Users still
+ # need to click through a prompt. So we could consider relaxing the
+ # DISALLOW_AUTO_OPEN restriction.
+ extension: "reg"
+ uma_value: 16
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Registry Script Windows.
+ extension: "rgs"
+ uma_value: 167
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Windows Explorer Command.
+ # See https://support.microsoft.com/kb/190355 for an example
+ extension: "scf"
+ uma_value: 49
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Windows Screen Saver.
+ extension: "scr"
+ uma_value: 4
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Windows Script Component. Microsoft FoxPro Screen.
+ # A Script Component is a COM component created using script.
+ # See https://msdn.microsoft.com/library/aa233148.aspx for an
+ # example.
+ extension: "sct"
+ uma_value: 50
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Windows Vista Index Search Data, for local file system.
+ # Used to find files landed surreptitiously w/o UI.
+ extension: "search-ms"
+ uma_value: 246
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Windows Shortcut into a document.
+ # See https://support.microsoft.com/kb/212344
+ extension: "shb"
+ uma_value: 116
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Shell Scrap Object File.
+ extension: "shs"
+ uma_value: 117
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # System executable. Windows tries hard to prevent you from opening these
+ # types of files.
+ extension: "sys"
+ uma_value: 3
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # U3 Smart Application.
+ extension: "u3p"
+ uma_value: 168
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "vsd"
+ uma_value: 118
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Visual Studio Binary-based Macro Project.
+ extension: "vsmacros"
+ uma_value: 119
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "vss"
+ uma_value: 120
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "vst"
+ uma_value: 121
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Visio Workspace
+ extension: "vsw"
+ uma_value: 122
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # XAML Browser Application.
+ extension: "xbap"
+ uma_value: 126
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: DANGEROUS
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Microsoft Exchange Public Folder Shortcut
+ extension: "xnk"
+ uma_value: 127
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+
+##
+## MacOS-specific files
+##
+
+# Executable files on MacOS
+file_types {
+ extension: "cdr"
+ uma_value: 251
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "dart"
+ uma_value: 254
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "dc42"
+ uma_value: 255
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "diskcopy42"
+ uma_value: 256
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "dmg"
+ uma_value: 21
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "dmgpart"
+ uma_value: 252
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "dvdr"
+ uma_value: 253
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "img"
+ uma_value: 247
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "imgpart"
+ uma_value: 257
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "ndif"
+ uma_value: 258
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "smi"
+ uma_value: 248
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "sparsebundle"
+ uma_value: 249
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "sparseimage"
+ uma_value: 250
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "toast"
+ uma_value: 260
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "udif"
+ uma_value: 259
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Other MacOS files
+file_types {
+ # Automator action
+ extension: "action"
+ uma_value: 158
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "command"
+ uma_value: 140
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Automator workflow
+ extension: "workflow"
+ uma_value: 170
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+
+##
+## Linux-specific files
+##
+
+## Package management formats (non-windows)
+file_types {
+ extension: "pkg"
+ uma_value: 22
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_MAC
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "deb"
+ uma_value: 141
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "pet"
+ uma_value: 192
+ is_archive: true
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "pup"
+ uma_value: 193
+ is_archive: true
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "rpm"
+ uma_value: 142
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "slp"
+ uma_value: 225
+ is_archive: true
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # "Common" executable file extension for Linux. There's not really much
+ # reason to block since they require execute bit to actually run.
+ # Included for UMA histograms.
+ extension: "out"
+ uma_value: 164
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "run"
+ uma_value: 261
+ ping_setting: SAMPLED_PING
+ platform_settings {
+ platform: PLATFORM_LINUX
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+
+# Non-windows Shell Languages
+file_types {
+ extension: "bash"
+ uma_value: 134
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "csh"
+ uma_value: 135
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "ksh"
+ uma_value: 136
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "sh"
+ uma_value: 137
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "shar"
+ uma_value: 138
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ extension: "tcsh"
+ uma_value: 139
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+ platform_settings {
+ platform: PLATFORM_WINDOWS
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+
+##
+## Android-specific files
+##
+file_types {
+ extension: "dex"
+ uma_value: 143
+ ping_setting: FULL_PING
+ platform_settings {
+ platform: PLATFORM_ANDROID
+ danger_level: ALLOW_ON_USER_GESTURE
+ auto_open_hint: DISALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Android download manager checks APKs
+ extension: "apk"
+ uma_value: 20
+ ping_setting: FULL_PING
+}
diff --git a/chromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py b/chromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py
new file mode 100755
index 00000000000..1e55f9a10c1
--- /dev/null
+++ b/chromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py
@@ -0,0 +1,200 @@
+#!/usr/bin/python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+ Convert the ASCII download_file_types.asciipb proto into a binary resource.
+
+ We generate a separate variant of the binary proto for each platform,
+ each which contains only the values that platform needs.
+"""
+
+import optparse
+import re
+import subprocess
+import sys
+
+
+def ImportProtoModules(paths):
+ """Import the protobuf modiles we need. |paths| is list of import paths"""
+ for path in paths:
+ # Put the path to our proto libraries in front, so that we don't use system
+ # protobuf.
+ sys.path.insert(1, path)
+
+ import download_file_types_pb2 as config_pb2
+ globals()['config_pb2'] = config_pb2
+
+ import google.protobuf.text_format as text_format
+ globals()['text_format'] = text_format
+
+
+# Map of platforms for which we can generate binary protos.
+# This must be run after the custom imports.
+# key: type-name
+# value: proto-platform_type (int)
+def PlatformTypes():
+ return {
+ "android": config_pb2.DownloadFileType.PLATFORM_ANDROID,
+ "chromeos": config_pb2.DownloadFileType.PLATFORM_CHROME_OS,
+ "linux": config_pb2.DownloadFileType.PLATFORM_LINUX,
+ "mac": config_pb2.DownloadFileType.PLATFORM_MAC,
+ "win": config_pb2.DownloadFileType.PLATFORM_WINDOWS,
+ }
+
+
+def ValidatePb(pb):
+ """ Validate the basic values of the protobuf. The
+ file_type_policies_unittest.cc will also validate it by platform,
+ but this will catch errors earlier.
+ """
+ assert pb.version_id > 0;
+ assert pb.sampled_ping_probability >= 0.0;
+ assert pb.sampled_ping_probability <= 1.0;
+ assert len(pb.default_file_type.platform_settings) >= 1;
+ assert len(pb.file_types) > 1;
+
+
+def PrunePlatformSettings(file_type, default_settings, platform_type):
+ # Modify this file_type's platform_settings by keeping the only the
+ # best one for this platform_type. In order of preference:
+ # * Exact match to platform_type
+ # * PLATFORM_ANY entry
+ # * or copy from the default file type.
+
+ last_platform = -1
+ setting_match = None
+ for s in file_type.platform_settings:
+ # Enforce: sorted and no dups (signs of mistakes).
+ assert last_platform < s.platform, (
+ "Extension '%s' has duplicate or out of order platform: '%s'" %
+ (file_type.extension, s.platform))
+ last_platform = s.platform
+
+ # Pick the most specific match.
+ if ((s.platform == platform_type) or
+ (s.platform == config_pb2.DownloadFileType.PLATFORM_ANY and
+ setting_match is None)):
+ setting_match = s
+
+ # If platform_settings was empty, we'll fill in from the default
+ if setting_match is None:
+ assert default_settings is not None, (
+ "Missing default settings for platform %d" % platform_type)
+ setting_match = default_settings
+
+ # Now clear out the full list and replace it with 1 entry.
+ del file_type.platform_settings[:]
+ new_setting = file_type.platform_settings.add()
+ new_setting.CopyFrom(setting_match)
+ new_setting.ClearField('platform')
+
+
+def FilterPbForPlatform(full_pb, platform_type):
+ """ Return a filtered protobuf for this platform_type """
+
+ new_pb = config_pb2.DownloadFileTypeConfig();
+ new_pb.CopyFrom(full_pb)
+
+ # Ensure there's only one platform_settings for the default.
+ PrunePlatformSettings(new_pb.default_file_type, None, platform_type)
+
+ # This can be extended if we want to match weird extensions.
+ # Just no dots, non-UTF8, or uppercase chars.
+ invalid_char_re = re.compile('[^a-z0-9_-]')
+
+ # Filter platform_settings for each type.
+ uma_values_used = set()
+ extensions_used = set()
+ for file_type in new_pb.file_types:
+ assert not invalid_char_re.search(file_type.extension), (
+ "File extension '%s' contains non alpha-num-dash chars" % (
+ file_type.extension))
+ assert file_type.extension is not extensions_used, (
+ "Duplicate extension '%s'" % file_type.extension)
+ extensions_used.add(file_type.extension)
+
+ assert file_type.uma_value not in uma_values_used, (
+ "Extension '%s' reused UMA value %d." % (
+ file_type.extension, file_type.uma_value))
+ uma_values_used.add(file_type.uma_value)
+
+ # Modify file_type to include only the best match platform_setting.
+ PrunePlatformSettings(
+ file_type, new_pb.default_file_type.platform_settings[0], platform_type)
+
+ return new_pb
+
+
+def GeneratBinaryProtos(opts):
+ # Read the ASCII
+ ifile = open(opts.infile, 'r')
+ ascii_pb_str = ifile.read()
+ ifile.close()
+
+ # Parse it into a structure PB
+ pb = config_pb2.DownloadFileTypeConfig()
+ text_format.Merge(ascii_pb_str, pb)
+
+ ValidatePb(pb);
+ platform_type = PlatformTypes()[opts.type]
+ filtered_pb = FilterPbForPlatform(pb, platform_type);
+
+ # Serialize it
+ binary_pb_str = filtered_pb.SerializeToString()
+
+ # Write it to disk
+ open(opts.outfile, 'wb').write(binary_pb_str)
+
+
+def main():
+ parser = optparse.OptionParser()
+ # TODO(nparker): Remove this once the bug is fixed.
+ parser.add_option('-w', '--wrap', action="store_true", default=False,
+ help='Wrap this script in another python '
+ 'execution to disable site-packages. This is a '
+ 'fix for http://crbug.com/605592')
+ parser.add_option('-t', '--type',
+ help='The platform type. One of android, chromeos, ' +
+ 'linux, mac, win')
+ parser.add_option('-i', '--infile',
+ help='The ASCII DownloadFileType-proto file to read.')
+ parser.add_option('-o', '--outfile',
+ help='The binary file to write to.')
+ parser.add_option('-p', '--path', action="append",
+ help='Repeat this as needed. Directory(s) containing ' +
+ 'the download_file_types_pb2.py and ' +
+ 'google.protobuf.text_format modules')
+ (opts, args) = parser.parse_args()
+ if opts.infile is None or opts.outfile is None:
+ parser.print_help()
+ return 1
+
+ if opts.wrap:
+ # Run this script again with different args to the interpreter.
+ command = [sys.executable, '-S', '-s', sys.argv[0]]
+ command += ['-t', opts.type]
+ command += ['-i', opts.infile]
+ command += ['-o', opts.outfile]
+ for path in opts.path:
+ command += ['-p', path]
+ sys.exit(subprocess.call(command))
+
+ ImportProtoModules(opts.path)
+
+ if (opts.type not in PlatformTypes()):
+ print "ERROR: Unknown platform type '%s'" % opts.type
+ parser.print_help()
+ return 1
+
+ try:
+ GeneratBinaryProtos(opts)
+ except Exception as e:
+ print "ERROR: Failed to render binary version of %s:\n %s\n" % (
+ opts.infile, str(e))
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(main())
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 25ae86f239f..af67455dc5d 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html
+++ b/chromium/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -10,72 +10,73 @@
<style include="settings-shared"></style>
<if expr="chromeos">
<div class="settings-box row first">
- <span i18n-content="a11yExplanation"></span>
- <a i18n-values="href:a11yLearnMoreUrl" i18n-content="learnMore"
- target="_blank"></a>
+ <span>
+ $i18n{a11yExplanation}
+ <a href="$i18nRaw{a11yLearnMoreUrl}" target="_blank">
+ $i18n{learnMore}
+ </a>
+ </span>
</div>
<div class="settings-box block">
- <settings-checkbox i18n-values="label:optionsInMenuLabel"
+ <settings-checkbox label="$i18n{optionsInMenuLabel}"
pref="{{prefs.settings.a11y.enable_menu}}">
</settings-checkbox>
- <settings-checkbox i18n-values="label:largeMouseCursorLabel"
+ <settings-checkbox label="$i18n{largeMouseCursorLabel}"
pref="{{prefs.settings.a11y.large_cursor_enabled}}">
</settings-checkbox>
- <settings-checkbox i18n-values="label:highContrastLabel"
+ <settings-checkbox label="$i18n{highContrastLabel}"
pref="{{prefs.settings.a11y.high_contrast_enabled}}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.settings.a11y.sticky_keys_enabled}}"
- i18n-values="label:stickyKeysLabel">
+ label="$i18n{stickyKeysLabel}">
</settings-checkbox>
<settings-checkbox pref="{{prefs.settings.accessibility}}"
- i18n-values="label:chromeVoxLabel">
+ label="$i18n{chromeVoxLabel}">
</settings-checkbox>
- <settings-checkbox i18n-values="label:screenMagnifierLabel"
+ <settings-checkbox label="$i18n{screenMagnifierLabel}"
pref="{{prefs.settings.a11y.screen_magnifier}}">
</settings-checkbox>
- <settings-checkbox i18n-values="label:tapDraggingLabel"
+ <settings-checkbox label="$i18n{tapDraggingLabel}"
pref="{{prefs.settings.touchpad.enable_tap_dragging}}">
</settings-checkbox>
- <settings-checkbox i18n-values="label:clickOnStopLabel"
+ <settings-checkbox label="$i18n{clickOnStopLabel}"
pref="{{prefs.settings.a11y.autoclick}}">
</settings-checkbox>
<div class="list-item settings-checkbox-spacer">
- <div i18n-content="delayBeforeClickLabel"></div>
+ <div>$i18n{delayBeforeClickLabel}</div>
<select value="{{prefs.settings.a11y.autoclick_delay_ms::change}}">
- <option value="200" i18n-content="delayBeforeClickExtremelyShort">
- </option>
- <option value="400" i18n-content="delayBeforeClickVeryShort">
- </option>
- <option value="600" i18n-content="delayBeforeClickShort">
- </option>
- <option value="800" i18n-content="delayBeforeClickLong">
- </option>
- <option value="1000" i18n-content="delayBeforeClickVeryLong">
- </option>
+ <option value="200">$i18n{delayBeforeClickExtremelyShort}</option>
+ <option value="400">$i18n{delayBeforeClickVeryShort}</option>
+ <option value="600">$i18n{delayBeforeClickShort}</option>
+ <option value="800">$i18n{delayBeforeClickLong}</option>
+ <option value="1000">$i18n{delayBeforeClickVeryLong}</option>
</select>
</div>
<settings-checkbox pref="{{prefs.settings.a11y.virtual_keyboard}}"
- i18n-values="label:onScreenKeyboardLabel">
+ label="$i18n{onScreenKeyboardLabel}">
+ </settings-checkbox>
+ <settings-checkbox pref="{{prefs.settings.a11y.mono_audio}}"
+ label="$i18n{monoAudioLabel}">
</settings-checkbox>
<template is="dom-if" if="[[showExperimentalFeatures_]]">
<settings-checkbox pref="{{prefs.settings.a11y.caret_highlight}}"
- i18n-values="label:caretHighlightLabel">
+ label="$i18n{caretHighlightLabel}">
</settings-checkbox>
<settings-checkbox pref="{{prefs.settings.a11y.cursor_highlight}}"
- i18n-values="label:cursorHighlightLabel">
+ label="$i18n{cursorHighlightLabel}">
</settings-checkbox>
<settings-checkbox pref="{{prefs.settings.a11y.focus_highlight}}"
- i18n-values="label:focusHighlightLabel">
+ label="$i18n{focusHighlightLabel}">
</settings-checkbox>
<settings-checkbox pref="{{prefs.settings.a11y.select_to_speak}}"
- i18n-values="label:selectToSpeakLabel">
+ label="$i18n{selectToSpeakLabel}">
</settings-checkbox>
<settings-checkbox pref="{{prefs.settings.a11y.switch_access}}"
- i18n-values="label:switchAccessLabel">
+ label="$i18n{switchAccessLabel}">
</settings-checkbox>
</template>
</div>
@@ -88,8 +89,8 @@
<div class="settings-box first">
</if>
<div class="button-strip">
- <paper-button i18n-content="moreFeaturesLink" class="primary-button"
- on-tap="onMoreFeaturesTap_"></paper-button>
+ <paper-button class="primary-button"
+ on-tap="onMoreFeaturesTap_">$i18n{moreFeaturesLink}</paper-button>
</div>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.html b/chromium/chrome/browser/resources/settings/about_page/about_page.html
new file mode 100644
index 00000000000..14f8089616c
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.html
@@ -0,0 +1,76 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://md-settings/about_page/about_page_browser_proxy.html">
+<link rel="import" href="chrome://md-settings/settings_page/main_page_behavior.html">
+<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
+<link rel="import" href="chrome://md-settings/settings_page/settings_section.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.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">
+
+<if expr="chromeos">
+<link rel="import" href="chrome://md-settings/about_page/detailed_build_info.html">
+<link rel="import" href="chrome://md-settings/settings_page/settings_subpage.html">
+</if>
+
+<dom-module id="settings-about-page">
+ <link rel="import" type="css" href="chrome://md-settings/settings_page.css">
+ <template>
+ <style include="settings-shared main-page-styles">
+ span {
+ font-size: 20px;
+ margin-top: auto;
+ margin-bottom: auto;
+ }
+
+ img {
+ -webkit-margin-end: 10px;
+ }
+ </style>
+ <settings-section page-title="$i18n{aboutPageTitle}"
+ current-route="[[currentRoute]]" section="about">
+ <settings-animated-pages id="pages" current-route="{{currentRoute}}"
+ section="about">
+ <neon-animatable id="main">
+ <div class="settings-box">
+ <img id="product-logo"
+ srcset="chrome://theme/current-channel-logo@1x 1x,
+ chrome://theme/current-channel-logo@2x 2x" alt="">
+ <span>$i18n{aboutProductTitle}</span>
+ </div>
+ <div class="settings-box two-line">
+ <!-- TODO(dpapad): Implement this. -->
+ <div class="start">
+ <div>Your device is up to date</div>
+ <div class="secondary">Version Foo.bar.baz</div>
+ </div>
+ <div class="secondary-action">
+ <paper-button class="secondary-button">Check for update</paper-button>
+ </div>
+ </div>
+ <div id="help" class="settings-box two-line" on-tap="onHelpTap_">
+ $i18n{aboutGetHelpUsingChrome}
+ </div>
+<if expr="_google_chrome">
+ <div id="reportIssue" class="settings-box" on-tap="onReportIssueTap_">
+ $i18n{aboutReportAnIssue}
+ </div>
+</if>
+<if expr="chromeos">
+ <div class="settings-box" on-tap="onDetailedBuildInfoTap_">
+ <!-- TODO(dpapad): Localize string. -->
+ Detailed build info
+ </div>
+</if>
+ </neon-animatable>
+<if expr="chromeos">
+ <template is="dom-if" name="detailed-build-info">
+ <settings-subpage page-title="Detailed build information">
+ <settings-detailed-build-info></settings-detailed-build-info>
+ </settings-subpage>
+ </template>
+</if>
+ </settings-animated-pages>
+ </settings-section>
+ </template>
+ <script src="about_page.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.js b/chromium/chrome/browser/resources/settings/about_page/about_page.js
new file mode 100644
index 00000000000..44da2984db3
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.js
@@ -0,0 +1,64 @@
+// 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-about-page' contains version and OS related
+ * information.
+ */
+Polymer({
+ is: 'settings-about-page',
+
+ behaviors: [RoutableBehavior],
+
+ properties: {
+ /**
+ * The current active route.
+ */
+ currentRoute: {
+ type: Object,
+ notify: true,
+ },
+ },
+
+ /** @private {?settings.AboutPageBrowserProxy} */
+ browserProxy_: null,
+
+ /**
+ * @type {string} Selector to get the sections.
+ * TODO(michaelpg): replace duplicate docs with @override once b/24294625
+ * is fixed.
+ */
+ sectionSelector: 'settings-section',
+
+ /** @override */
+ ready: function() {
+ this.browserProxy_ = settings.AboutPageBrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ this.scroller = this.parentElement;
+ },
+
+ /** @private */
+ onHelpTap_: function() {
+ this.browserProxy_.openHelpPage();
+ },
+
+<if expr="chromeos">
+ /** @private */
+ onDetailedBuildInfoTap_: function() {
+ var animatedPages = /** @type {!SettingsAnimatedPagesElement} */ (
+ this.$.pages);
+ animatedPages.setSubpageChain(['detailed-build-info']);
+ },
+</if>
+
+<if expr="_google_chrome">
+ /** @private */
+ onReportIssueTap_: function() {
+ this.browserProxy_.openFeedbackDialog();
+ },
+</if>
+});
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.html b/chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.html
new file mode 100644
index 00000000000..0fac0e69c61
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://md-settings/about_page/about_page_browser_proxy.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js b/chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js
new file mode 100644
index 00000000000..491eddeb8be
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js
@@ -0,0 +1,168 @@
+// 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 A helper object used from the "About" section to interact with
+ * the browser.
+ */
+
+<if expr="chromeos">
+/**
+ * @typedef {{
+ * text: string,
+ * url: string,
+ * }}
+ */
+var RegulatoryInfo;
+
+/**
+ * @typedef {{
+ * arcVersion: string,
+ * osFirmware: string,
+ * osVersion: string,
+ * }}
+ */
+var VersionInfo;
+
+/**
+ * Enumeration of all possible browser channels.
+ * @enum {string}
+ */
+var BrowserChannel = {
+ BETA: 'beta-channel',
+ DEV: 'dev-channel',
+ STABLE: 'stable-channel',
+};
+</if>
+
+cr.define('settings', function() {
+ /** @interface */
+ function AboutPageBrowserProxy() {}
+
+ AboutPageBrowserProxy.prototype = {
+ /**
+ * Indicates to the browser that the page is ready.
+ */
+ pageReady: function() {},
+
+ /**
+ * Request update status from the browser. It results in one or more
+ * 'update-status-changed' WebUI events.
+ */
+ refreshUpdateStatus: function() {},
+
+ /**
+ * Relaunches the browser.
+ */
+ relaunchNow: function() {},
+
+ /** Opens the help page. */
+ openHelpPage: function() {},
+
+<if expr="_google_chrome">
+ /**
+ * Opens the feedback dialog.
+ */
+ openFeedbackDialog: function() {},
+</if>
+
+<if expr="chromeos">
+ /**
+ * Checks for available update and applies if it exists.
+ */
+ requestUpdate: function() {},
+
+ /**
+ * @param {!BrowserChannel} channel
+ * @param {boolean} isPowerwashAllowed
+ */
+ setChannel: function(channel, isPowerwashAllowed) {},
+
+ /** @return {!Promise<!BrowserChannel>} */
+ getCurrentChannel: function() {},
+
+ /** @return {!Promise<!BrowserChannel>} */
+ getTargetChannel: function() {},
+
+ /** @return {!Promise<!VersionInfo>} */
+ getVersionInfo: function() {},
+
+ /** @return {!Promise<?RegulatoryInfo>} */
+ getRegulatoryInfo: function() {},
+</if>
+ };
+
+ /**
+ * @implements {settings.AboutPageBrowserProxy}
+ * @constructor
+ */
+ function AboutPageBrowserProxyImpl() {}
+ cr.addSingletonGetter(AboutPageBrowserProxyImpl);
+
+ AboutPageBrowserProxyImpl.prototype = {
+ /** @override */
+ pageReady: function() {
+ chrome.send('aboutPageReady');
+ },
+
+ /** @override */
+ refreshUpdateStatus: function() {
+ chrome.send('refreshUpdateStatus');
+ },
+
+ /** @override */
+ relaunchNow: function() {
+ chrome.send('relaunchNow');
+ },
+
+ /** @override */
+ openHelpPage: function() {
+ chrome.send('openHelpPage');
+ },
+
+<if expr="_google_chrome">
+ /** @override */
+ openFeedbackDialog: function() {
+ chrome.send('openFeedbackDialog');
+ },
+</if>
+
+<if expr="chromeos">
+ /** @override */
+ requestUpdate: function() {
+ chrome.send('requestUpdate');
+ },
+
+ /** @override */
+ setChannel: function(channel, isPowerwashAllowed) {
+ chrome.send('setChannel', [channel, isPowerwashAllowed]);
+ },
+
+ /** @override */
+ getCurrentChannel: function() {
+ return cr.sendWithPromise('getCurrentChannel');
+ },
+
+ /** @override */
+ getTargetChannel: function() {
+ return cr.sendWithPromise('getTargetChannel');
+ },
+
+ /** @override */
+ getVersionInfo: function() {
+ return cr.sendWithPromise('getVersionInfo');
+ },
+
+ /** @override */
+ getRegulatoryInfo: function() {
+ return cr.sendWithPromise('getRegulatoryInfo');
+ }
+</if>
+ };
+
+ return {
+ AboutPageBrowserProxy: AboutPageBrowserProxy,
+ AboutPageBrowserProxyImpl: AboutPageBrowserProxyImpl,
+ };
+});
diff --git a/chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp
new file mode 100644
index 00000000000..66b049c1c86
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/compiled_resources2.gyp
@@ -0,0 +1,32 @@
+# 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': 'about_page',
+ 'dependencies': [
+ 'about_page_browser_proxy',
+ '../settings_page/compiled_resources2.gyp:main_page_behavior',
+ '../settings_page/compiled_resources2.gyp:settings_animated_pages',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'about_page_browser_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):chrome_send',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'detailed_build_info',
+ 'dependencies': [
+ 'about_page_browser_proxy',
+ '<(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
new file mode 100644
index 00000000000..136902b7dac
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html
@@ -0,0 +1,80 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://md-settings/about_page/about_page_browser_proxy.html">
+<link rel="import" href="chrome://md-settings/i18n_setup.html"
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+
+<dom-module id="settings-detailed-build-info">
+ <template>
+ <style include="settings-shared"></style>
+ <div class="settings-box two-line">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>Platform</div>
+ <div class="secondary" id="osVersion">[[versionInfo_.osVersion]]</div>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ hidden$="[[!shouldShowVersion_(versionInfo_.osFirmware)]]">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>Firmware</div>
+ <div class="secondary" id="osFirmware">[[versionInfo_.osFirmware]]</div>
+ </div>
+ </div>
+ <div class="settings-box two-line">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>Channel</div>
+ <div class="secondary">[[currentlyOnChannelText_]]</div>
+ </div>
+ <div class="secondary-action">
+ <paper-button class="secondary-button">Change channel</paper-button>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ hidden$="[[!shouldShowVersion_(versionInfo_.arcVersion)]]">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>ARC Version</div>
+ <div class="secondary" id="arcVersion">[[versionInfo_.arcVersion]]</div>
+ </div>
+ </div>
+ <div class="settings-box two-line">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>Blink</div>
+ <div class="secondary">$i18n{aboutBlinkVersion}</div>
+ </div>
+ </div>
+ <div class="settings-box two-line">
+ <div class="start">
+ <div>V8</div>
+ <div class="secondary">$i18n{aboutJsEngineVersion}</div>
+ </div>
+ </div>
+ <div class="settings-box two-line">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>User agent</div>
+ <div class="secondary">$i18n{aboutUserAgent}</div>
+ </div>
+ </div>
+ <div class="settings-box two-line">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>Command line</div>
+ <div class="secondary">$i18n{aboutCommandLine}</div>
+ </div>
+ </div>
+ <div class="settings-box two-line">
+ <div class="start">
+ <!-- TODO(dpapad): Localize string -->
+ <div>Build date</div>
+ <div class="secondary">$i18n{aboutBuildDate}</div>
+ </div>
+ </div>
+ </template>
+ <script src="detailed_build_info.js"></script>
+</dom-module>
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
new file mode 100644
index 00000000000..cb9f109aada
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.js
@@ -0,0 +1,64 @@
+// 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-detailed-build-info' contains detailed build
+ * information for ChromeOS.
+ */
+
+(function() {
+
+/**
+ * @param {!BrowserChannel} channel
+ * @return {string}
+ */
+function browserChannelToI18nId(channel) {
+ switch (channel) {
+ case BrowserChannel.BETA: return 'aboutChannelBeta';
+ case BrowserChannel.DEV: return 'aboutChannelDev';
+ case BrowserChannel.STABLE: return 'aboutChannelStable';
+ }
+
+ assertNotReached();
+}
+
+Polymer({
+ is: 'settings-detailed-build-info',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @private {!VersionInfo} */
+ versionInfo_: Object,
+
+ /** @private */
+ currentlyOnChannelText_: String,
+ },
+
+ /** @override */
+ ready: function() {
+ var browserProxy = settings.AboutPageBrowserProxyImpl.getInstance();
+ browserProxy.pageReady();
+
+ browserProxy.getVersionInfo().then(function(versionInfo) {
+ this.versionInfo_ = versionInfo;
+ }.bind(this));
+ browserProxy.getCurrentChannel().then(function(channel) {
+ this.currentlyOnChannelText_ = this.i18n(
+ 'aboutCurrentlyOnChannel',
+ this.i18n(browserChannelToI18nId(channel)));
+ }.bind(this));
+ },
+
+ /**
+ * @param {string} version
+ * @return {boolean}
+ * @private
+ */
+ shouldShowVersion_: function(version) {
+ return version.length > 0;
+ },
+});
+
+})();
diff --git a/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.html b/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.html
index 91b063fa31b..3db44b1bcc8 100644
--- a/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.html
+++ b/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.html
@@ -1,4 +1,3 @@
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://md-settings/a11y_page/a11y_page.html">
<link rel="import" href="chrome://md-settings/downloads_page/downloads_page.html">
@@ -8,6 +7,7 @@
<link rel="import" href="chrome://md-settings/reset_page/reset_page.html">
<link rel="import" href="chrome://md-settings/settings_page/main_page_behavior.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_page_visibility.html">
+<link rel="import" href="chrome://md-settings/settings_page/settings_router.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_section.html">
<link rel="import" href="chrome://md-settings/site_settings/constants.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_category.html">
@@ -27,7 +27,7 @@
<style include="main-page-styles"></style>
<if expr="chromeos">
<template is="dom-if" if="[[showPage(pageVisibility.dateTime)]]" restamp>
- <settings-section page-title="[[i18n('dateTimePageTitle')]]"
+ <settings-section page-title="$i18n{dateTimePageTitle}"
current-route="[[currentRoute]]" section="dateTime">
<settings-date-time-page prefs="{{prefs}}">
</settings-date-time-page>
@@ -35,7 +35,7 @@
</template>
</if>
<template is="dom-if" if="[[showPage(pageVisibility.privacy)]]" restamp>
- <settings-section page-title="[[i18n('privacyPageTitle')]]"
+ <settings-section page-title="$i18n{privacyPageTitle}"
current-route="[[currentRoute]]" section="privacy">
<settings-privacy-page prefs="{{prefs}}"
current-route="{{currentRoute}}">
@@ -44,7 +44,7 @@
</template>
<if expr="chromeos">
<template is="dom-if" if="[[showPage(pageVisibility.bluetooth)]]" restamp>
- <settings-section page-title="[[i18n('bluetoothPageTitle')]]"
+ <settings-section page-title="$i18n{bluetoothPageTitle}"
current-route="[[currentRoute]]" section="bluetooth">
<settings-bluetooth-page current-route="{{currentRoute}}">
</settings-bluetooth-page>
@@ -54,7 +54,7 @@
<template is="dom-if" if="[[showPage(pageVisibility.passwordsAndForms)]]"
restamp>
<settings-section
- page-title="[[i18n('passwordsAndAutofillPageTitle')]]"
+ page-title="$i18n{passwordsAndAutofillPageTitle}"
current-route="[[currentRoute]]" section="passwordsAndForms">
<settings-passwords-and-forms-page prefs="{{prefs}}"
current-route="{{currentRoute}}">
@@ -62,7 +62,7 @@
</settings-section>
</template>
<template is="dom-if" if="[[showPage(pageVisibility.languages)]]" restamp>
- <settings-section page-title="[[i18n('languagesPageTitle')]]"
+ <settings-section page-title="$i18n{languagesPageTitle}"
current-route="[[currentRoute]]" section="languages">
<settings-languages-page prefs="{{prefs}}"
current-route="{{currentRoute}}">
@@ -70,7 +70,7 @@
</settings-section>
</template>
<template is="dom-if" if="[[showPage(pageVisibility.downloads)]]" restamp>
- <settings-section page-title="[[i18n('downloadsPageTitle')]]"
+ <settings-section page-title="$i18n{downloadsPageTitle}"
current-route="[[currentRoute]]" section="downloads">
<settings-downloads-page prefs="{{prefs}}">
</settings-downloads-page>
@@ -80,21 +80,21 @@
<!-- TODO(dschuyler): Add Google Cloud Print section here. -->
<template is="dom-if" if="[[showPage(pageVisibility.a11y)]]" restamp>
- <settings-section page-title="[[i18n('a11yPageTitle')]]"
+ <settings-section page-title="$i18n{a11yPageTitle}"
current-route="[[currentRoute]]" section="a11y">
<settings-a11y-page prefs="{{prefs}}"></settings-a11y-page>
</settings-section>
</template>
<if expr="not chromeos">
<template is="dom-if" if="[[showPage(pageVisibility.system)]]" restamp>
- <settings-section page-title="[[i18n('systemPageTitle')]]"
+ <settings-section page-title="$i18n{systemPageTitle}"
current-route="[[currentRoute]]" section="system">
<settings-system-page prefs="{{prefs}}"></settings-system-page>
</settings-section>
</template>
</if>
<template is="dom-if" if="[[showPage(pageVisibility.reset)]]" restamp>
- <settings-section page-title="[[i18n('resetPageTitle')]]"
+ <settings-section page-title="$i18n{resetPageTitle}"
current-route="[[currentRoute]]" section="reset">
<settings-reset-page></settings-reset-page>
</settings-section>
diff --git a/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.js b/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.js
index 8df437730c7..b686b14ce43 100644
--- a/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.js
+++ b/chromium/chrome/browser/resources/settings/advanced_page/advanced_page.js
@@ -6,19 +6,11 @@
* @fileoverview
* 'settings-advanced-page' is the settings page containing the advanced
* settings.
- *
- * Example:
- *
- * <iron-animated-pages>
- * <settings-advanced-page prefs="{{prefs}}">
- * </settings-advanced-page>
- * ... other pages ...
- * </iron-animated-pages>
*/
Polymer({
is: 'settings-advanced-page',
- behaviors: [I18nBehavior, SettingsPageVisibility, RoutableBehavior],
+ behaviors: [SettingsPageVisibility, RoutableBehavior],
properties: {
/**
@@ -31,6 +23,7 @@ Polymer({
/**
* The current active route.
+ * @type {SettingsRoute}
*/
currentRoute: {
type: Object,
diff --git a/chromium/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp
index 5a4abab9848..d7ece91576a 100644
--- a/chromium/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/advanced_page/compiled_resources2.gyp
@@ -6,9 +6,9 @@
{
'target_name': 'advanced_page',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'../settings_page/compiled_resources2.gyp:main_page_behavior',
'../settings_page/compiled_resources2.gyp:settings_page_visibility',
+ '../settings_page/compiled_resources2.gyp:settings_router',
'../settings_page/compiled_resources2.gyp:transition_behavior',
'../system_page/compiled_resources2.gyp:system_page',
],
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.html b/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.html
new file mode 100644
index 00000000000..a624ebe2669
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="href" src="chrome://resources/html/cr.html">
+<script src="chrome://md-settings/appearance_page/appearance_browser_proxy.js"></script>
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
new file mode 100644
index 00000000000..8982f699f94
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js
@@ -0,0 +1,53 @@
+// 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', function() {
+ /** @interface */
+ function AppearanceBrowserProxy() {}
+
+ AppearanceBrowserProxy.prototype = {
+ /**
+ * @return {!Promise<boolean>} Whether the theme may be reset.
+ */
+ getResetThemeEnabled: assertNotReached,
+
+<if expr="chromeos">
+ openWallpaperManager: assertNotReached,
+</if>
+
+ resetTheme: assertNotReached,
+ };
+
+ /**
+ * @implements {settings.AppearanceBrowserProxy}
+ * @constructor
+ */
+ function AppearanceBrowserProxyImpl() {}
+
+ cr.addSingletonGetter(AppearanceBrowserProxyImpl);
+
+ AppearanceBrowserProxyImpl.prototype = {
+ /** @override */
+ getResetThemeEnabled: function() {
+ return cr.sendWithPromise('getResetThemeEnabled');
+ },
+
+<if expr="chromeos">
+ /** @override */
+ openWallpaperManager: function() {
+ chrome.send('openWallpaperManager');
+ },
+</if>
+
+ /** @override */
+ resetTheme: function() {
+ chrome.send('resetTheme');
+ },
+ };
+
+ return {
+ AppearanceBrowserProxy: AppearanceBrowserProxy,
+ AppearanceBrowserProxyImpl: AppearanceBrowserProxyImpl,
+ };
+});
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 37c4a1cfae2..58365514b21 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,38 +1,38 @@
<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/paper-slider/paper-slider.html">
<link rel="import" href="chrome://md-settings/appearance_page/fonts_browser_proxy.html">
<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html">
+<link rel="import" href="chrome://md-settings/i18n_setup.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-appearance-fonts-page">
- <link rel="import" type="css"
- href="chrome://md-settings/appearance_page/appearance_shared.css">
<template>
<style include="settings-shared"></style>
<div class="settings-box first">
<div class="start">$i18n{fontSize}</div>
- <paper-slider class="slider-labels" id="sizeSlider"
- value="{{fontSizeIndex_}}"
- max="[[fontSizeRangeLimit_]]" max-markers="5"
- immediate-value="{{immediateSizeIndex_}}" snaps>
+ <paper-slider class="always-on" id="sizeSlider"
+ value="{{fontSizeIndex_}}"
+ max="[[fontSizeRangeLimit_]]" max-markers="5"
+ immediate-value="{{immediateSizeIndex_}}" snaps>
</paper-slider>
</div>
<div class="settings-box">
<div class="start">$i18n{minimumFont}</div>
<div class="list-item" style$="[[computeStyle_(minimumFontSize_, prefs.webkit.webprefs.fonts.standard.Zyyy.value)]]">
<span>[[minimumFontSize_]]</span>:&nbsp;
- <span i18n-content="quickBrownFox"></span>
+ $i18n{quickBrownFox}
</div>
- <paper-slider class="slider-labels" id="minimumSizeSlider"
- value="{{minimumSizeIndex_}}"
- max="[[minimumFontSizeRangeLimit_]]" max-markers="5"
- immediate-value="{{immediateMinimumSizeIndex_}}" snaps>
+ <paper-slider class="always-on" id="minimumSizeSlider"
+ value="{{minimumSizeIndex_}}"
+ max="[[minimumFontSizeRangeLimit_]]" max-markers="5"
+ immediate-value="{{immediateMinimumSizeIndex_}}" snaps>
</paper-slider>
</div>
<div class="settings-box">
<div class="start">
- <h2 i18n-content="standardFont"></h2>
+ <h2>$i18n{standardFont}</h2>
<div class="list-frame">
<div class="list-item">
<settings-dropdown-menu class="start" id="standardFont"
@@ -43,10 +43,10 @@
<div class="list-item underbar"
style$="[[computeStyle_(defaultFontSize_, prefs.webkit.webprefs.fonts.standard.Zyyy.value)]]">
<span>[[defaultFontSize_]]</span>:&nbsp;
- <span i18n-content="quickBrownFox"></span>
+ $i18n{quickBrownFox}
</div>
</div>
- <h2 i18n-content="serifFont"></h2>
+ <h2>$i18n{serifFont}</h2>
<div class="list-frame">
<div class="list-item">
<settings-dropdown-menu class="start" id="serifFont"
@@ -57,10 +57,10 @@
<div class="list-item underbar"
style$="[[computeStyle_(defaultFontSize_, prefs.webkit.webprefs.fonts.serif.Zyyy.value)]]">
<span>[[defaultFontSize_]]</span>:&nbsp;
- <span i18n-content="quickBrownFox"></span>
+ $i18n{quickBrownFox}
</div>
</div>
- <h2 i18n-content="sansSerifFont"></h2>
+ <h2>$i18n{sansSerifFont}</h2>
<div class="list-frame">
<div class="list-item">
<settings-dropdown-menu class="start" id="sansSerifFont"
@@ -71,10 +71,10 @@
<div class="list-item underbar"
style$="{{computeStyle_(defaultFontSize_, prefs.webkit.webprefs.fonts.sansserif.Zyyy.value)}}">
<span>[[defaultFontSize_]]</span>:&nbsp;
- <span i18n-content="quickBrownFox"></span>
+ $i18n{quickBrownFox}
</div>
</div>
- <h2 i18n-content="fixedWidthFont"></h2>
+ <h2>$i18n{fixedWidthFont}</h2>
<div class="list-frame">
<div class="list-item">
<settings-dropdown-menu class="start" id="fixedFont"
@@ -85,22 +85,25 @@
<div class="list-item"
style$="[[computeStyle_(defaultFontSize_, prefs.webkit.webprefs.fonts.fixed.Zyyy.value)]]">
<span>[[defaultFontSize_]]</span>:&nbsp;
- <span i18n-content="quickBrownFox"></span>
+ $i18n{quickBrownFox}
</div>
</div>
</div>
</div>
<div class="settings-box">
- <div class="start" i18n-content="encoding"></div>
+ <div class="start">$i18n{encoding}</div>
<settings-dropdown-menu id="encoding"
pref="{{prefs.intl.charset_default}}"
menu-options="[[encodingOptions_]]" no-label-float>
</settings-dropdown-menu>
</div>
- <div class="settings-box two-line">
+ <div class="settings-box two-line" id="advancedButton"
+ on-tap="openAdvancedExtension_">
<div class="start">
- <div i18n-content="advancedFontSettings"></div>
- <div class="secondary" i18n-content="requiresWebStoreExtension"></div>
+ <div>$i18n{advancedFontSettings}</div>
+ <div class="secondary" id="advancedButtonSublabel">
+ [[advancedExtensionSublabel_]]
+ </div>
</div>
</div>
</template>
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 e698ece59ae..5f2c9e417f2 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
@@ -35,9 +35,18 @@
Polymer({
is: 'settings-appearance-fonts-page',
- behaviors: [I18nBehavior],
+ behaviors: [I18nBehavior, WebUIListenerBehavior],
properties: {
+ /** @private */
+ advancedExtensionInstalled_: Boolean,
+
+ /** @private */
+ advancedExtensionSublabel_: String,
+
+ /** @private */
+ advancedExtensionUrl_: String,
+
/** @private {!settings.FontsBrowserProxy} */
browserProxy_: Object,
@@ -152,6 +161,10 @@
/** @override */
ready: function() {
+ this.addWebUIListener('advanced-font-settings-installed',
+ this.setAdvancedExtensionInstalled_.bind(this));
+ this.browserProxy_.observeAdvancedFontExtensionAvailable();
+
this.browserProxy_.fetchFontsData().then(
this.setFontsData_.bind(this));
},
@@ -174,8 +187,28 @@
this.minimumFontSizeRange_[this.immediateMinimumSizeIndex_]);
},
+ /** @private */
+ openAdvancedExtension_: function() {
+ if (this.advancedExtensionInstalled_)
+ this.browserProxy_.openAdvancedFontSettings();
+ else
+ window.open(this.advancedExtensionUrl_);
+ },
+
+ /**
+ * @param {boolean} isInstalled Whether the advanced font settings
+ * extension is installed.
+ * @private
+ */
+ setAdvancedExtensionInstalled_: function(isInstalled) {
+ this.advancedExtensionInstalled_ = isInstalled;
+ this.advancedExtensionSublabel_ = this.i18n(isInstalled ?
+ 'openAdvancedFontSettings' : 'requiresWebStoreExtension');
+ },
+
/**
- * @param {!FontsData} response A list of fonts and encodings.
+ * @param {!FontsData} response A list of fonts, encodings and the advanced
+ * font settings extension URL.
* @private
*/
setFontsData_: function(response) {
@@ -199,6 +232,7 @@
});
}
this.$.encoding.menuOptions = encodingMenuOptions;
+ this.advancedExtensionUrl_ = response.extensionUrl;
},
/**
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 9bc323e4397..761fd57e782 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -2,59 +2,65 @@
<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/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/device-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/image-icons.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="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="chrome://md-settings/appearance_page/appearance_browser_proxy.html">
<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html">
<link rel="import" href="chrome://md-settings/controls/settings_input.html">
<link rel="import" href="chrome://md-settings/controls/settings_radio_group.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_subpage.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<link rel="import" href="appearance_fonts_page.html">
<dom-module id="settings-appearance-page">
- <link rel="import" type="css"
- href="chrome://md-settings/appearance_page/appearance_shared.css">
<link rel="import" type="css" href="chrome://resources/css/widgets.css">
<link rel="import" href="chrome://resources/html/action_link.html">
<template>
<style include="settings-shared">
.settings-box iron-icon {
- -webkit-margin-end: var(--checkbox-spacing);
+ -webkit-margin-end: var(--iron-icon-spacing);
}
</style>
<settings-animated-pages id="pages" current-route="{{currentRoute}}"
section="appearance">
<neon-animatable id="main">
<if expr="chromeos">
- <div class="settings-box first two-line">
- <iron-icon icon="device:wallpaper"></iron-icon>
+ <div class="settings-box first two-line" id="wallpaperButton"
+ on-tap="openWallpaperManager_">
+ <iron-icon icon="settings:wallpaper"></iron-icon>
<div class="start">
- <div>[[i18n('setWallpaper')]]</div>
- <div class="secondary">[[i18n('openWallpaperApp')]]</div>
+ <div>$i18n{setWallpaper}</div>
+ <div class="secondary">$i18n{openWallpaperApp}</div>
</div>
</div>
- <div class="settings-box two-line" on-tap="openThemesGallery_">
+ <div class="settings-box two-line">
</if>
<if expr="not chromeos">
- <div class="settings-box two-line first" on-tap="openThemesGallery_">
+ <div class="settings-box two-line first">
</if>
- <iron-icon icon="image:palette"></iron-icon>
- <div class="start">
- <div>[[i18n('getThemes')]]</div>
- <div class="secondary">[[themeSublabel_]]</div>
+ <div class="layout horizontal center flex"
+ on-tap="openThemesGallery_">
+ <iron-icon icon="settings:palette"></iron-icon>
+ <div>
+ <div>$i18n{getThemes}</div>
+ <div class="secondary">[[themeSublabel_]]</div>
+ </div>
</div>
<template is="dom-if" if="[[allowResetTheme_]]">
- <paper-button on-tap="resetTheme_" class="secondary-action"
- >[[i18n('resetToDefaultTheme')]]</paper-button>
+ <div class="secondary-action">
+ <paper-button id="resetTheme" on-tap="resetTheme_"
+ class="secondary-button">
+ $i18n{resetToDefaultTheme}
+ </paper-button>
+ </div>
</template>
</div>
<div class="settings-box two-line">
- <settings-checkbox class="start" i18n-values="label:showHomeButton"
+ <settings-checkbox class="start" label="$i18n{showHomeButton}"
sub-label="[[getShowHomeSubLabel_(prefs.homepage_is_newtabpage.value, prefs.homepage.value)]]"
pref="{{prefs.browser.show_home_button}}">
</settings-checkbox>
@@ -63,24 +69,24 @@
<div class="list-frame">
<settings-radio-group pref="{{prefs.homepage_is_newtabpage}}">
<paper-radio-button class="list-item" name="true">
- [[i18n('homePageNtp')]]
+ $i18n{homePageNtp}
</paper-radio-button>
<paper-radio-button class="list-item" name="false">
- [[i18n('other')]]
+ $i18n{other}
<settings-input no-label-float pref="{{prefs.homepage}}"
- label="[[i18n('exampleDotCom')]]">
+ label="$i18n{exampleDotCom}">
</settings-input>
</paper-radio-button>
</settings-radio-group>
</div>
</template>
<div class="settings-box">
- <settings-checkbox class="start" i18n-values="label:showBookmarksBar"
+ <settings-checkbox class="start" label="$i18n{showBookmarksBar}"
pref="{{prefs.bookmark_bar.show_on_all_tabs}}">
</settings-checkbox>
</div>
<div class="settings-box">
- <div class="start" i18n-content="fontSize"></div>
+ <div class="start">$i18n{fontSize}</div>
<settings-dropdown-menu id="defaultFontSize"
pref="{{prefs.webkit.webprefs.default_font_size}}"
menu-options="[[fontSizeOptions_]]" no-label-float>
@@ -88,19 +94,19 @@
</div>
<div class="settings-box two-line" on-tap="onCustomizeFontsTap_">
<div class="start">
- <div i18n-content="customizeFonts"></div>
- <div class="secondary" i18n-content="chooseFontsAndEncoding"></div>
+ <div>$i18n{customizeFonts}</div>
+ <div class="secondary">$i18n{chooseFontsAndEncoding}</div>
</div>
</div>
<div class="settings-box">
- <div class="start" i18n-content="pageZoom"></div>
+ <div class="start">$i18n{pageZoom}</div>
<settings-dropdown-menu id="pageZoom" pref="{{defaultZoomLevel_}}"
menu-options="[[pageZoomOptions_]]" no-label-float>
</settings-dropdown-menu>
</div>
</neon-animatable>
<template is="dom-if" name="appearance-fonts">
- <settings-subpage page-title="[[i18n('customizeFonts')]]">
+ <settings-subpage page-title="$i18n{customizeFonts}">
<settings-appearance-fonts-page prefs="{{prefs}}">
</settings-appearance-fonts-page>
</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 c8320e907b5..42bde602738 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -28,6 +28,9 @@ Polymer({
type: Object,
},
+ /** @private {!settings.AppearanceBrowserProxy} */
+ browserProxy_: Object,
+
/**
* Preferences state.
*/
@@ -111,6 +114,10 @@ Polymer({
'zoomLevelChanged_(defaultZoomLevel_.value)',
],
+ created: function() {
+ this.browserProxy_ = settings.AppearanceBrowserProxyImpl.getInstance();
+ },
+
ready: function() {
this.$.defaultFontSize.menuOptions = this.fontSizeOptions_;
this.$.pageZoom.menuOptions = this.pageZoomOptions_;
@@ -123,7 +130,7 @@ Polymer({
/** @override */
attached: function() {
// Query the initial state.
- cr.sendWithPromise('getResetThemeEnabled').then(
+ this.browserProxy_.getResetThemeEnabled().then(
this.setResetThemeEnabled.bind(this));
// Set up the change event listener.
@@ -160,9 +167,19 @@ Polymer({
window.open(loadTimeData.getString('themesGalleryUrl'));
},
+<if expr="chromeos">
+ /**
+ * ChromeOS only.
+ * @private
+ */
+ openWallpaperManager_: function() {
+ this.browserProxy_.openWallpaperManager();
+ },
+</if>
+
/** @private */
resetTheme_: function() {
- chrome.send('resetTheme');
+ this.browserProxy_.resetTheme();
},
/** @private */
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_shared.css b/chromium/chrome/browser/resources/settings/appearance_page/appearance_shared.css
deleted file mode 100644
index d81173da5c4..00000000000
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_shared.css
+++ /dev/null
@@ -1,12 +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. */
-
-/*
- * Keep the slider color consistent throughout the range.
- */
-paper-slider {
- --paper-slider-knob-start-border-color: var(--google-blue-700);
- --paper-slider-knob-start-color: var(--google-blue-700);
- --paper-slider-pin-start-color: var(--google-blue-700);
-}
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 346e8f9504f..dc3d6305133 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp
@@ -7,6 +7,7 @@
'target_name': 'appearance_fonts_page',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-slider/compiled_resources2.gyp:paper-slider-extracted',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(EXTERNS_GYP):chrome_send',
@@ -15,6 +16,15 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'appearance_browser_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):chrome_send',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'appearance_page',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
@@ -24,7 +34,8 @@
'<(EXTERNS_GYP):settings_private',
'<(EXTERNS_GYP):chrome_send',
'../controls/compiled_resources2.gyp:settings_dropdown_menu',
- '../settings_page/compiled_resources2.gyp:settings_animated_pages'
+ '../settings_page/compiled_resources2.gyp:settings_animated_pages',
+ 'appearance_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js b/chromium/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js
index 61f2edb3615..75649d97378 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.js
@@ -6,6 +6,7 @@
* @typedef {{
* fontList: Array<{0: string, 1: (string|undefined), 2: (string|undefined)}>,
* encodingList: Array<{0: string, 1: string}>,
+ * extensionUrl: string
* }}
*/
var FontsData;
@@ -16,9 +17,14 @@ cr.define('settings', function() {
FontsBrowserProxy.prototype = {
/**
- * @return {!Promise<!FontsData>} Fonts and encodings.
+ * @return {!Promise<!FontsData>} Fonts, encodings and the advanced font
+ * settings extension URL.
*/
fetchFontsData: assertNotReached,
+
+ observeAdvancedFontExtensionAvailable: assertNotReached,
+
+ openAdvancedFontSettings: assertNotReached,
};
/**
@@ -34,6 +40,16 @@ cr.define('settings', function() {
fetchFontsData: function() {
return cr.sendWithPromise('fetchFontsData');
},
+
+ /** @override */
+ observeAdvancedFontExtensionAvailable: function() {
+ chrome.send('observeAdvancedFontExtensionAvailable');
+ },
+
+ /** @override */
+ openAdvancedFontSettings: function() {
+ chrome.send('openAdvancedFontSettings');
+ }
};
return {
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 cb30d7016f6..77861eb2fcc 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -1,9 +1,9 @@
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://md-settings/appearance_page/appearance_page.html">
<link rel="import" href="chrome://md-settings/search_page/search_page.html">
<link rel="import" href="chrome://md-settings/settings_page/main_page_behavior.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_page_visibility.html">
+<link rel="import" href="chrome://md-settings/settings_page/settings_router.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_section.html">
<link rel="import" href="chrome://md-settings/on_startup_page/on_startup_page.html">
<link rel="import" href="chrome://md-settings/people_page/people_page.html">
@@ -28,7 +28,7 @@
</template>
<if expr="chromeos">
<template is="dom-if" if="[[showPage(pageVisibility.internet)]]" restamp>
- <settings-section page-title="[[i18n('internetPageTitle')]]"
+ <settings-section page-title="$i18n{internetPageTitle}"
current-route="[[currentRoute]]" section="internet">
<settings-internet-page current-route="{{currentRoute}}">
</settings-internet-page>
@@ -36,7 +36,7 @@
</template>
</if>
<template is="dom-if" if="[[showPage(pageVisibility.people)]]" restamp>
- <settings-section page-title="[[i18n('peoplePageTitle')]]"
+ <settings-section page-title="$i18n{peoplePageTitle}"
current-route="[[currentRoute]]" section="people">
<settings-people-page prefs="{{prefs}}"
current-route="{{currentRoute}}">
@@ -44,7 +44,7 @@
</settings-section>
</template>
<template is="dom-if" if="[[showPage(pageVisibility.appearance)]]" restamp>
- <settings-section page-title="[[i18n('appearancePageTitle')]]"
+ <settings-section page-title="$i18n{appearancePageTitle}"
current-route="[[currentRoute]]" section="appearance">
<settings-appearance-page prefs="{{prefs}}"
current-route="{{currentRoute}}">
@@ -53,7 +53,7 @@
</template>
<if expr="chromeos">
<template is="dom-if" if="[[showPage(pageVisibility.device)]]" restamp>
- <settings-section page-title="[[i18n('devicePageTitle')]]"
+ <settings-section page-title="$i18n{devicePageTitle}"
current-route="[[currentRoute]]" section="device">
<settings-device-page prefs="{{prefs}}"
current-route="{{currentRoute}}">
@@ -62,7 +62,7 @@
</template>
</if>
<template is="dom-if" if="[[showPage(pageVisibility.search)]]" restamp>
- <settings-section page-title="[[i18n('searchPageTitle')]]"
+ <settings-section page-title="$i18n{searchPageTitle}"
current-route="[[currentRoute]]" section="search">
<settings-search-page current-route="{{currentRoute}}">
</settings-search-page>
@@ -71,7 +71,7 @@
<if expr="not chromeos">
<template is="dom-if" if="[[showPage(pageVisibility.defaultBrowser)]]"
restamp>
- <settings-section page-title="[[i18n('defaultBrowser')]]"
+ <settings-section page-title="$i18n{defaultBrowser}"
expand-container="{{expandContainer}}"
current-route="[[currentRoute]]" section="defaultBrowser">
<settings-default-browser-page>
@@ -80,7 +80,7 @@
</template>
</if>
<template is="dom-if" if="[[showPage(pageVisibility.onStartup)]]" restamp>
- <settings-section page-title="[[i18n('onStartup')]]"
+ <settings-section page-title="$i18n{onStartup}"
current-route="[[currentRoute]]" section="onStartup">
<settings-on-startup-page prefs="{{prefs}}"
current-route="{{currentRoute}}">
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 80787fc349b..b6141d01de7 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -5,17 +5,12 @@
/**
* @fileoverview
* 'settings-basic-page' is the settings page containing the basic settings.
- *
- * Example:
- *
- * <iron-animated-pages>
- * <settings-basic-page prefs="{{prefs}}"></settings-basic-page>
- * ... other pages ...
- * </iron-animated-pages>
*/
Polymer({
is: 'settings-basic-page',
+ behaviors: [SettingsPageVisibility, RoutableBehavior],
+
properties: {
/**
* Preferences state.
@@ -27,6 +22,7 @@ Polymer({
/**
* The current active route.
+ * @type {SettingsRoute}
*/
currentRoute: {
type: Object,
@@ -59,8 +55,6 @@ Polymer({
this.scroller = this.parentElement;
},
- behaviors: [I18nBehavior, SettingsPageVisibility, RoutableBehavior],
-
onResetDone_: function() {
this.showResetProfileBanner_ = false;
},
diff --git a/chromium/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp
index b3013ed57a1..00b3fc4f275 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/basic_page/compiled_resources2.gyp
@@ -7,9 +7,9 @@
'target_name': 'basic_page',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'../settings_page/compiled_resources2.gyp:main_page_behavior',
'../settings_page/compiled_resources2.gyp:settings_page_visibility',
+ '../settings_page/compiled_resources2.gyp:settings_router',
'../settings_page/compiled_resources2.gyp:transition_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.html b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.html
deleted file mode 100644
index e936a7240c0..00000000000
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<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/iron-selector/iron-selector.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-spinner/paper-spinner.html">
-<link rel="import" href="chrome://md-settings/settings_shared_css.html">
-
-<dom-module id="settings-bluetooth-add-device-dialog">
- <link rel="import" type="css" href="bluetooth_page.css">
- <link rel="import" type="css" href="bluetooth_dialog.css">
- <template>
- <style include="settings-shared"></style>
- <div id="dialogOuterDiv" class="layout vertical flex">
- <div id="dialogHeaderDiv" class="settings-box layout horizontal">
- <span id="dialogTitle" class="flex"
- i18n-content="bluetoothAddDevicePageTitle">
- </span>
- <paper-icon-button icon="close" on-tap="onCancelTap_" id="close">
- </paper-icon-button>
- </div>
- <div class="settings-box flex">
- <div id="dialogDeviceList" class="settings-box layout vertical"
- on-device-event="onDeviceEvent_">
- <span class="no-devices" hidden$="[[haveDevices_(deviceList)]]"
- i18n-content="bluetoothNoDevices">
- </span>
- <iron-selector class="flex">
- <template is="dom-repeat" items="[[deviceList]]"
- filter="deviceNotPaired_" observe="paired">
- <bluetooth-device-list-item device="[[item]]">
- </bluetooth-device-list-item>
- </template>
- </iron-selector>
- </div>
- </div>
- <div id="dialogFooterDiv" class="layout horizontal center">
- <div id="scanning" class="layout horizontal center flex"
- hidden$="[[!adapterState.discovering]]">
- <paper-spinner active="[[adapterState.discovering]]">
- </paper-spinner>
- <span i18n-content="bluetoothScanning"></span>
- </div>
- <paper-button id="cancel" class="end-justified"
- i18n-content="cancel" on-tap="onCancelTap_">
- </paper-button>
- </div>
- </div>
- </template>
- <script src="bluetooth_add_device_dialog.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.js b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.js
deleted file mode 100644
index eaff3ae4b33..00000000000
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_add_device_dialog.js
+++ /dev/null
@@ -1,68 +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-bluetooth-add-device-dialog' is the settings subpage for adding
- * bluetooth devices.
- */
-Polymer({
- is: 'settings-bluetooth-add-device-dialog',
-
- properties: {
- /**
- * The cached bluetooth adapter state.
- * @type {!chrome.bluetooth.AdapterState|undefined}
- */
- adapterState: {
- type: Object,
- observer: 'adapterStateChanged_',
- },
-
- /**
- * The ordered list of bluetooth devices.
- * @type {!Array<!chrome.bluetooth.Device>}
- */
- deviceList: {
- type: Array,
- value: function() { return []; },
- },
- },
-
- /** @private */
- adapterStateChanged_: function() {
- if (!this.adapterState.powered)
- this.fire('close-dialog');
- },
-
- /**
- * @param {!chrome.bluetooth.Device} device
- * @return {boolean}
- * @private
- */
- deviceNotPaired_: function(device) {
- return !device.paired;
- },
-
- /**
- * @param {!Array<!chrome.bluetooth.Device>} deviceList
- * @return {boolean} True if deviceList contains any unpaired devices.
- * @private
- */
- haveDevices_: function(deviceList) {
- return this.deviceList.findIndex(function(d) { return !d.paired; }) != -1;
- },
-
- /**
- * @param {!{detail: {action: string, device: !chrome.bluetooth.Device}}} e
- * @private
- */
- onDeviceEvent_: function(e) {
- this.fire('device-event', e.detail);
- /** @type {Event} */(e).stopPropagation();
- },
-
- /** @private */
- onCancelTap_: function() { this.fire('close-dialog'); },
-});
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
new file mode 100644
index 00000000000..ca8cb0c31c0
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
@@ -0,0 +1,171 @@
+<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-flex-layout/classes/iron-flex-layout.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-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="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
+<link rel="import" href="chrome://md-settings/bluetooth_page/bluetooth_device_list_item.html">
+<link rel="import" href="chrome://md-settings/icons.html">
+<link rel="import" href="chrome://md-settings/settings_dialog.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+
+<dom-module id="bluetooth-device-dialog">
+ <template>
+ <style include="settings-shared">
+ #dialogFooterDiv {
+ height: 40px;
+ margin: 0 20px;
+ }
+
+ #dialogMessage {
+ margin-bottom: 10px;
+ }
+
+ #dialogDeviceList {
+ -webkit-margin-start: 4px;
+ height: 210px;
+ margin-bottom: 20px;
+ overflow-y: auto;
+ }
+
+ #pairing {
+ margin-bottom: 10px;
+ }
+
+ #pairing paper-input {
+ text-align: center;
+ }
+
+ #pinDiv {
+ margin-top: 10px;
+ }
+
+ iron-selector {
+ width: 100%;
+ }
+
+ paper-spinner {
+ height: 20px;
+ margin: 0 10px;
+ width: 20px;
+ }
+
+ /* .display indicates a displayed pin code or passkey. */
+ span.display {
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ box-shadow: 0 0 0 1px #222;
+ color: #222;
+ font-size: 16px;
+ height: 38px;
+ line-height: 38px;
+ margin: 0 5px;
+ padding: 0 15px;
+ text-align: center;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ }
+
+ span.display.next {
+ background: rgb(77, 144, 254);
+ border: 2px solid rgb(77, 144, 254);
+ box-shadow: none;
+ color: #fff;
+ }
+
+ span.display.untyped {
+ border: 1px solid #d4d4d4;
+ box-shadow: 0 0 0 1px #888;
+ color: #666;
+ }
+
+ /* .confirm indicates a confirmation passkey. */
+ span.confirm {
+ color: #999;
+ font-size: 20px;
+ font-weight: 600; /* semibold */
+ margin: 0 20px;
+ }
+ </style>
+ <settings-dialog id="dialog" class="layout vertical"
+ on-iron-overlay-canceled="onIronOverlayCanceled_"
+ on-iron-overlay-closed="onIronOverlayClosed_">
+ <div class="title">[[getTitle_(dialogType)]]</div>
+ <div class="body">
+ <template is="dom-if" if="[[isDialogType_(dialogType, 'addDevice')]]">
+ <div class="settings-box flex">
+ <div id="dialogDeviceList" class="settings-box layout vertical"
+ on-device-event="onDeviceEvent_">
+ <span class="no-devices" hidden$="[[haveDevices_(deviceList)]]">
+ $i18n{bluetoothNoDevices}
+ </span>
+ <iron-selector class="flex">
+ <template is="dom-repeat" items="[[deviceList]]"
+ filter="deviceNotPaired_" observe="paired">
+ <bluetooth-device-list-item device="[[item]]">
+ </bluetooth-device-list-item>
+ </template>
+ </iron-selector>
+ </div>
+ </div>
+ </template>
+ <template is="dom-if" if="[[isDialogType_(dialogType, 'pairDevice')]]">
+ <div id="pairing" class="settings-blox layout vertical center
+ center-justified flex">
+ <div id="dialogMessage">
+ [[getMessage_(pairingDevice, pairingEvent)]]
+ </div>
+ <div hidden$="[[!showEnterPincode_(pairingEvent)]]">
+ <paper-input id="pincode" minlength="1" maxlength="16"
+ type="text">
+ </div>
+ <div hidden$="[[!showEnterPasskey_(pairingEvent)]]">
+ <paper-input id="passkey" minlength="6" maxlength="6" type="text">
+ </div>
+ <div id="pinDiv" class="layout horizontal center center-justified"
+ hidden="[[!showDisplayPassOrPin_(pairingEvent)]]">
+ <template is="dom-repeat" items="[[digits]]">
+ <span class$="[[getPinClass_(pairingEvent, index)]]">
+ [[getPinDigit_(pairingEvent, index)]]
+ </span>
+ </template>
+ <span class$="[[getPinClass_(pairingEvent, -1)]]"
+ hidden="[[showAcceptReject_(pairingEvent)]]">
+ $i18n{bluetoothEnterKey}
+ </span>
+ </div>
+ </div>
+ </template>
+ </div>
+ <div class="button-container">
+ <template is="dom-if" if="[[isDialogType_(dialogType, 'addDevice')]]">
+ <div id="scanning" class="layout horizontal center flex"
+ hidden$="[[!adapterState.discovering]]">
+ <paper-spinner active="[[adapterState.discovering]]">
+ </paper-spinner>
+ <span>$i18n{bluetoothScanning}</span>
+ </div>
+ <paper-button class="end-justified" on-tap="onCancelTap_">
+ $i18n{cancel}
+ </paper-button>
+ </template>
+ <template is="dom-if" if="[[isDialogType_(dialogType, 'pairDevice')]]">
+ <paper-button hidden$="[[!showAcceptReject_(pairingEvent)]]"
+ on-tap="onAcceptTap_">$i18n{bluetoothAccept}</paper-button>
+ <paper-button hidden$="[[!showAcceptReject_(pairingEvent)]]"
+ on-tap="onRejectTap_">$i18n{bluetoothReject}</paper-button>
+ <paper-button hidden$="[[!showConnect_(pairingEvent)]]"
+ on-tap="onConnectTap_">$i18n{bluetoothConnect}</paper-button>
+ <paper-button hidden$="[[!showDismiss_(pairingDevice, pairingEvent)]]"
+ on-tap="onDismissTap_">$i18n{bluetoothDismiss}</paper-button>
+ <paper-button hidden$="[[showDismiss_(pairingDevice, pairingEvent)]]"
+ on-tap="onCancelTap_">
+ $i18n{cancel}
+ </paper-button>
+ </template>
+ </div>
+ </settings-dialog>
+ </template>
+ <script src="chrome://md-settings/bluetooth_page/bluetooth_device_dialog.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_pair_device_dialog.js b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.js
index 83178309a7e..7b410b0c33b 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_pair_device_dialog.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.js
@@ -1,22 +1,74 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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-bluetooth-pair-device-dialog' is the settings dialog for pairing
- * a bluetooth device.
- */
+cr.exportPath('settings');
(function() {
var PairingEventType = chrome.bluetoothPrivate.PairingEventType;
-Polymer({
- is: 'settings-bluetooth-pair-device-dialog',
+// NOTE(dbeam): even though these behaviors are only used privately, they must
+// be globally accessible for Closure's --polymer_pass to compile happily.
+
+/** @polymerBehavior */
+settings.BluetoothAddDeviceBehavior = {
+ properties: {
+ /**
+ * The cached bluetooth adapter state.
+ * @type {!chrome.bluetooth.AdapterState|undefined}
+ */
+ adapterState: {
+ type: Object,
+ observer: 'adapterStateChanged_',
+ },
+
+ /**
+ * The ordered list of bluetooth devices.
+ * @type {!Array<!chrome.bluetooth.Device>}
+ */
+ deviceList: {
+ type: Array,
+ value: /** @return {Array} */ function() { return []; },
+ },
+ },
+
+ /** @private */
+ adapterStateChanged_: function() {
+ if (!this.adapterState.powered)
+ this.fire('close-dialog');
+ },
+
+ /**
+ * @param {!chrome.bluetooth.Device} device
+ * @return {boolean}
+ * @private
+ */
+ deviceNotPaired_: function(device) {
+ return !device.paired;
+ },
- behaviors: [I18nBehavior],
+ /**
+ * @param {!Array<!chrome.bluetooth.Device>} deviceList
+ * @return {boolean} True if deviceList contains any unpaired devices.
+ * @private
+ */
+ haveDevices_: function(deviceList) {
+ return this.deviceList.findIndex(function(d) { return !d.paired; }) != -1;
+ },
+ /**
+ * @param {!{detail: {action: string, device: !chrome.bluetooth.Device}}} e
+ * @private
+ */
+ onDeviceEvent_: function(e) {
+ this.fire('device-event', e.detail);
+ /** @type {Event} */(e).stopPropagation();
+ },
+};
+
+/** @polymerBehavior */
+settings.BluetoothPairDeviceBehavior = {
properties: {
/**
* Current Pairing device.
@@ -36,7 +88,7 @@ Polymer({
*/
digits: {
type: Array,
- readonly: true,
+ readOnly: true,
value: [0, 1, 2, 3, 4, 5],
},
},
@@ -167,13 +219,6 @@ Polymer({
},
/** @private */
- onCancelTap_: function() {
- this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.CANCEL);
- // Close the dialog immediately.
- this.fire('close-dialog', '');
- },
-
- /** @private */
onDismissTap_: function() { this.fire('close-dialog', ''); },
/** @private */
@@ -264,5 +309,67 @@ Polymer({
}
return cssClass;
},
+};
+
+Polymer({
+ is: 'bluetooth-device-dialog',
+
+ behaviors: [
+ I18nBehavior,
+ settings.BluetoothAddDeviceBehavior,
+ settings.BluetoothPairDeviceBehavior,
+ ],
+
+ properties: {
+ /** Which version of this dialog to show (adding or pairing). */
+ dialogType: String,
+ },
+
+ /**
+ * @param {string} dialogType
+ * @return {string} The title of for that |dialogType|.
+ */
+ getTitle_: function(dialogType) {
+ return this.i18n(dialogType == 'addDevice' ?
+ 'bluetoothAddDevicePageTitle' : 'bluetoothPairDevicePageTitle');
+ },
+
+ /**
+ * @param {string} currentDialogType
+ * @param {string} wantedDialogType
+ * @return {boolean}
+ * @private
+ */
+ isDialogType_: function(currentDialogType, wantedDialogType) {
+ return currentDialogType == wantedDialogType;
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ // NOTE: tapping on an element with [dialog-dismiss] doesn't trigger an
+ // iron-overlay-cancel event, whereas tapping (X) or pressing Esc does.
+ // Using cancel() ensures all 3 ways to close the dialog run the same code.
+ this.$.dialog.cancel();
+ },
+
+ /** @private */
+ onIronOverlayCanceled_: function() {
+ if (this.dialogType == 'pairDevice')
+ this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.CANCEL);
+ },
+
+ /** @private */
+ onIronOverlayClosed_: function() {
+ this.fire('close-dialog', '');
+ },
+
+ open: function() {
+ this.$.dialog.open();
+ },
+
+ close: function() {
+ this.$.dialog.close();
+ },
});
+
})();
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.css b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.css
deleted file mode 100644
index bd41095ea12..00000000000
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.css
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright 2015 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-#outer {
- -webkit-padding-end: 5px;
- -webkit-padding-start: 15px;
- padding-bottom: 5px;
- padding-top: 5px;
-}
-
-#outer:hover:not([dropdown]) {
- background-color: #f0f0f0;
-}
-
-iron-icon {
- -webkit-padding-start: 10px;
-}
-
-paper-item:hover {
- background-color: #f0f0f0;
-}
-
-span.name {
- padding: 10px 0;
-}
-
-span.name[connected] {
- font-weight: bold;
-}
-
-.dropdown-content {
- background: white;
- box-shadow: 0 2px 6px grey;
-}
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html
index 55a16906fb9..252ef143591 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html
@@ -1,33 +1,54 @@
+<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-dropdown/iron-dropdown.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/iron-icon/iron-icon.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-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
<dom-module id="bluetooth-device-list-item">
- <link rel="import" type="css" href="bluetooth_device_list_item.css">
+ <style>
+ iron-icon {
+ -webkit-padding-start: 10px;
+ }
+
+ span.name {
+ padding: 10px 0;
+ }
+
+ span.name[connected] {
+ font-weight: 500;
+ }
+
+ /* TODO(dbeam): combine with other similar styles. */
+ .dropdown-content {
+ background: white;
+ box-shadow: 0 2px 6px grey;
+ }
+ </style>
<template>
- <div id="outer" class="layout horizontal center"
- dropdown$="[[dropdownOpened]]" on-tap="itemTapped_">
+ <div class="flex layout horizontal center" dropdown$="[[dropdownOpened]]"
+ on-tap="itemTapped_">
<span class="name" connected$="[[device.connected]]">
[[getDeviceName_(device)]]
</span>
- <iron-icon icon="check" hidden$="[[!device.connected]]"></iron-icon>
+ <iron-icon icon="cr:check" hidden$="[[!device.connected]]">
+ </iron-icon>
<span class="flex"></span>
- <span hidden$="[[!device.connecting]]"
- i18n-content="bluetoothConnecting"></span>
+ <span hidden$="[[!device.connecting]]">$i18n{bluetoothConnecting}</span>
<div hidden$="[[!device.paired]]" on-tap="doNothing_">
- <paper-icon-button icon="more-vert" toggles active="{{dropdownOpened}}">
+ <paper-icon-button icon="cr:more-vert" toggles
+ active="{{dropdownOpened}}">
</paper-icon-button>
<iron-dropdown opened="{{dropdownOpened}}" on-tap="menuSelected_">
<div class="dropdown-content">
- <paper-item id="connect" i18n-content="bluetoothConnect"
- hidden$="[[device.connected]]"></paper-item>
- <paper-item id="disconnect" i18n-content="bluetoothDisconnect"
- hidden$="[[!device.connected]]"></paper-item>
- <paper-item id="remove" i18n-content="bluetoothRemove"></paper-item>
+ <paper-item id="connect" hidden$="[[device.connected]]">
+ $i18n{bluetoothConnect}
+ </paper-item>
+ <paper-item id="disconnect" hidden$="[[!device.connected]]">
+ $i18n{bluetoothDisconnect}
+ </paper-item>
+ <paper-item id="remove">$i18n{bluetoothRemove}</paper-item>
</div>
</iron-dropdown>
</div>
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_dialog.css b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_dialog.css
deleted file mode 100644
index 827fd37a114..00000000000
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_dialog.css
+++ /dev/null
@@ -1,91 +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. */
-
-#dialogOuterDiv {
- margin-bottom: 16px;
-}
-
-#dialogHeaderDiv {
- height: 40px;
- margin: 0 5px 10px;
-}
-
-#dialogFooterDiv {
- height: 40px;
- margin: 0 20px;
-}
-
-#dialogMessage {
- margin-bottom: 10px;
-}
-
-#dialogTitle {
- font-size: 125%;
- margin: 0 10px;
-}
-
-#dialogDeviceList {
- -webkit-margin-start: 4px;
- height: 210px;
- margin-bottom: 20px;
- overflow-y: auto;
-}
-
-#pairing {
- margin-bottom: 10px;
-}
-
-#pairing paper-input {
- text-align: center;
-}
-
-#pinDiv {
- margin-top: 10px;
-}
-
-iron-selector {
- width: 100%;
-}
-
-paper-spinner {
- height: 20px;
- margin: 0 10px;
- width: 20px;
-}
-
-/* .display indicates a displayed pin code or passkey. */
-span.display {
- border: 1px solid #ccc;
- border-radius: 4px;
- box-shadow: 0 0 0 1px #222;
- color: #222;
- font-size: 16px;
- height: 38px;
- line-height: 38px;
- margin: 0 5px;
- padding: 0 15px;
- text-align: center;
- text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-}
-
-span.display.next {
- background: rgb(77, 144, 254);
- border: 2px solid rgb(77, 144, 254);
- box-shadow: none;
- color: #fff;
-}
-
-span.display.untyped {
- border: 1px solid #d4d4d4;
- box-shadow: 0 0 0 1px #888;
- color: #666;
-}
-
-/* .confirm indicates a confirmation passkey. */
-span.confirm {
- color: #999;
- font-size: 20px;
- font-weight: 600; /* semibold */
- margin: 0 20px;
-}
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.css b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.css
deleted file mode 100644
index 2eb7bd8b15d..00000000000
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.css
+++ /dev/null
@@ -1,32 +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. */
-
-#addDevice {
- color: blue;
-}
-
-#deviceList {
- -webkit-margin-start: 15px;
- max-height: 300px;
- overflow-y: auto;
-}
-
-cr-expand-button {
- -webkit-margin-end: 10px;
-}
-
-iron-icon {
- -webkit-margin-end: 10px;
-}
-
-settings-bluetooth-add-device-dialog,
-settings-bluetooth-pair-device-dialog {
- height: 400px;
- padding: 0;
- width: 500px;
-}
-
-span.no-devices {
- margin: 10px 20px;
-}
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 7c720a64697..18cce8c1891 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
@@ -2,28 +2,50 @@
<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/iron-flex-layout/classes/iron-flex-layout.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/device-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.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="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+<link rel="import" href="bluetooth_device_dialog.html">
<link rel="import" href="bluetooth_device_list_item.html">
-<link rel="import" href="bluetooth_add_device_dialog.html">
-<link rel="import" href="bluetooth_pair_device_dialog.html">
<dom-module id="settings-bluetooth-page">
- <link rel="import" type="css" href="bluetooth_page.css">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ iron-icon {
+ -webkit-margin-end: var(--iron-icon-spacing);
+ }
+
+ cr-expand-button {
+ -webkit-margin-end: 10px;
+ }
+
+ #deviceList {
+ max-height: 300px;
+ overflow-y: auto;
+ }
+
+ .no-devices {
+ min-height: var(--settings-row-min-height);
+ }
+
+ settings-bluetooth-add-device-dialog,
+ settings-bluetooth-pair-device-dialog {
+ height: 400px;
+ padding: 0;
+ width: 500px;
+ }
+ </style>
<settings-animated-pages id="pages" current-route="{{currentRoute}}"
section="bluetooth">
<neon-animatable id="main">
<div class="settings-box first">
- <div class="layout horizontal center">
- <iron-icon icon="device:bluetooth"></iron-icon>
- <span class="flex" i18n-content="bluetoothEnable"></span>
+ <div class="layout horizontal center flex">
+ <iron-icon icon="settings:bluetooth"></iron-icon>
+ <span class="flex">$i18n{bluetoothEnable}</span>
<cr-expand-button id="expandListButton"
hidden$="[[!bluetoothEnabled]]"
expanded="{{deviceListExpanded}}">
@@ -33,53 +55,42 @@
on-change="onBluetoothEnabledChange_">
</paper-toggle-button>
</div>
- <iron-collapse opened="[[deviceListExpanded]]">
- <div id="deviceList" class="layout vertical"
- on-device-event="onDeviceEvent_">
- <span class="no-devices"
- hidden$="[[haveDevices_(deviceList.splices)]]"
- i18n-content="bluetoothNoDevices">
- </span>
- <template is="dom-repeat" items="[[deviceList]]"
- filter="deviceIsPairedOrConnecting_">
- <bluetooth-device-list-item device="[[item]]">
- </bluetooth-device-list-item>
- </template>
- </div>
- <div class="settings-box" hidden$="[[!bluetoothEnabled]]">
- <paper-button id="addDevice" i18n-content="bluetoothAddDevice"
- on-tap="onAddDeviceTap_">
- </paper-button>
- </div>
- </iron-collapse>
</div>
+ <iron-collapse opened="[[canShowDeviceList_(bluetoothEnabled,
+ deviceListExpanded)]]">
+ <div id="deviceList" class="list-frame vertical-list"
+ on-device-event="onDeviceEvent_">
+ <template is="dom-repeat" items="[[deviceList]]"
+ filter="deviceIsPairedOrConnecting_">
+ <bluetooth-device-list-item device="[[item]]" class="list-item">
+ </bluetooth-device-list-item>
+ </template>
+ <div class="no-devices layout horizontal center"
+ hidden$="[[haveDevices_(deviceList.splices)]]">
+ $i18n{bluetoothNoDevices}
+ </div>
+ </div>
+ <div class="settings-box" hidden$="[[!bluetoothEnabled]]">
+ <paper-button class="primary-button" on-tap="onAddDeviceTap_">
+ $i18n{bluetoothAddDevice}
+ </paper-button>
+ </div>
+ </iron-collapse>
</neon-animatable>
</settings-animated-pages>
- <paper-dialog modal id="deviceDialog" class="layout vertical"
+ <bluetooth-device-dialog id="deviceDialog"
+ adapter-state="[[adapterState]]"
+ device-list="[[deviceList]]"
+ dialog-type="[[dialog]]"
+ on-close-dialog="onCloseDialog_"
+ on-device-event="onDeviceEvent_"
+ on-iron-overlay-closed="onDialogClosed_"
on-iron-overlay-opened="onDialogOpened_"
- on-iron-overlay-closed="onDialogClosed_">
- <template is="dom-if" if="[[dialogIsVisible_(dialog, 'addDevice')]]"
- restamp>
- <settings-bluetooth-add-device-dialog
- class="layout vertical flex"
- adapter-state="[[adapterState]]"
- device-list="[[deviceList]]"
- on-device-event="onDeviceEvent_"
- on-close-dialog="onCloseDialog_">
- </settings-bluetooth-add-device-dialog>
- </template>
- <template is="dom-if" if="[[dialogIsVisible_(dialog, 'pairDevice')]]"
- restamp>
- <settings-bluetooth-pair-device-dialog
- class="layout vertical flex"
- pairing-device="[[pairingDevice]]"
- pairing-event="[[pairingEvent]]"
- on-response="onResponse_"
- on-close-dialog="onCloseDialog_">
- </settings-bluetooth-pair-device-dialog>
- </template>
- </paper-dialog>
+ on-response="onResponse_"
+ pairing-device="[[pairingDevice]]"
+ pairing-event="[[pairingEvent]]">
+ </bluetooth-device-dialog>
</template>
<script src="bluetooth_page.js"></script>
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 41ba307bde9..405d29b9cd0 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -197,6 +197,16 @@ Polymer({
},
/**
+ * @param {boolean} bluetoothEnabled
+ * @param {boolean} deviceListExpanded
+ * @return {boolean} Whether the <iron-collapse> can be shown.
+ * @private
+ */
+ canShowDeviceList_: function(bluetoothEnabled, deviceListExpanded) {
+ return bluetoothEnabled && deviceListExpanded;
+ },
+
+ /**
* If bluetooth is enabled, request the complete list of devices and update
* |deviceList|.
* @private
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_pair_device_dialog.html b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_pair_device_dialog.html
deleted file mode 100644
index 2705f4e119a..00000000000
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_pair_device_dialog.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<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.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
-<link rel="import" href="chrome://md-settings/settings_shared_css.html">
-
-<dom-module id="settings-bluetooth-pair-device-dialog">
- <link rel="import" type="css" href="bluetooth_page.css">
- <link rel="import" type="css" href="bluetooth_dialog.css">
- <template>
- <style include="settings-shared"></style>
- <div id="dialogOuterDiv" class="layout vertical flex">
- <div id="dialogHeaderDiv" class="settings-box layout horizontal center">
- <span id="dialogTitle" class="flex"
- i18n-content="bluetoothPairDevicePageTitle">
- </span>
- <paper-icon-button icon="close" on-tap="onCancelTap_" id="close">
- </paper-icon-button>
- </div>
- <div id="pairing"
- class="settings-blox layout vertical center center-justified flex">
- <div id="dialogMessage">
- [[getMessage_(pairingDevice, pairingEvent)]]
- </div>
- <div hidden$="[[!showEnterPincode_(pairingEvent)]]">
- <paper-input id="pincode" minlength="1" maxlength="16" type="text">
- </div>
- <div hidden$="[[!showEnterPasskey_(pairingEvent)]]">
- <paper-input id="passkey" minlength="6" maxlength="6" type="text">
- </div>
- <div id="pinDiv" class="layout horizontal center center-justified"
- hidden="[[!showDisplayPassOrPin_(pairingEvent)]]">
- <template is="dom-repeat" items="[[digits]]">
- <span class$="[[getPinClass_(pairingEvent, index)]]">
- [[getPinDigit_(pairingEvent, index)]]
- </span>
- </template>
- <span class$="[[getPinClass_(pairingEvent, -1)]]"
- hidden="[[showAcceptReject_(pairingEvent)]]">
- [[i18n('bluetoothEnterKey')]]
- </span>
- </div>
- </div>
- <div id="dialogFooterDiv" class="layout horizontal center end-justified">
- <paper-button i18n-content="bluetoothAccept"
- hidden$="[[!showAcceptReject_(pairingEvent)]]"
- on-tap="onAcceptTap_">
- </paper-button>
- <paper-button i18n-content="bluetoothReject"
- hidden$="[[!showAcceptReject_(pairingEvent)]]"
- on-tap="onRejectTap_">
- </paper-button>
- <paper-button i18n-content="bluetoothConnect"
- hidden$="[[!showConnect_(pairingEvent)]]"
- on-tap="onConnectTap_">
- </paper-button>
- <paper-button i18n-content="bluetoothDismiss"
- hidden$="[[!showDismiss_(pairingDevice, pairingEvent)]]"
- on-tap="onDismissTap_">
- </paper-button>
- <paper-button i18n-content="cancel" on-tap="onCancelTap_"
- hidden$="[[showDismiss_(pairingDevice, pairingEvent)]]">
- </paper-button>
- </div>
- </div>
- </template>
- <script src="bluetooth_pair_device_dialog.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp
index 3cbd221727d..dca7922cc3f 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/compiled_resources2.gyp
@@ -16,26 +16,20 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'bluetooth_device_list_item',
- 'dependencies': [
- '<(EXTERNS_GYP):bluetooth',
- ],
- 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'bluetooth_add_device_dialog',
+ 'target_name': 'bluetooth_device_dialog',
'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',
'<(EXTERNS_GYP):bluetooth',
+ '<(EXTERNS_GYP):bluetooth_private',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'bluetooth_pair_device_dialog',
+ 'target_name': 'bluetooth_device_list_item',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):bluetooth',
- '<(EXTERNS_GYP):bluetooth_private',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
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 ed4eef12782..dae9c6b95f5 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
@@ -3,8 +3,6 @@
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.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-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<link rel="import" href="chrome://md-settings/certificate_manager_page/certificate_subentry.html">
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 cc468ef480e..6e4b4efaca7 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
@@ -46,7 +46,7 @@ Polymer({
certificateTypeEnum_: {
type: Object,
value: settings.CertificateType,
- readonly: true,
+ readOnly: true,
},
/** @private */
diff --git a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.html b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.html
index 7f7d3732435..71a3700ebf3 100644
--- a/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.html
+++ b/chromium/chrome/browser/resources/settings/certificate_manager_page/certificate_subentry.html
@@ -1,10 +1,9 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://md-settings/certificate_manager_page/certificates_browser_proxy.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.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-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
+<link rel="import" href="chrome://md-settings/certificate_manager_page/certificates_browser_proxy.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-certificate-subentry">
@@ -41,7 +40,7 @@
$i18n{certificateManagerUntrusted}
</div>
<div class="name">[[model.name]]</div>
- <paper-icon-button id="dots" icon="more-vert" toggles
+ <paper-icon-button id="dots" icon="cr:more-vert" toggles
active="{{menuOpened}}"></paper-icon-button>
<!-- TODO(dpapad): Figure out RTL for this menu -->
<template is="dom-if" if="[[menuOpened]]">
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html
new file mode 100644
index 00000000000..0c96ce9a995
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://md-settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js
new file mode 100644
index 00000000000..575345ef0ce
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js
@@ -0,0 +1,46 @@
+// 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 A helper object used from the "Clear browsing data" dialog
+ * to interact with the browser.
+ */
+
+cr.define('settings', function() {
+ /** @interface */
+ function ClearBrowsingDataBrowserProxy() {}
+
+ ClearBrowsingDataBrowserProxy.prototype = {
+ /**
+ * @return {!Promise} A promise resolved when data clearing has completed.
+ */
+ clearBrowsingData: function() {},
+
+ /** Initializes the dialog. */
+ initialize: function() {},
+ };
+
+ /**
+ * @constructor
+ * @implements {settings.ClearBrowsingDataBrowserProxy}
+ */
+ function ClearBrowsingDataBrowserProxyImpl() {}
+ cr.addSingletonGetter(ClearBrowsingDataBrowserProxyImpl);
+
+ ClearBrowsingDataBrowserProxyImpl.prototype = {
+ /** @override */
+ clearBrowsingData: function() {
+ return cr.sendWithPromise('clearBrowsingData');
+ },
+
+ /** @override */
+ initialize: function() {
+ chrome.send('initializeClearBrowsingData');
+ },
+ };
+
+ return {
+ ClearBrowsingDataBrowserProxyImpl: ClearBrowsingDataBrowserProxyImpl,
+ };
+});
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 360c5edebcf..1f2f4e6965e 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
@@ -1,19 +1,76 @@
<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/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://md-settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html">
<link rel="import" href="chrome://md-settings/controls/settings_checkbox.html">
<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_dialog.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-clear-browsing-data-dialog">
<template>
- <style include="settings-shared"></style>
- <settings-dialog id="dialog" on-iron-overlay-closed="onDialogClosed_">
- <div class="title" i18n-content="clearBrowsingData"></div>
+ <style include="settings-shared">
+ #dialog {
+ max-width: 600px;
+ }
+
+ paper-spinner {
+ -webkit-margin-end: 16px;
+ margin-bottom: auto;
+ margin-top: auto;
+ }
+
+ #generalFooter {
+ margin: 0;
+ min-height: 18px;
+ }
+
+ #generalFooter iron-icon {
+ height: 18px;
+ padding: 1px;
+ width: 18px;
+ }
+
+ #googleFooter {
+ margin: 0 0 0.8em 0;
+ min-height: 16px;
+ }
+
+ #googleFooter iron-icon {
+ height: 16px;
+ padding: 2px;
+ width: 16px;
+ }
+
+ .clear-browsing-data-footer {
+ padding-left: 4px;
+ }
+
+ .clear-browsing-data-footer .footer-text {
+ -webkit-margin-start: 36px;
+ }
+
+ .clear-browsing-data-footer iron-icon {
+ float: left;
+ }
+
+ html[dir='rtl'] .clear-browsing-data-footer iron-icon {
+ float: right;
+ }
+
+ .clear-browsing-data-footer a {
+ text-decoration: none;
+ }
+ </style>
+
+ <settings-dialog id="dialog">
+ <div class="title">$i18n{clearBrowsingData}</div>
<div class="body">
<div class="row">
- <span class="start" i18n-content="clearFollowingItemsFrom"></span>
+ <span class="start">$i18n{clearFollowingItemsFrom}</span>
<settings-dropdown-menu id="clearFrom"
pref="{{prefs.browser.clear_data.time_period}}"
menu-options="[[clearFromOptions_]]" no-label-float>
@@ -21,47 +78,61 @@
</div>
<settings-checkbox id="browsingCheckbox"
pref="{{prefs.browser.clear_data.browsing_history}}"
- i18n-values="label:clearBrowsingHistory">
+ label="$i18n{clearBrowsingHistory}">
</settings-checkbox>
<settings-checkbox id="downloadCheckbox"
pref="{{prefs.browser.clear_data.download_history}}"
- i18n-values="label:clearDownloadHistory">
+ label="$i18n{clearDownloadHistory}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.browser.clear_data.cache}}"
- i18n-values="label:clearCache">
+ label="$i18n{clearCache}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.browser.clear_data.cookies}}"
- i18n-values="label:clearCookies">
+ label="$i18n{clearCookies}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.browser.clear_data.passwords}}"
- i18n-values="label:clearPasswords">
+ label="$i18n{clearPasswords}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.browser.clear_data.form_data}}"
- i18n-values="label:clearFormData">
+ label="$i18n{clearFormData}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.browser.clear_data.hosted_apps_data}}"
- i18n-values="label:clearHostedAppData">
+ label="$i18n{clearHostedAppData}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.browser.clear_data.content_licenses}}"
- i18n-values="label:clearDeauthorizeContentLicenses">
+ label="$i18n{clearDeauthorizeContentLicenses}">
</settings-checkbox>
</div>
<div class="button-container">
- <paper-button class="cancel-button" i18n-content="cancel"
- dialog-dismiss></paper-button>
- <paper-button class="action-button" id="clearDataButton"
- i18n-content="clearBrowsingData" dialog-confirm>
+ <paper-spinner active="[[clearingInProgress_]]"></paper-spinner>
+ <paper-button class="cancel-button" disabled="[[clearingInProgress_]]"
+ dialog-dismiss>$i18n{cancel}</paper-button>
+ <paper-button class="action-button" disabled="[[clearingInProgress_]]"
+ on-tap="onClearBrowsingDataTap_">
+ $i18n{clearBrowsingData}
</paper-button>
</div>
<div class="footer">
- <span i18n-content="warnAboutNonClearedData"></span>
- <span i18n-content="clearsSyncedData"></span>
+ <div id="googleFooter" class="clear-browsing-data-footer">
+ <iron-icon icon="settings:googleg"></iron-icon>
+ <div class="footer-text">$i18nRaw{otherFormsOfBrowsingHistory}</div>
+ </div>
+ <div id="generalFooter" class="clear-browsing-data-footer">
+ <iron-icon icon="settings:info"></iron-icon>
+ <div class="footer-text">
+ <span id="syncedDataSentence">$i18n{clearsSyncedData}</span>
+ <span>$i18n{warnAboutNonClearedData}</span>
+ <a id="clear-browser-data-old-learn-more-link"
+ href="$i18n{clearBrowsingDataLearnMoreUrl}"
+ target="_blank">$i18n{learnMore}</a>
+ </div>
+ </div>
</div>
</settings-dialog>
</template>
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
index 0d9f4de1dd6..ab1fff32c1f 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
@@ -3,21 +3,14 @@
// found in the LICENSE file.
/**
- * @fileoverview
- * 'settings-clear-browsing-data-page' provides options to delete browsing
- * data that has been cached by chromium.
- *
- * Example:
- *
- * <iron-animated-pages>
- * <settings-clear-browsing-data-page prefs="{{prefs}}">
- * </settings-clear-browsing-data-page>
- * ... other pages ...
- * </iron-animated-pages>
+ * @fileoverview 'settings-clear-browsing-data-dialog' allows the user to delete
+ * browsing data that has been cached by Chromium.
*/
Polymer({
is: 'settings-clear-browsing-data-dialog',
+ behaviors: [WebUIListenerBehavior],
+
properties: {
/**
* Preferences state.
@@ -28,14 +21,6 @@ Polymer({
},
/**
- * The current active route.
- */
- currentRoute: {
- type: Object,
- notify: true,
- },
-
- /**
* List of options for the dropdown menu.
* @private {!DropdownMenuOptionList>}
*/
@@ -50,39 +35,34 @@ Polymer({
{value: 4, name: loadTimeData.getString('clearDataEverything')},
],
},
- },
- ready: function() {
- this.$.clearFrom.menuOptions = this.clearFromOptions_;
+ /** @private */
+ clearingInProgress_: Boolean,
},
- attached: function() {
- var self = this;
- cr.define('SettingsClearBrowserData', function() {
- return {
- doneClearing: function() {
- return self.doneClearing_.apply(self, arguments);
- },
- setAllowDeletingHistory: function() {
- return self.setAllowDeletingHistory_.apply(self, arguments);
- },
- };
- });
- },
+ /** @private {!settings.ClearBrowsingDataBrowserProxy} */
+ browserProxy_: null,
- /** @private */
- doneClearing_: function() {
- // TODO(dschuyler): inform the user on whether clearing data was successful.
+ /** @override */
+ ready: function() {
+ this.$.clearFrom.menuOptions = this.clearFromOptions_;
+ this.addWebUIListener(
+ 'browsing-history-pref-changed',
+ this.setAllowDeletingHistory_.bind(this));
+ this.addWebUIListener(
+ 'update-footer',
+ this.updateFooter_.bind(this));
+ this.browserProxy_ =
+ settings.ClearBrowsingDataBrowserProxyImpl.getInstance();
+ this.browserProxy_.initialize();
+ this.$.dialog.open();
},
/**
- * @private
* @param {boolean} allowed Whether the user is allowed to delete histories.
+ * @private
*/
setAllowDeletingHistory_: function(allowed) {
- // This is called from c++, protect against poor timing.
- if (!this.$)
- return;
this.$.browsingCheckbox.disabled = !allowed;
this.$.downloadCheckbox.disabled = !allowed;
if (!allowed) {
@@ -91,16 +71,29 @@ Polymer({
}
},
+ /**
+ * Updates the footer to show only those sentences that are relevant to this
+ * user.
+ * @param {boolean} syncing Whether the user is syncing data.
+ * @param {boolean} otherFormsOfBrowsingHistory Whether the user has other
+ * forms of browsing history in their account.
+ * @private
+ */
+ updateFooter_: function(syncing, otherFormsOfBrowsingHistory) {
+ this.$.googleFooter.hidden = !otherFormsOfBrowsingHistory;
+ this.$.syncedDataSentence.hidden = !syncing;
+ },
+
open: function() {
this.$.dialog.open();
},
- /**
- * @param {!Event} event Tells us whether to perform an action or cancel.
- * @private
- */
- onDialogClosed_: function(event) {
- if (event.detail.confirmed)
- chrome.send('performClearBrowserData');
+ /** @private */
+ onClearBrowsingDataTap_: function() {
+ this.clearingInProgress_ = true;
+ this.browserProxy_.clearBrowsingData().then(function() {
+ this.clearingInProgress_ = false;
+ this.$.dialog.close();
+ }.bind(this));
},
});
diff --git a/chromium/chrome/browser/resources/settings/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
index f6f6c522984..8f82f53d4ce 100644
--- a/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
@@ -7,6 +7,7 @@
'target_name': 'settings_resources',
'type': 'none',
'dependencies': [
+ 'about_page/compiled_resources2.gyp:*',
'advanced_page/compiled_resources2.gyp:*',
'appearance_page/compiled_resources2.gyp:*',
'basic_page/compiled_resources2.gyp:*',
diff --git a/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp
index 962857a6bb7..7d82bb1aec5 100644
--- a/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/controls/compiled_resources2.gyp
@@ -28,7 +28,6 @@
'<(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',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):settings_private',
'../prefs/compiled_resources2.gyp:pref_util',
'pref_control_behavior',
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
index 15b0fb57890..9d2cab66119 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -9,22 +9,14 @@
<dom-module id="settings-checkbox">
<link rel="import" type="css" href="chrome://resources/cr_elements/shared.css">
<template>
- <style is="custom-style" include="settings-shared">
+ <style include="settings-shared">
:host {
align-items: center;
display: flex;
min-height: 40px;
}
- paper-checkbox {
- --paper-checkbox-label-spacing: var(--checkbox-spacing);
- --paper-checkbox-size: var(--checkbox-size);
- --paper-checkbox-checked-color: var(--google-blue-500);
- --paper-checkbox-unchecked-color: var(--paper-grey-600);
- -webkit-margin-start: var(--checkbox-margin-start);
- }
-
- .secondary {
+ .secondary:not(:empty) {
@apply(--settings-secondary);
}
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 65e00bfe1aa..e8d9f5ade5e 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
@@ -1,8 +1,7 @@
-<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-dropdown-menu/paper-dropdown-menu.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-listbox/paper-listbox.html">
<link rel="import" href="chrome://md-settings/controls/pref_control_behavior.html">
<link rel="import" href="chrome://md-settings/prefs/pref_util.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
@@ -29,16 +28,16 @@
<paper-dropdown-menu id="dropdownMenu" label="[[menuLabel_]]"
on-iron-select="onSelect_" no-label-float$="[[noLabelFloat]]"
disabled="[[shouldDisableMenu_(disabled, menuOptions.*)]]">
- <paper-menu class="dropdown-content" selected="{{selected_}}"
+ <paper-listbox class="dropdown-content" selected="{{selected_}}"
attr-for-selected="data-value">
<template is="dom-repeat" items="[[menuOptions]]">
<paper-item data-value$="[[item.value]]">[[item.name]]</paper-item>
</template>
<paper-item data-value$="[[notFoundValue_]]"
hidden$="[[!isSelectedNotFound_(selected_)]]">
- [[i18n('custom')]]
+ $i18n{custom}
</paper-item>
- </paper-menu>
+ </paper-listbox>
</paper-dropdown-menu>
</template>
<script src="settings_dropdown_menu.js"></script>
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 c26c9268712..56d27d2c29f 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
+++ b/chromium/chrome/browser/resources/settings/controls/settings_dropdown_menu.js
@@ -75,7 +75,6 @@ Polymer({
},
behaviors: [
- I18nBehavior,
PrefControlBehavior,
],
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_radio_group.css b/chromium/chrome/browser/resources/settings/controls/settings_radio_group.css
deleted file mode 100644
index 9ff03faeb2f..00000000000
--- a/chromium/chrome/browser/resources/settings/controls/settings_radio_group.css
+++ /dev/null
@@ -1,11 +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. */
-
-:host {
- display: block;
-}
-
-paper-radio-group {
- width: 100%;
-}
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_radio_group.html b/chromium/chrome/browser/resources/settings/controls/settings_radio_group.html
index a5a5143da02..39986b2748e 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_radio_group.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_radio_group.html
@@ -3,18 +3,11 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
<link rel="import" href="chrome://md-settings/controls/pref_control_behavior.html">
<link rel="import" href="chrome://md-settings/prefs/pref_util.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-radio-group">
- <link rel="import" type="css" href="settings_radio_group.css">
+ <style include="settings-shared"></style>
<template>
- <style is="custom-style">
- :host ::content paper-radio-button {
- @apply(--layout-center);
- display: flex;
- min-height: 40px;
- padding: 0;
- }
- </style>
<div>[[label]]</div>
<paper-radio-group selected="{{selected}}">
<content></content>
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 a935f11dd5b..7778730af0b 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
@@ -7,12 +7,11 @@
<template>
<style include="settings-shared"></style>
<div class="settings-box first block">
- <div i18n-content="timeZone"></div>
+ <div>$i18n{timeZone}</div>
<settings-checkbox pref="{{prefs.settings.clock.use_24hour_clock}}"
- i18n-values="label:use24HourClock">
+ label="$i18n{use24HourClock}">
</settings-checkbox>
- <div id="setAutomatically" i18n-content="dateTimeSetAutomatically">
- </div>
+ <div id="setAutomatically">$i18n{dateTimeSetAutomatically}</div>
</div>
</template>
<script src="date_time_page.js"></script>
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 53000ef6cff..f99f27a919b 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
@@ -1,7 +1,7 @@
-<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-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-default-browser-page">
@@ -11,12 +11,12 @@
<div class="settings-box first two-line">
<template is="dom-if" if="[[showButton_]]">
<div class="start" on-tap="onSetDefaultBrowserTap_">
- <div>[[i18n('defaultBrowser')]]</div>
- <div class="secondary">[[i18n('defaultBrowserMakeDefault')]]</div>
+ <div>$i18n{defaultBrowser}</div>
+ <div class="secondary">$i18n{defaultBrowserMakeDefault}</div>
</div>
<template is="dom-if" if="[[showError_]]">
- <iron-icon icon="error" class="error-icon"
- title="[[i18n('unableToSetDefaultBrowser')]]"></iron-icon>
+ <iron-icon icon="settings:error" class="error-icon"
+ title="$i18n{unableToSetDefaultBrowser}"></iron-icon>
</template>
</template>
<template is="dom-if" if="[[!showButton_]]">
diff --git a/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.js b/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.js
index 694ece0ca9c..09d49fa298c 100644
--- a/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.js
+++ b/chromium/chrome/browser/resources/settings/default_browser_page/default_browser_page.js
@@ -6,14 +6,6 @@
* @fileoverview
* 'settings-default-browser-page' is the settings page that contains
* settings to change the default browser (i.e. which the OS will open).
- *
- * Example:
- *
- * <iron-animated-pages>
- * <settings-default-browser-page>
- * </settings-default-browser-page>
- * ... other pages ...
- * </iron-animated-pages>
*/
Polymer({
is: 'settings-default-browser-page',
@@ -59,10 +51,6 @@ Polymer({
},
},
- behaviors: [
- I18nBehavior,
- ],
-
ready: function() {
var self = this;
cr.define('Settings', function() {
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 67a7d9c82af..6541d926ff1 100644
--- a/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
@@ -6,26 +6,42 @@
{
'target_name': 'device_page',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'device_page_browser_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'touchpad',
+ 'dependencies': [
+ 'device_page_browser_proxy'
+ ],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'keyboard',
'dependencies': [
+ '../prefs/compiled_resources2.gyp:prefs_behavior',
+ '../prefs/compiled_resources2.gyp:prefs_types',
+ '<(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',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(EXTERNS_GYP):settings_private',
+ 'device_page_browser_proxy'
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'display',
'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-slider/compiled_resources2.gyp:paper-slider-extracted',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):system_display',
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 d541f8d2613..a55bbc0ad85 100644
--- a/chromium/chrome/browser/resources/settings/device_page/device_page.html
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page.html
@@ -1,13 +1,12 @@
<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/iron-icons/hardware-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/image-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html">
+<link rel="import" href="chrome://md-settings/device_page/device_page_browser_proxy.html">
<link rel="import" href="chrome://md-settings/device_page/display.html">
<link rel="import" href="chrome://md-settings/device_page/keyboard.html">
<link rel="import" href="chrome://md-settings/device_page/touchpad.html">
-<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/prefs/prefs.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_subpage.html">
@@ -19,17 +18,18 @@
<settings-animated-pages id="pages" section="device"
current-route="{{currentRoute}}">
<neon-animatable id="main">
- <div class="settings-box first" on-tap="onTouchpadTap_">
+ <div id="touchpadRow" class="settings-box first"
+ on-tap="onTouchpadTap_">
<!-- TODO(michaelpg): Get a touchpad icon. -->
- <iron-icon icon="image:brightness-1"></iron-icon>
+ <iron-icon icon="settings:brightness-1"></iron-icon>
<div class="middle">$i18n{touchpadTitle}</div>
</div>
<div id="keyboardRow" class="settings-box" on-tap="onKeyboardTap_">
- <iron-icon icon="hardware:keyboard"></iron-icon>
+ <iron-icon icon="settings:keyboard"></iron-icon>
<div class="middle">$i18n{keyboardTitle}</div>
</div>
<div id="displayRow" class="settings-box" on-tap="onDisplayTap_">
- <iron-icon icon="hardware:desktop-windows"></iron-icon>
+ <iron-icon icon="settings:desktop-windows"></iron-icon>
<div class="middle">$i18n{displayTitle}</div>
</div>
</neon-animatable>
@@ -40,7 +40,8 @@
</template>
<template is="dom-if" name="keyboard">
<settings-subpage page-title="$i18n{keyboardTitle}">
- <settings-keyboard prefs="{{prefs}}"></settings-keyboard>
+ <settings-keyboard prefs="{{prefs}}" current-route="{{currentRoute}}">
+ </settings-keyboard>
</settings-subpage>
</template>
<template is="dom-if" name="display">
diff --git a/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.html b/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.html
new file mode 100644
index 00000000000..127edfa276d
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://md-settings/device_page/device_page_browser_proxy.js"></script>
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
new file mode 100644
index 00000000000..ad9077dd51f
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page_browser_proxy.js
@@ -0,0 +1,56 @@
+// 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 A helper object used for testing the Device page. */
+cr.define('settings', function() {
+ /** @interface */
+ function DevicePageBrowserProxy() {}
+
+ DevicePageBrowserProxy.prototype = {
+ /**
+ * Override to interact with the on-tap/on-keydown event on the Learn More
+ * link.
+ * @param {!Event} e
+ */
+ handleLinkEvent: function(e) {},
+
+ /** Initializes the keyboard WebUI handler. */
+ initializeKeyboard: function() {},
+
+ /** Shows the Ash keyboard shortcuts overlay. */
+ showKeyboardShortcutsOverlay: function() {},
+ };
+
+ /**
+ * @constructor
+ * @implements {settings.DevicePageBrowserProxy}
+ */
+ function DevicePageBrowserProxyImpl() {}
+ cr.addSingletonGetter(DevicePageBrowserProxyImpl);
+
+ DevicePageBrowserProxyImpl.prototype = {
+ /** override */
+ handleLinkEvent: function(e) {
+ // Prevent the link from activating its parent element when tapped or
+ // when Enter is pressed.
+ if (e.type != 'keydown' || e.keyCode == 13)
+ e.stopPropagation();
+ },
+
+ /** @override */
+ initializeKeyboard: function() {
+ chrome.send('initializeKeyboardSettings');
+ },
+
+ /** @override */
+ showKeyboardShortcutsOverlay: function() {
+ chrome.send('showKeyboardShortcutsOverlay');
+ },
+ };
+
+ return {
+ DevicePageBrowserProxy: DevicePageBrowserProxy,
+ DevicePageBrowserProxyImpl: DevicePageBrowserProxyImpl,
+ };
+});
diff --git a/chromium/chrome/browser/resources/settings/device_page/display.html b/chromium/chrome/browser/resources/settings/device_page/display.html
index 14597761355..026006e27dc 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display.html
+++ b/chromium/chrome/browser/resources/settings/device_page/display.html
@@ -5,6 +5,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-slider/paper-slider.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-display">
@@ -18,46 +19,75 @@
}
.settings-box.embedded {
+ align-self: stretch;
margin-left: 20px;
padding: 0;
}
/* TODO(stevenjb): Placeholder */
.display-area {
+ align-self: stretch;
border: lightgrey solid 1px;
- height: 300px;
+ flex: 1 1;
+ height: 200px;
margin: 10px;
- width: 600px;
+ }
+
+ .textarea {
+ margin: 10px 0;
+ }
+
+ .info-text {
+ color: var(--paper-grey-500);
}
</style>
- <div class="settings-box first layout vertical">
+ <div class="settings-box first layout vertical self-stretch">
<div class="display-section">$i18n{displayArrangement}</div>
- <!-- TODO(stevenjb): Placeholder -->
- <div class="display-area"></div>
+ <div class="display-area">
+ <!-- TODO(stevenjb): Support layout -->
+ <template is="dom-repeat" items="[[displays]]">
+ <paper-button toggles active="[[isSelected_(item, selectedDisplay)]]"
+ on-tap="onSelectDisplayTap_" id="[[item.id]]">
+ [[item.name]]
+ </paper-button>
+ </template>
+ </div>
</div>
<div class="settings-box layout vertical">
<div class="display-section">[[selectedDisplay.name]]</div>
- <div class="settings-box embedded first self-stretch"
- hidden$="[[!hasMultipleDisplays_(displays)]]">
- <paper-checkbox class="flex" checked="[[isMirrored_(selectedDisplay)]]">
+ <div class="settings-box embedded first">
+ <paper-checkbox class="flex" checked="[[isMirrored_(displays)]]"
+ hidden$="[[!showMirror_(displays)]]" on-tap="onMirroredTap_">
$i18n{displayMirror}
</paper-checkbox>
- <paper-button hidden$="[[selectedDisplay.isPrimary]]">
+ <paper-button
+ hidden$="[[!showMakePrimary_(selectedDisplay, primaryDisplayId)]]"
+ on-tap="onMakePrimaryTap_">
$i18n{displayMakePrimary}
</paper-button>
</div>
- <div class="settings-box embedded self-stretch">
- <div class="start">$i18n{displayResolution}</div>
- <!-- TODO(stevenjb): Implement -->
- <paper-slider disabled></paper-slider>
+ <div class="settings-box embedded horizontal justified">
+ <div class="start textarea layout vertical">
+ <div>$i18n{displayResolutionTitle}</div>
+ <div class="info-text layout self-start">
+ [[getResolutionText_(selectedDisplay, immediateSelectedModeIndex_)]]
+ </div>
+ </div>
+ <paper-slider snaps max-markers="100" step="1"
+ disabled="[[!enableSetResolution_(selectedDisplay)]]"
+ min="0" max="[[maxModeIndex_]]"
+ value="[[selectedModeIndex_]]"
+ immediate-value="{{immediateSelectedModeIndex_}}"
+ on-change="onChangeMode_">
+ </paper-slider>
</div>
- <div class="settings-box embedded self-stretch">
- <div class="start">$i18n{displayOrientation}</div>
+ <div class="settings-box embedded">
+ <div class="start textarea">$i18n{displayOrientation}</div>
<paper-dropdown-menu>
<paper-listbox class="dropdown-content"
- selected="[[selectedDisplay.rotation]]"
- attr-for-selected="value"
- on-iron-activate="onSetOrientation_">
+ selected="[[selectedDisplay.rotation]]"
+ attr-for-selected="value"
+ on-iron-activate="onSetOrientation_">
<paper-item value="0">$i18n{displayOrientationStandard}
</paper-item>
<paper-item value="90">90</paper-item>
diff --git a/chromium/chrome/browser/resources/settings/device_page/display.js b/chromium/chrome/browser/resources/settings/device_page/display.js
index 3c2edb20b47..0bbf2f3888d 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display.js
+++ b/chromium/chrome/browser/resources/settings/device_page/display.js
@@ -26,10 +26,10 @@ Polymer({
properties: {
/**
- * Map of displays by id.
- * @type {!Object<!chrome.system.display.DisplayUnitInfo>}
+ * Array of displays.
+ * @type {!Array<!chrome.system.display.DisplayUnitInfo>}
*/
- displays: Object,
+ displays: Array,
/** Primary display id */
primaryDisplayId: String,
@@ -38,7 +38,16 @@ Polymer({
* Selected display
* @type {!chrome.system.display.DisplayUnitInfo|undefined}
*/
- selectedDisplay: Object,
+ selectedDisplay: {type: Object, observer: 'selectedDisplayChanged_'},
+
+ /** Maximum mode index value for slider. */
+ maxModeIndex_: {type: Number, value: 0},
+
+ /** Selected mode index value for slider. */
+ selectedModeIndex_: {type: Number},
+
+ /** Immediate selected mode index value for slider. */
+ immediateSelectedModeIndex_: {type: Number, value: 0}
},
/**
@@ -70,31 +79,204 @@ Polymer({
this.updateDisplayInfo_.bind(this));
},
+ /**
+ * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
+ * @return {number}
+ * @private
+ */
+ getSelectedModeIndex_: function(selectedDisplay) {
+ for (var i = 0; i < selectedDisplay.modes.length; ++i) {
+ if (selectedDisplay.modes[i].isSelected)
+ return i;
+ }
+ return 0;
+ },
+
/** @private */
- hasMultipleDisplays_: function(displays) {
- return Object.keys(displays).length > 1;
+ selectedDisplayChanged_: function() {
+ // Set maxModeIndex first so that the slider updates correctly.
+ if (this.selectedDisplay.modes.length == 0) {
+ this.maxModeIndex_ = 0;
+ this.selectedModeIndex_ = 0;
+ return;
+ }
+ this.maxModeIndex_ = this.selectedDisplay.modes.length - 1;
+ this.selectedModeIndex_ = this.getSelectedModeIndex_(this.selectedDisplay);
+ },
+
+ /**
+ * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
+ * @param {string} primaryDisplayId
+ * @return {boolean}
+ * @private
+ */
+ showMakePrimary_: function(selectedDisplay, primaryDisplayId) {
+ return !!selectedDisplay && selectedDisplay.id != primaryDisplayId;
+ },
+
+ /**
+ * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
+ * @return {boolean}
+ * @private
+ */
+ showMirror_: function(displays) {
+ return this.isMirrored_(displays) || displays.length == 2;
+ },
+
+ /**
+ * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
+ * @return {boolean}
+ * @private
+ */
+ isMirrored_: function(displays) {
+ return displays.length > 0 && !!displays[0].mirroringSourceId;
+ },
+
+ /**
+ * @param {!chrome.system.display.DisplayUnitInfo} display
+ * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
+ * @return {boolean}
+ * @private
+ */
+ isSelected_: function(display, selectedDisplay) {
+ return display.id == selectedDisplay.id;
+ },
+
+ /**
+ * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
+ * @return {boolean}
+ * @private
+ */
+ enableSetResolution_: function(selectedDisplay) {
+ return selectedDisplay.modes.length > 1;
+ },
+
+ /**
+ * @param {!chrome.system.display.DisplayUnitInfo} selectedDisplay
+ * @param {number} immediateSelectedModeIndex
+ * @return {string}
+ * @private
+ */
+ getResolutionText_: function(selectedDisplay, immediateSelectedModeIndex) {
+ if (this.selectedDisplay.modes.length == 0) {
+ var widthStr = selectedDisplay.bounds.width.toString();
+ var heightStr = selectedDisplay.bounds.height.toString();
+ return this.i18n('displayResolutionText', widthStr, heightStr);
+ }
+ if (isNaN(immediateSelectedModeIndex))
+ immediateSelectedModeIndex = this.getSelectedModeIndex_(selectedDisplay);
+ var mode = selectedDisplay.modes[immediateSelectedModeIndex];
+ var best = selectedDisplay.isInternal ? mode.uiScale == 1.0 : mode.isNative;
+ var widthStr = mode.width.toString();
+ var heightStr = mode.height.toString();
+ if (best)
+ return this.i18n('displayResolutionTextBest', widthStr, heightStr);
+ else if (mode.isNative)
+ return this.i18n('displayResolutionTextNative', widthStr, heightStr);
+ return this.i18n('displayResolutionText', widthStr, heightStr);
+ },
+
+ /**
+ * @param {!{model: !{index: number}, target: !PaperButtonElement}} e
+ * @private
+ */
+ onSelectDisplayTap_: function(e) {
+ this.selectedDisplay = this.displays[e.model.index];
+ // Force active in case selected display was clicked.
+ e.target.active = true;
},
/** @private */
- isMirrored_: function(selectedDisplay) {
- return !!this.selectedDisplay.mirroringSourceId;
+ onMakePrimaryTap_: function() {
+ if (!this.selectedDisplay)
+ return;
+ if (this.selectedDisplay.id == this.primaryDisplayId)
+ return;
+ /** @type {!chrome.system.display.DisplayProperties} */ var properties = {
+ isPrimary: true
+ };
+ settings.display.systemDisplayApi.setDisplayProperties(
+ this.selectedDisplay.id, properties,
+ this.setPropertiesCallback_.bind(this));
+ },
+
+ /**
+ * @param {!{target: !PaperSliderElement}} e
+ * @private
+ */
+ onChangeMode_: function(e) {
+ var curIndex = this.selectedModeIndex_;
+ var newIndex = parseInt(e.target.value, 10);
+ if (newIndex == curIndex)
+ return;
+ assert(newIndex >= 0);
+ assert(newIndex < this.selectedDisplay.modes.length);
+ /** @type {!chrome.system.display.DisplayProperties} */ var properties = {
+ displayMode: this.selectedDisplay.modes[newIndex]
+ };
+ settings.display.systemDisplayApi.setDisplayProperties(
+ this.selectedDisplay.id, properties,
+ this.setPropertiesCallback_.bind(this));
},
/**
- * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displaysArray
+ * @param {!{detail: !{selected: string}}} e
* @private
*/
- updateDisplayInfo_(displaysArray) {
- var displays = {};
- this.primaryDisplayId = '';
- for (var i = 0; i < displaysArray.length; ++i) {
- var display = displaysArray[i];
- displays[display.id] = display;
- if (display.isPrimary && !this.primaryDisplayId)
- this.primaryDisplayId = display.id;
+ onSetOrientation_: function(e) {
+ /** @type {!chrome.system.display.DisplayProperties} */ var properties = {
+ rotation: parseInt(e.detail.selected, 10)
+ };
+ settings.display.systemDisplayApi.setDisplayProperties(
+ this.selectedDisplay.id, properties,
+ this.setPropertiesCallback_.bind(this));
+ },
+
+ /** @private */
+ onMirroredTap_: function() {
+ var id = '';
+ /** @type {!chrome.system.display.DisplayProperties} */ var properties = {};
+ if (this.isMirrored_(this.displays)) {
+ id = this.primaryDisplayId;
+ properties.mirroringSourceId = '';
+ } else {
+ // Set the mirroringSourceId of the secondary (first non-primary) display.
+ for (var display of this.displays) {
+ if (display.id != this.primaryDisplayId) {
+ id = display.id;
+ break;
+ }
+ }
+ properties.mirroringSourceId = this.primaryDisplayId;
}
+ settings.display.systemDisplayApi.setDisplayProperties(
+ id, properties, this.setPropertiesCallback_.bind(this));
+ },
+
+ /**
+ * @param {!Array<!chrome.system.display.DisplayUnitInfo>} displays
+ * @private
+ */
+ updateDisplayInfo_(displays) {
this.displays = displays;
- // Always update selectedDisplay.
- this.selectedDisplay = this.displays[this.primaryDisplayId];
+ var primaryDisplay = undefined;
+ var selectedDisplay = undefined;
+ for (var display of this.displays) {
+ if (display.isPrimary && !primaryDisplay)
+ primaryDisplay = display;
+ if (this.selectedDisplay && display.id == this.selectedDisplay.id)
+ selectedDisplay = display;
+ }
+ this.primaryDisplayId = (primaryDisplay && primaryDisplay.id) || '';
+ this.selectedDisplay = selectedDisplay || primaryDisplay ||
+ (this.displays && this.displays[0]);
+ },
+
+ /** @private */
+ setPropertiesCallback_: function() {
+ if (chrome.runtime.lastError) {
+ console.error(
+ 'setDisplayProperties Error: ' + chrome.runtime.lastError.message);
+ }
},
});
diff --git a/chromium/chrome/browser/resources/settings/device_page/keyboard.html b/chromium/chrome/browser/resources/settings/device_page/keyboard.html
index 75187a21cbc..7289495dcad 100644
--- a/chromium/chrome/browser/resources/settings/device_page/keyboard.html
+++ b/chromium/chrome/browser/resources/settings/device_page/keyboard.html
@@ -1,28 +1,32 @@
<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-collapse/iron-collapse.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-slider/paper-slider.html">
<link rel="import" href="chrome://md-settings/controls/settings_checkbox.html">
<link rel="import" href="chrome://md-settings/controls/settings_dropdown_menu.html">
+<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://md-settings/prefs/prefs_behavior.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-keyboard">
<template>
<style include="settings-shared"></style>
<div class="settings-box first">
- <div class="start">[[i18n('keyboardKeySearch')]]</div>
+ <div class="start">$i18n{keyboardKeySearch}</div>
<settings-dropdown-menu
pref="{{prefs.settings.language.xkb_remap_search_key_to}}"
menu-options="[[keyMapTargetsWithCapsLock_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
- <div class="start">[[i18n('keyboardKeyCtrl')]]</div>
+ <div class="start">$i18n{keyboardKeyCtrl}</div>
<settings-dropdown-menu
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>
+ <div class="start">$i18n{keyboardKeyAlt}</div>
<settings-dropdown-menu
pref="{{prefs.settings.language.xkb_remap_alt_key_to}}"
menu-options="[[keyMapTargets_]]">
@@ -30,7 +34,7 @@
</div>
<template is="dom-if" if="[[showCapsLock_]]">
<div class="settings-box" id="capsLockKey">
- <div class="start">[[i18n('keyboardKeyCapsLock')]]</div>
+ <div class="start">$i18n{keyboardKeyCapsLock}</div>
<settings-dropdown-menu
pref="{{prefs.settings.language.remap_caps_lock_key_to}}"
menu-options="[[keyMapTargetsWithCapsLock_]]">
@@ -39,7 +43,7 @@
</template>
<template is="dom-if" if="[[showDiamondKey_]]">
<div class="settings-box" id="diamondKey">
- <div class="start">[[i18n('keyboardKeyDiamond')]]</div>
+ <div class="start">$i18n{keyboardKeyDiamond}</div>
<settings-dropdown-menu
pref="{{prefs.settings.language.remap_diamond_key_to}}"
menu-options="[[keyMapTargets_]]">
@@ -49,13 +53,51 @@
<div class="settings-box two-line">
<settings-checkbox
pref="{{prefs.settings.language.send_function_keys}}"
- label="[[i18n('keyboardSendFunctionKeys')]]"
- sub-label="[[i18n('keyboardSendFunctionKeysDescription')]]">
+ label="$i18n{keyboardSendFunctionKeys}"
+ sub-label="$i18n{keyboardSendFunctionKeysDescription}">
</settings-checkbox>
</div>
- <!-- TODO(michaelpg): Auto-repeat options. -->
- <!-- TODO(michaelpg): Keyboard shortcuts button. -->
- <!-- TODO(michaelpg): Language & input button. -->
+ <div class="settings-box">
+ <settings-checkbox
+ pref="{{prefs.settings.language.xkb_auto_repeat_enabled_r2}}"
+ label="$i18n{keyboardEnableAutoRepeat}">
+ </settings-checkbox>
+ </div>
+ <iron-collapse
+ 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>
+ <div class="layout horizontal center">
+ <div>$i18n{keyRepeatDelayLong}</div>
+ <paper-slider id="delaySlider" class="always-on" snaps
+ max="[[delayMaxTick_()]]" on-change="onDelaySliderChange_"
+ disabled="[[!prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]"
+ aria-labelledby="repeatDelayLabel">
+ </paper-slider>
+ <div>$i18n{keyRepeatDelayShort}</div>
+ </div>
+ </div>
+ <div class="settings-box continuation settings-checkbox-spacer">
+ <div class="start" id="repeatRateLabel">$i18n{keyRepeatRate}</div>
+ <div class="layout horizontal center">
+ <div>$i18n{keyRepeatRateSlow}</div>
+ <paper-slider id="repeatRateSlider" class="always-on" snaps
+ max="[[repeatRateMaxTick_()]]"
+ on-change="onRepeatRateSliderChange_"
+ disabled="{{!prefs.settings.language.xkb_auto_repeat_enabled_r2.value}}"
+ aria-labelledby="repeatRateLabel">
+ </paper-slider>
+ <div>$i18n{keyRepeatRateFast}</div>
+ </div>
+ </div>
+ </iron-collapse>
+ <div id="keyboardOverlay" class="settings-box"
+ on-tap="onShowKeyboardShortcutsOverlayTap_">
+ $i18n{showKeyboardShortcutsOverlay}
+ </div>
+ <div class="settings-box" on-tap="onShowLanguageInputTap_">
+ $i18n{keyboardShowLanguageAndInput}
+ </div>
</template>
<script src="keyboard.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/device_page/keyboard.js b/chromium/chrome/browser/resources/settings/device_page/keyboard.js
index 0c538902414..730d4545c68 100644
--- a/chromium/chrome/browser/resources/settings/device_page/keyboard.js
+++ b/chromium/chrome/browser/resources/settings/device_page/keyboard.js
@@ -16,11 +16,34 @@ var DropdownMenuOption;
/** @typedef {!Array<!DropdownMenuOption>} */
var DropdownMenuOptionList;
+/**
+ * Auto-repeat delays (in ms) for the corresponding slider values, from
+ * long to short. The values were chosen to provide a large range while giving
+ * several options near the defaults.
+ * @type {!Array<number>}
+ * @const
+ */
+var AUTO_REPEAT_DELAYS =
+ [2000, 1500, 1000, 500, 300, 200, 150];
+
+/**
+ * Auto-repeat intervals (in ms) for the corresponding slider values, from
+ * long to short. The slider itself is labeled "rate", the inverse of
+ * interval, and goes from slow (long interval) to fast (short interval).
+ * @type {!Array<number>}
+ * @const
+ */
+var AUTO_REPEAT_INTERVALS =
+ [2000, 1000, 500, 300, 200, 100, 50, 30, 20];
+
+var AUTO_REPEAT_DELAY_PREF = 'settings.language.xkb_auto_repeat_delay_r2';
+var AUTO_REPEAT_INTERVAL_PREF = 'settings.language.xkb_auto_repeat_interval_r2';
+
Polymer({
is: 'settings-keyboard',
behaviors: [
- I18nBehavior,
+ PrefsBehavior,
],
properties: {
@@ -30,6 +53,12 @@ Polymer({
notify: true,
},
+ /** The current active route. */
+ currentRoute: {
+ type: Object,
+ notify: true,
+ },
+
/** @private Whether to show Caps Lock options. */
showCapsLock_: Boolean,
@@ -46,10 +75,17 @@ Polymer({
keyMapTargetsWithCapsLock_: Object,
},
+ observers: [
+ 'autoRepeatDelayPrefChanged_(' +
+ 'prefs.' + AUTO_REPEAT_DELAY_PREF + '.*)',
+ 'autoRepeatIntervalPrefChanged_(' +
+ 'prefs.' + AUTO_REPEAT_INTERVAL_PREF + '.*)',
+ ],
+
/** @override */
ready: function() {
cr.addWebUIListener('show-keys-changed', this.onShowKeysChange_.bind(this));
- chrome.send('initializeKeyboardSettings');
+ settings.DevicePageBrowserProxyImpl.getInstance().initializeKeyboard();
this.setUpKeyMapTargets_();
},
@@ -84,4 +120,91 @@ Polymer({
this.showCapsLock_ = showCapsLock;
this.showDiamondKey_ = showDiamondKey;
},
+
+ onShowKeyboardShortcutsOverlayTap_: function() {
+ settings.DevicePageBrowserProxyImpl.getInstance()
+ .showKeyboardShortcutsOverlay();
+ },
+
+ onShowLanguageInputTap_: function() {
+ this.currentRoute = {
+ page: 'advanced',
+ section: 'languages',
+ subpage: [],
+ };
+ },
+
+ /** @private */
+ autoRepeatDelayPrefChanged_: function() {
+ var delay = /** @type number */(this.getPref(AUTO_REPEAT_DELAY_PREF).value);
+ this.$.delaySlider.value =
+ this.findNearestIndex_(AUTO_REPEAT_DELAYS, delay);
+ },
+
+ /** @private */
+ autoRepeatIntervalPrefChanged_: function() {
+ var interval = /** @type number */(
+ this.getPref(AUTO_REPEAT_INTERVAL_PREF).value);
+ this.$.repeatRateSlider.value =
+ this.findNearestIndex_(AUTO_REPEAT_INTERVALS, interval);
+ },
+
+ /** @private */
+ onDelaySliderChange_: function() {
+ var index = this.$.delaySlider.value;
+ assert(index >= 0 && index < AUTO_REPEAT_DELAYS.length);
+ this.setPrefValue(AUTO_REPEAT_DELAY_PREF, AUTO_REPEAT_DELAYS[index]);
+ },
+
+ /** @private */
+ onRepeatRateSliderChange_: function() {
+ var index = this.$.repeatRateSlider.value;
+ assert(index >= 0 && index < AUTO_REPEAT_INTERVALS.length);
+ this.setPrefValue(AUTO_REPEAT_INTERVAL_PREF, AUTO_REPEAT_INTERVALS[index]);
+ },
+
+ /**
+ * @return {number}
+ * @private
+ */
+ delayMaxTick_: function() {
+ return AUTO_REPEAT_DELAYS.length - 1;
+ },
+
+ /**
+ * @return {number}
+ * @private
+ */
+ repeatRateMaxTick_: function() {
+ return AUTO_REPEAT_INTERVALS.length - 1;
+ },
+
+ /**
+ * Returns the index of the item in |arr| closest to |value|. Same cost as
+ * Array.prototype.indexOf if an exact match exists.
+ * @param {!Array<number>} arr
+ * @param {number} value
+ * @return {number}
+ * @private
+ */
+ findNearestIndex_: function(arr, value) {
+ assert(arr.length);
+
+ // The common case has an exact match.
+ var closestIndex = arr.indexOf(value);
+ if (closestIndex != -1)
+ return closestIndex;
+
+ // No exact match. Find the element closest to |value|.
+ 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;
+ }
+ }
+
+ return closestIndex;
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/device_page/touchpad.html b/chromium/chrome/browser/resources/settings/device_page/touchpad.html
index af7a0fa6a31..30ad15c0b06 100644
--- a/chromium/chrome/browser/resources/settings/device_page/touchpad.html
+++ b/chromium/chrome/browser/resources/settings/device_page/touchpad.html
@@ -10,22 +10,26 @@
<!-- TODO(michaelpg): Add touchpad speed slider. -->
<div class="settings-box block first">
<settings-checkbox pref="{{prefs.settings.touchpad.enable_tap_to_click}}"
- i18n-values="label:touchpadTapToClickEnabledLabel">
+ label="$i18n{touchpadTapToClickEnabledLabel}">
</settings-checkbox>
<settings-checkbox pref="{{prefs.settings.touchpad.enable_tap_dragging}}"
- i18n-values="label:tapDraggingLabel">
+ label="$i18n{tapDraggingLabel}">
</settings-checkbox>
</div>
- <div class="settings-box" i18n-content="scrollLabel"></div>
+ <div class="settings-box">$i18n{scrollLabel}</div>
<div class="list-frame">
<settings-radio-group pref="{{prefs.settings.touchpad.natural_scroll}}">
- <paper-radio-button name="false" i18n-content="traditionalScrollLabel">
+ <paper-radio-button name="false">
+ $i18n{traditionalScrollLabel}
+ </paper-radio-button>
+ <paper-radio-button name="true">
+ $i18n{naturalScrollLabel}
+ <a href="$i18n{naturalScrollLearnMoreLink}" target="_blank"
+ on-tap="onLearnMoreLinkActivated_"
+ on-keydown="onLearnMoreLinkActivated_">
+ $i18n{naturalScrollLearnMore}
+ </a>
</paper-radio-button>
- <!-- TODO(michaelpg): Make link inside label clickable.
- https://github.com/PolymerElements/paper-radio-button/issues/86
- -->
- <paper-radio-button name="true"
- i18n-values=".innerHTML:naturalScrollLabel"></paper-radio-button>
</settings-radio-group>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/device_page/touchpad.js b/chromium/chrome/browser/resources/settings/device_page/touchpad.js
index b0b3183f194..16ee984f64d 100644
--- a/chromium/chrome/browser/resources/settings/device_page/touchpad.js
+++ b/chromium/chrome/browser/resources/settings/device_page/touchpad.js
@@ -16,4 +16,13 @@ Polymer({
notify: true,
},
},
+
+ /**
+ * Prevents the link from activating its parent paper-radio-button.
+ * @param {!Event} e
+ * @private
+ */
+ onLearnMoreLinkActivated_: function(e) {
+ settings.DevicePageBrowserProxyImpl.getInstance().handleLinkEvent(e);
+ },
});
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 c09ef403936..bb85cd63390 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
+++ b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -14,10 +14,12 @@
<div>$i18n{downloadLocation}</div>
<div class="secondary">[[prefs.download.default_directory.value]]</div>
</div>
- <paper-button class="secondary-action" id="changeDownloadsPath"
- on-tap="selectDownloadLocation_">
- $i18n{changeDownloadLocation}
- </paper-button>
+ <div class="secondary-action">
+ <paper-button class="secondary-button" id="changeDownloadsPath"
+ on-tap="selectDownloadLocation_">
+ $i18n{changeDownloadLocation}
+ </paper-button>
+ </div>
</div>
<div class="settings-box block">
<settings-checkbox pref="{{prefs.download.prompt_for_download}}"
diff --git a/chromium/chrome/browser/resources/settings/icons.html b/chromium/chrome/browser/resources/settings/icons.html
index d4b7ee25f1b..01d9e45e768 100644
--- a/chromium/chrome/browser/resources/settings/icons.html
+++ b/chromium/chrome/browser/resources/settings/icons.html
@@ -1,22 +1,103 @@
<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 name="md-settings-icons" size="48">
+<iron-iconset-svg name="settings" size="24">
<svg>
<defs>
<!-- Cookie SVG obtained from rolfe@ -->
- <g id="cookie" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="SVG-versions" transform="translate(-85.000000, -221.000000)" fill="#000000">
- <g id="accessed_cookies" transform="translate(85.000000, 221.000000)">
- <path d="M31.0002118,15 L31.0002118,14 C31.0002118,12.042 30.0002118,11 28.0002118,11 L27.0002118,11 C26.4482118,11 26.0002118,10.552 26.0002118,10 L26.0002118,6 C26.0002118,4.042 24.0002118,4 24.0002118,4 C12.5972118,4 3.42421177,13.542 4.02821177,25.077 C4.55821177,35.172 12.8282118,43.442 22.9232118,43.972 C34.4582118,44.577 44.0002118,35.403 44.0002118,24 L44.0002118,22 C44.0002118,20.895 43.1052118,20 42.0002118,20 L38.0032118,20 C37.4492118,20 37.0002118,19.551 37.0002118,18.997 L37.0002118,18 C37.0002118,16.125 36.0422118,15.042 34.0002118,15 L31.0002118,15 L31.0002118,15 Z M11.5872118,24.944 C9.47421177,25.345 7.65521177,23.526 8.05621177,21.412 C8.27921177,20.238 9.23921177,19.278 10.4132118,19.056 C12.5262118,18.655 14.3452118,20.474 13.9442118,22.587 C13.7222118,23.761 12.7622118,24.722 11.5872118,24.944 L11.5872118,24.944 Z M15.0562118,14.587 C14.6552118,12.474 16.4742118,10.655 18.5872118,11.056 C19.7612118,11.278 20.7212118,12.238 20.9442118,13.412 C21.3452118,15.526 19.5272118,17.345 17.4132118,16.944 C16.2392118,16.722 15.2782118,15.761 15.0562118,14.587 L15.0562118,14.587 Z M22.5872118,38.944 C20.4732118,39.345 18.6552118,37.526 19.0562118,35.412 C19.2792118,34.238 20.2392118,33.278 21.4132118,33.056 C23.5272118,32.656 25.3452118,34.474 24.9442118,36.587 C24.7222118,37.761 23.7612118,38.722 22.5872118,38.944 L22.5872118,38.944 Z M23.0002118,28 C21.3432118,28 20.0002118,26.657 20.0002118,25 C20.0002118,23.343 21.3432118,22 23.0002118,22 C24.6572118,22 26.0002118,23.343 26.0002118,25 C26.0002118,26.657 24.6572118,28 23.0002118,28 L23.0002118,28 Z M33.0002118,32 C31.3432118,32 30.0002118,30.657 30.0002118,29 C30.0002118,27.343 31.3432118,26 33.0002118,26 C34.6572118,26 36.0002118,27.343 36.0002118,29 C36.0002118,30.657 34.6572118,32 33.0002118,32 L33.0002118,32 Z" id="Imported-Layers"></path>
- </g>
- </g>
+ <g id="cookie">
+ <path d="M15.5 7.5V7c0-.98-.5-1.5-1.5-1.5h-.5c-.276 0-.5-.224-.5-.5V3c0-.98-1-1-1-1C6.3 2 1.712 6.77 2.014 12.54c.265 5.046 4.4 9.18 9.448 9.446C17.23 22.288 22 17.7 22 12v-1c0-.553-.447-1-1-1h-1.998c-.277 0-.502-.225-.502-.502V9c0-.938-.48-1.48-1.5-1.5h-1.5zm-9.706 4.972c-1.057.2-1.966-.71-1.766-1.766.112-.587.592-1.067 1.18-1.178 1.055-.2 1.965.71 1.764 1.765-.11.588-.59 1.068-1.178 1.18zm1.734-5.178c-.2-1.057.71-1.966 1.766-1.766.587.11 1.067.59 1.178 1.178.2 1.057-.708 1.966-1.765 1.766-.587-.11-1.068-.59-1.18-1.178zm3.766 12.178c-1.057.2-1.966-.71-1.766-1.766.112-.587.592-1.067 1.18-1.178 1.056-.2 1.965.71 1.764 1.766-.11.587-.59 1.067-1.178 1.178zM11.5 14c-.828 0-1.5-.67-1.5-1.5s.672-1.5 1.5-1.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5zm5 2c-.828 0-1.5-.67-1.5-1.5s.672-1.5 1.5-1.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z" fill-rule="evenodd"></path>
</g>
- <g id="search" stroke="none" stroke-width="1" fill="#ffffff">
- <path d="M31 28h-1.59l-.55-.55C30.82 25.18 32 22.23 32 19c0-7.18-5.82-13-13-13S6 11.82 6 19s5.82 13 13 13c3.23 0 6.18-1.18 8.45-3.13l.55.55V31l10 9.98L40.98 38 31 28zm-12 0c-4.97 0-9-4.03-9-9s4.03-9 9-9 9 4.03 9 9-4.03 9-9 9z"></path>
- <path d="M0 0h48v48H0z" fill="none"></path>
+ <!-- The Google "G" icon in the Clear Browsing Data dialog. -->
+ <g id="googleg">
+ <path fill="#4285F4" d="M7.36 4.08c0-.23-.025-.405-.055-.58H4v1.2h1.985c-.05.31-.26.795-.725 1.13v.82h1.06c.66-.605 1.04-1.505 1.04-2.57z"></path>
+ <path fill="#34A853" d="M4 7.5c.945 0 1.735-.315 2.315-.845l-1.06-.82c-.3.215-.71.375-1.255.375-.945 0-1.74-.62-2.04-1.48H.875v.845C1.45 6.715 2.63 7.5 4 7.5z"></path>
+ <path fill="#FBBC05" d="M1.96 4.725c-.075-.225-.13-.47-.13-.725s.05-.5.13-.725V2.43H.875C.635 2.905.5 3.435.5 4s.135 1.095.375 1.57l1.085-.845z"></path>
+ <path fill="#EA4335" d="M4 1.79c.68 0 1.135.29 1.395.54l.95-.915C5.735.845 4.945.5 4 .5 2.63.5 1.45 1.285.875 2.43l1.085.845C2.26 2.415 3.055 1.79 4 1.79z"></path>
+ <path fill="none" d="M.5.5h7v7h-7z"></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.
+ -->
+<if expr="chromeos">
+ <g id="access-time"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g>
+</if>
+ <g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"></path></g>
+ <g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"></path></g>
+ <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g>
+ <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g>
+ <g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-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-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"></path></g>
+<if expr="chromeos">
+ <g id="battery-charging-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM11 20v-5.5H9L13 7v5.5h2L11 20z"></path></g>
+ <g id="bluetooth"><path d="M17.71 7.71L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88z"></path></g>
+ <g id="brightness-1"><circle cx="12" cy="12" r="10"></circle></g>
+</if>
+<if expr="not chromeos">
+ <g id="build"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></g>
+</if>
+<if expr="chromeos">
+ <g id="camera-alt"><circle cx="12" cy="12" r="3.2"></circle><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"></path></g>
+</if>
+ <g id="cloud"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"></path></g>
+ <g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"></path></g>
+ <g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"></path></g>
+<if expr="chromeos">
+ <g id="desktop-windows"><path d="M21 2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v2H8v2h8v-2h-2v-2h7c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H3V4h18v12z"></path></g>
+</if>
+ <g id="done"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path></g>
+ <g id="error"><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-2h2v2zm0-4h-2V7h2v6z"></path></g>
+<if expr="chromeos">
+ <g id="flip"><path d="M15 21h2v-2h-2v2zm4-12h2V7h-2v2zM3 5v14c0 1.1.9 2 2 2h4v-2H5V5h4V3H5c-1.1 0-2 .9-2 2zm16-2v2h2c0-1.1-.9-2-2-2zm-8 20h2V1h-2v22zm8-6h2v-2h-2v2zM15 5h2V3h-2v2zm4 8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2z"></path></g>
+ <g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"></path></g>
+</if>
+ <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>
+ <g id="language"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"></path></g>
+<if expr="chromeos">
+ <g id="laptop-chromebook"><path d="M22 18V3H2v15H0v2h24v-2h-2zm-8 0h-4v-1h4v1zm6-3H4V5h16v10z"></path></g>
+</if>
+ <g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"></path></g>
+ <g id="location-on"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"></path></g>
+<if expr="chromeos">
+ <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="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g>
+ <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>
+<if expr="chromeos">
+ <g id="network-wifi"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"></path><path d="M3.53 10.95l8.46 10.54.01.01.01-.01 8.46-10.54C20.04 10.62 16.81 8 12 8c-4.81 0-8.04 2.62-8.47 2.95z"></path></g>
+</if>
+ <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="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></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="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></g>
+ <g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"></path></g>
+ <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>
+ <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
+<if expr="chromeos">
+ <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>
+</if>
+ <g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 16.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.66 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"></path></g>
+ <g id="sync-disabled"><path d="M10 6.35V4.26c-.8.21-1.55.54-2.23.96l1.46 1.46c.25-.12.5-.24.77-.33zm-7.14-.94l2.36 2.36C4.45 8.99 4 10.44 4 12c0 2.21.91 4.2 2.36 5.64L4 20h6v-6l-2.24 2.24C6.68 15.15 6 13.66 6 12c0-1 .25-1.94.68-2.77l8.08 8.08c-.25.13-.5.25-.77.34v2.09c.8-.21 1.55-.54 2.23-.96l2.36 2.36 1.27-1.27L4.14 4.14 2.86 5.41zM20 4h-6v6l2.24-2.24C17.32 8.85 18 10.34 18 12c0 1-.25 1.94-.68 2.77l1.46 1.46C19.55 15.01 20 13.56 20 12c0-2.21-.91-4.2-2.36-5.64L20 4z"></path></g>
+ <g id="sync-problem"><path d="M3 12c0 2.21.91 4.2 2.36 5.64L3 20h6v-6l-2.24 2.24C5.68 15.15 5 13.66 5 12c0-2.61 1.67-4.83 4-5.65V4.26C5.55 5.15 3 8.27 3 12zm8 5h2v-2h-2v2zM21 4h-6v6l2.24-2.24C18.32 8.85 19 10.34 19 12c0 2.61-1.67 4.83-4 5.65v2.09c3.45-.89 6-4.01 6-7.74 0-2.21-.91-4.2-2.36-5.64L21 4zm-10 9h2V7h-2v6z"></path></g>
+ <g id="videocam"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"></path></g>
+ <g id="visibility"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"></path></g>
+ <g id="volume-up"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"></path></g>
+<if expr="chromeos">
+ <g id="wallpaper"><path d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9l-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z"></path></g>
+</if>
+<if expr="not chromeos">
+ <g id="web"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z"></path></g>
+</if>
</defs>
</svg>
-</iron-icon-set>
+</iron-iconset-svg>
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 e016009873e..f18ca8a59fa 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
@@ -8,7 +8,6 @@
'dependencies': [
'<(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',
'<(INTERFACES_GYP):networking_private_interface',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
],
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.css b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.css
deleted file mode 100644
index f31caedc2ef..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.css
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright 2015 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-.section {
- margin-bottom: 5px;
-}
-
-iron-collapse {
- margin: 10px;
-}
-
-cr-network-icon {
- height: 32px;
- width: 32px;
-}
-
-cr-policy-network-indicator {
- -webkit-margin-start: 10px;
-}
-
-#networkName,
-#networkState {
- -webkit-margin-start: 10px;
- font-size: 20px;
-}
-
-#networkName {
- font-weight: bold;
-}
-
-#networkState[connected] {
- color: green;
-}
-
-#outerDiv {
- margin: 10px 20px;
-}
-
-#ipAddressLabel {
- -webkit-margin-end: 10px;
- font-weight: bold;
-}
-
-#preferButton {
- -webkit-margin-end: 8px;
- -webkit-margin-start: -3px;
- padding: 0
-}
-
-#proxyDiv {
- max-width: 500px;
-}
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 179f44ec37f..b50bca03f2d 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
@@ -1,11 +1,11 @@
<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/iron-flex-layout/classes/iron-flex-layout.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-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/cr_elements/cr_expand_button/cr_expand_button.html">
+<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_network_behavior.html">
@@ -19,9 +19,58 @@
<link rel="import" href="network_siminfo.html">
<dom-module id="settings-internet-detail-page">
- <link rel="import" type="css" href="internet_detail_page.css">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ .section {
+ margin-bottom: 5px;
+ }
+
+ iron-collapse {
+ margin: 10px;
+ }
+
+ cr-network-icon {
+ height: 32px;
+ width: 32px;
+ }
+
+ cr-policy-network-indicator {
+ -webkit-margin-start: 10px;
+ }
+
+ #networkName,
+ #networkState {
+ -webkit-margin-start: 10px;
+ font-size: 20px;
+ }
+
+ #networkName {
+ font-weight: bold;
+ }
+
+ #networkState[connected] {
+ color: green;
+ }
+
+ #outerDiv {
+ margin: 10px 20px;
+ }
+
+ #ipAddressLabel {
+ -webkit-margin-end: 10px;
+ font-weight: bold;
+ }
+
+ #preferButton {
+ -webkit-margin-end: 8px;
+ -webkit-margin-start: -3px;
+ padding: 0
+ }
+
+ #proxyDiv {
+ max-width: 500px;
+ }
+ </style>
<div class="layout vertical">
<!-- Title section: Icon + name + connection state. -->
<div id="titleDiv" class="layout horizontal center">
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 f15a9f13c0a..8e79c3a347d 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
@@ -547,7 +547,7 @@ Polymer({
* @private
*/
getPreferredIcon_: function(preferNetwork) {
- return preferNetwork ? 'star' : 'star-border';
+ return preferNetwork ? 'cr:star' : 'cr:star-border';
},
/**
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.css b/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.css
deleted file mode 100644
index fa7b85d985c..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.css
+++ /dev/null
@@ -1,22 +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. */
-
-#outerDiv {
- margin: 0 40px;
-}
-
-#headerDiv {
- background-color: grey;
- padding: 4px;
-}
-
-#headerDiv span {
- color: white;
- padding: 0 8px;
-}
-
-#headerDiv span.button {
- text-align: center;
- width: 60px;
-}
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 807d6735c93..90426da12ef 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,14 +1,30 @@
<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/iron-icons/iron-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_list.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-internet-known-networks-page">
- <link rel="import" type="css" href="internet_known_networks_page.css">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ #outerDiv {
+ margin: 0 40px;
+ }
+
+ #headerDiv {
+ background-color: grey;
+ padding: 4px;
+ }
+
+ #headerDiv span {
+ color: white;
+ padding: 0 8px;
+ }
+
+ #headerDiv span.button {
+ text-align: center;
+ width: 60px;
+ }
+ </style>
<div class="layout vertical">
<div id="outerDiv" class="layout vertical">
<div id="headerDiv" class="layout horizontal">
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 7c9a84b5336..863f8ba1ac4 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -1,4 +1,3 @@
-<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/cr_elements/network/cr_onc_types.html">
@@ -22,7 +21,7 @@
</network-summary>
</neon-animatable>
<template is="dom-if" name="network-detail">
- <settings-subpage page-title="[[i18n('internetDetailPageTitle')]]">
+ <settings-subpage page-title="$i18n{internetDetailPageTitle}">
<settings-internet-detail-page
guid="[[detailGuid]]"
default-network="[[defaultNetwork]]"
@@ -33,7 +32,7 @@
</template>
<template is="dom-if" name="known-networks">
<settings-subpage
- page-title="[[i18n('internetKnownNetworksPageTitle')]]">
+ page-title="$i18n{internetKnownNetworksPageTitle}">
<settings-internet-known-networks-page
network-type="[[knownNetworksType]]"
on-show-detail="onShowDetail_"
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 4ca97f10d6f..9f7cc3bdf7d 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -6,22 +6,10 @@
* @fileoverview
* 'settings-internet-page' is the settings page containing internet
* settings.
- *
- * Example:
- *
- * <core-animated-pages>
- * <settings-internet-page prefs='{{prefs}}'>
- * </settings-internet-page>
- * ... other pages ...
- * </core-animated-pages>
*/
Polymer({
is: 'settings-internet-page',
- behaviors: [
- I18nBehavior,
- ],
-
properties: {
/**
* The current active route.
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.css b/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.css
deleted file mode 100644
index 19a5acfa7bb..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.css
+++ /dev/null
@@ -1,20 +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. */
-
-#outerDiv {
- margin-bottom: 10px;
-}
-
-#selectDiv {
- margin-bottom: 10px;
-}
-
-#selectDiv select {
- -webkit-margin-start: 10px;
- padding: 5px;
-}
-
-#otherDiv network-property-list {
- -webkit-margin-start: 15px;
-}
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 a8b338e6359..5bdbbbea689 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_apnlist.html
@@ -4,8 +4,25 @@
<link rel="import" href="network_property_list.html">
<dom-module id="network-apnlist">
- <link rel="import" type="css" href="network_apnlist.css">
<template>
+ <style>
+ #outerDiv {
+ margin-bottom: 10px;
+ }
+
+ #selectDiv {
+ margin-bottom: 10px;
+ }
+
+ #selectDiv select {
+ -webkit-margin-start: 10px;
+ padding: 5px;
+ }
+
+ #otherDiv network-property-list {
+ -webkit-margin-start: 15px;
+ }
+ </style>
<div id="outerDiv" class="layout vertical">
<div id="selectDiv" class="layout horizontal center">
<span>Access Point:</span>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.css b/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.css
deleted file mode 100644
index 13e9069562e..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_ip_config.css
+++ /dev/null
@@ -1,11 +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. */
-
-paper-checkbox {
- margin-bottom: 10px;
-}
-
-network-property-list {
- -webkit-margin-start: 28px;
-}
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 f84807a540f..64602835833 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
@@ -4,8 +4,16 @@
<link rel="import" href="network_property_list.html">
<dom-module id="network-ip-config">
- <link rel="import" type="css" href="network_ip_config.css">
<template>
+ <style>
+ paper-checkbox {
+ margin-bottom: 10px;
+ }
+
+ network-property-list {
+ -webkit-margin-start: 28px;
+ }
+ </style>
<div id="outer" class="layout vertical">
<paper-checkbox checked="{{automatic}}" disabled="[[!editable]]">
Configure IP Address Automatically
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.css b/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.css
deleted file mode 100644
index 384697de512..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.css
+++ /dev/null
@@ -1,15 +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. */
-
-#selectTypeDiv {
- margin: 10px 0;
-}
-
-select {
- padding: 5px;
-}
-
-paper-input-container {
- margin: -9px 5px 0;
-}
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 2b4bbe2bc57..7621c98a6c0 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_nameservers.html
@@ -3,8 +3,20 @@
<link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.html">
<dom-module id="network-nameservers">
- <link rel="import" type="css" href="network_nameservers.css">
<template>
+ <style>
+ #selectTypeDiv {
+ margin: 10px 0;
+ }
+
+ select {
+ padding: 5px;
+ }
+
+ paper-input-container {
+ margin: -9px 5px 0;
+ }
+ </style>
<div id="outer" class="layout vertical">
<div id="selectTypeDiv">
<!-- TODO(stevenjb): Use cr-dropdown-menu once available. -->
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_property_list.css b/chromium/chrome/browser/resources/settings/internet_page/network_property_list.css
deleted file mode 100644
index bdb1712e846..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_property_list.css
+++ /dev/null
@@ -1,29 +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. */
-
-span {
- -webkit-margin-end: 5px;
- margin-bottom: 5px;
-}
-
-cr-policy-network-indicator {
- margin-bottom: 5px;
-}
-
-span.fill {
- border-bottom-color: grey;
- border-bottom-style: dotted;
- border-width: thin;
- min-width: 20px;
-}
-
-paper-input-container {
- -webkit-margin-start: 5px;
- margin-bottom: -3px;
- margin-top: -12px;
-}
-
-#outerDiv {
- padding: 5px 0;
-}
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 17364175e0b..1a8ba701120 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
@@ -5,8 +5,34 @@
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
<dom-module name="network-property-list">
- <link rel="import" type="css" href="network_property_list.css">
<template>
+ <style>
+ span {
+ -webkit-margin-end: 5px;
+ margin-bottom: 5px;
+ }
+
+ cr-policy-network-indicator {
+ margin-bottom: 5px;
+ }
+
+ span.fill {
+ border-bottom-color: grey;
+ border-bottom-style: dotted;
+ border-width: thin;
+ min-width: 20px;
+ }
+
+ paper-input-container {
+ -webkit-margin-start: 5px;
+ margin-bottom: -3px;
+ margin-top: -12px;
+ }
+
+ #outerDiv {
+ padding: 5px 0;
+ }
+ </style>
<div id="outerDiv" class="layout horizontal">
<div class="layout vertical">
<template is="dom-repeat" items="[[fields]]">
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy.css b/chromium/chrome/browser/resources/settings/internet_page/network_proxy.css
deleted file mode 100644
index 82bf90990ed..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy.css
+++ /dev/null
@@ -1,32 +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. */
-
-:host {
- display: inline-block;
-}
-
-#selectTypeDiv {
- margin: 10px 0;
-}
-
-select {
- padding: 5px;
-}
-
-span {
- margin: 5px;
-}
-
-cr-policy-network-indicator {
- -webkit-margin-end: 10px;
- mwrgin-bottom: 5px;
-}
-
-paper-checkbox {
- margin-bottom: 10px;
-}
-
-paper-input {
- margin: -9px 5px 0;
-}
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 b6c6501d8f0..f42a59ff80e 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy.html
@@ -10,8 +10,37 @@
<link rel="import" href="network_proxy_exclusions.html">
<dom-module id="network-proxy">
- <link rel="import" type="css" href="network_proxy.css">
<template>
+ <style>
+ :host {
+ display: inline-block;
+ }
+
+ #selectTypeDiv {
+ margin: 10px 0;
+ }
+
+ select {
+ padding: 5px;
+ }
+
+ span {
+ margin: 5px;
+ }
+
+ cr-policy-network-indicator {
+ -webkit-margin-end: 10px;
+ mwrgin-bottom: 5px;
+ }
+
+ paper-checkbox {
+ margin-bottom: 10px;
+ }
+
+ paper-input {
+ margin: -9px 5px 0;
+ }
+ </style>
<div id="outer" class="layout vertical flex">
<!-- TODO(stevenjb): Use cr-dropdown-menu once available. -->
<div class="layout horizontal center" hidden$=
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.css b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.css
deleted file mode 100644
index ad9a23955aa..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.css
+++ /dev/null
@@ -1,18 +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. */
-
-span {
- margin: 5px;
-}
-
-iron-icon {
- margin: 5px;
-}
-
-div#container {
- border: 1px solid lightgrey;
- height: 100px;
- margin: 5px;
- overflow-y: auto;
-}
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html
index 241e3f1edd0..31e2d56e015 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_exclusions.html
@@ -1,14 +1,30 @@
+<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-icons/iron-icons.html">
<dom-module id="network-proxy-exclusions">
- <link rel="import" type="css" href="network_proxy_exclusions.css">
<template>
+ <style>
+ span {
+ margin: 5px;
+ }
+
+ iron-icon {
+ margin: 5px;
+ }
+
+ div#container {
+ border: 1px solid lightgrey;
+ height: 100px;
+ margin: 5px;
+ overflow-y: auto;
+ }
+ </style>
<div id="container" class="layout vertical">
<template is="dom-repeat" items="[[exclusions]]">
<div class="layout horizontal">
<span class="flex">[[item]]</span>
- <iron-icon icon="clear" on-tap="onRemoveTap_"></iron-icon>
+ <iron-icon icon="cr:clear" on-tap="onRemoveTap_">
+ </iron-icon>
</div>
</template>
</div>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.css b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.css
deleted file mode 100644
index 514c7af4694..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.css
+++ /dev/null
@@ -1,15 +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. */
-
-#port {
- width: 50px;
-}
-
-span {
- -webkit-margin-end: 5px;
-}
-
-paper-input {
- margin: -9px 5px 0;
-}
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.html b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.html
index 42c3852180c..f2688a05ec8 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_input.html
@@ -2,8 +2,20 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<dom-module id="network-proxy-input">
- <link rel="import" type="css" href="network_proxy_input.css">
<template>
+ <style>
+ #port {
+ width: 50px;
+ }
+
+ span {
+ -webkit-margin-end: 5px;
+ }
+
+ paper-input {
+ margin: -9px 5px 0;
+ }
+ </style>
<div id="outer" class="layout horizontal">
<span class="flex">[[label]]</span>
<paper-input no-label-float id="url" disabled="[[!editable]]"
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.css b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.css
deleted file mode 100644
index df0d574c71b..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.css
+++ /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. */
-
-iron-icon {
- -webkit-margin-end: 5px;
- -webkit-margin-start: -3px;
-}
-
-paper-button {
- margin: 0;
-}
-
-span {
- -webkit-margin-end: 10px;
-}
-
-#lockedDiv span {
- color: red;
- font-weight: 500;
-}
-
-#lockedDiv paper-input {
- -webkit-margin-start: 10px;
- width: 80px;
-}
-
-#unlockSimDialog paper-input {
- -webkit-margin-start: 5px;
-}
-
-#unlockSimDialog span {
- -webkit-margin-start: 5px;
-}
-
-.pin {
- min-width: 100px;
-}
-
-.puk {
- min-width: 200px;
-}
-
-.error {
- color: red;
- max-width: 400px;
-}
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 1bb1397367a..7cf0c3fb2fc 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.html
@@ -1,21 +1,65 @@
<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/iron-icons/notification-icons.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="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-dialog/paper-dialog.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="network_property_list.html">
<dom-module id="network-siminfo">
- <link rel="import" type="css" href="network_siminfo.css">
<template>
+ <style>
+ iron-icon {
+ -webkit-margin-end: 5px;
+ -webkit-margin-start: -3px;
+ }
+
+ paper-button {
+ margin: 0;
+ }
+
+ span {
+ -webkit-margin-end: 10px;
+ }
+
+ #lockedDiv span {
+ color: red;
+ font-weight: 500;
+ }
+
+ #lockedDiv paper-input {
+ -webkit-margin-start: 10px;
+ width: 80px;
+ }
+
+ #unlockSimDialog paper-input {
+ -webkit-margin-start: 5px;
+ }
+
+ #unlockSimDialog span {
+ -webkit-margin-start: 5px;
+ }
+
+ .pin {
+ min-width: 100px;
+ }
+
+ .puk {
+ min-width: 200px;
+ }
+
+ .error {
+ color: red;
+ max-width: 400px;
+ }
+ </style>
<div id="outerDiv" class="layout vertical">
<div class="layout horizontal center"
hidden$="[[networkProperties.Cellular.SIMPresent]]">
<!-- SIM missing UI -->
- <iron-icon icon="notification:sim-card-alert"></iron-icon>
+ <iron-icon icon="settings:sim-card-alert"></iron-icon>
<span>Missing SIM card</span>
</div>
<div class="layout vertical"
@@ -23,7 +67,7 @@
<div id="lockedDiv" class="layout horizontal center"
hidden$="[[!isSimLocked_(networkProperties)]]">
<!-- SIM locked -->
- <iron-icon icon="lock"></iron-icon>
+ <iron-icon icon="settings:lock"></iron-icon>
<span>SIM card is locked.</span>
<paper-button on-tap="onUnlockPinTap_">Unlock</paper-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.css b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.css
deleted file mode 100644
index 678b3d849c9..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.css
+++ /dev/null
@@ -1,33 +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. */
-
-#details.selectable:hover {
- background-color: lightgrey;
-}
-
-#buttons {
- align-items: center;
-}
-
-.invisible {
- visibility: hidden;
-}
-
-paper-spinner {
- -webkit-margin-start: 20px;
-}
-
-#deviceEnabledButton {
- -webkit-margin-start: 10px;
-}
-
-#listDiv {
- -webkit-margin-end: 10px;
- -webkit-margin-start: 40px;
-}
-
-#networkList {
- margin: 5px 0 10px;
- max-height: 400px;
-}
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 73e3c8660d5..5b18cdd6555 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
@@ -5,19 +5,55 @@
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_list.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_list_item.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module name="network-summary-item">
- <link rel="import" type="css" href="network_summary_item.css">
<template>
- <div class="layout vertical" hidden$="[[isHidden]]">
- <div id="details" class="layout horizontal center"
- on-tap="onDetailsTap_">
- <cr-network-list-item id="detailsItem"
- network-state="[[networkState]]">
+ <style include="settings-shared">
+ :host {
+ --cr-network-icon-mixin: {
+ height: 24px;
+ left: -4px;
+ width: 24px;
+ }
+ --cr-network-name-mixin: {
+ font-size: inherit;
+ };
+ --cr-network-state-mixin: {
+ @apply(--settings-secondary);
+ font-size: inherit;
+ };
+ }
+
+ #buttons {
+ align-items: center;
+ }
+
+ .invisible {
+ visibility: hidden;
+ }
+
+ paper-spinner {
+ -webkit-margin-start: 20px;
+ }
+
+ #deviceEnabledButton {
+ -webkit-margin-start: 10px;
+ }
+
+ #networkList {
+ margin: 5px 0 10px;
+ max-height: 400px;
+ }
+ </style>
+ <div class="settings-box two-line" hidden$="[[isHidden]]">
+ <div id="details" class="start" on-tap="onDetailsTap_">
+ <cr-network-list-item id="detailsItem" network-state="[[networkState]]">
</cr-network-list-item>
<paper-spinner active="[[showScanning_(deviceState, expanded)]]">
</paper-spinner>
- <span class="flex"></span>
+ </div>
+ <div>
<div id="buttons" class="layout horizontal">
<cr-expand-button id="expandListButton"
class$="[[getExpandButtonClass_(deviceState, networkStateList)]]"
@@ -30,7 +66,9 @@
</paper-toggle-button>
</div>
</div>
- <div id="listDiv" class="layout vertical">
+ </div>
+ <template is="dom-if" if="[[expanded]]">
+ <div class="list-frame">
<cr-network-list id="networkList"
max-height="[[maxHeight]]"
networks="[[networkStateList]]"
@@ -44,7 +82,7 @@
</paper-button>
</div>
</div>
- </div>
+ </template>
</template>
<script src="network_summary_item.js"></script>
</dom-module>
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 bdbbec63a99..f13b9490447 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/languages_page/compiled_resources2.gyp
@@ -8,8 +8,11 @@
'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:promise_resolver',
'<(EXTERNS_GYP):chrome_send',
+ '<(EXTERNS_GYP):input_method_private',
'<(EXTERNS_GYP):language_settings_private',
+ '<(INTERFACES_GYP):input_method_private_interface',
'<(INTERFACES_GYP):language_settings_private_interface',
'../prefs/compiled_resources2.gyp:prefs_types',
'../prefs/compiled_resources2.gyp:prefs',
@@ -24,8 +27,8 @@
'<(DEPTH)/ui/webui/resources/js/chromeos/compiled_resources2.gyp:ui_account_tweaks',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(EXTERNS_GYP):chrome_send',
- 'languages_types',
'languages',
+ 'languages_types',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -34,10 +37,9 @@
'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',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
- 'languages_types',
'languages',
+ 'languages_types',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -50,11 +52,22 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'manage_languages_page',
+ 'target_name': 'manage_input_methods_page',
'dependencies': [
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-checkbox/compiled_resources2.gyp:paper-checkbox-extracted',
+ '<(EXTERNS_GYP):language_settings_private',
+ '../prefs/compiled_resources2.gyp:prefs',
+ 'languages',
'languages_types',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'manage_languages_page',
+ 'dependencies': [
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-checkbox/compiled_resources2.gyp:paper-checkbox-extracted',
'languages',
+ 'languages_types',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
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 447a083ee62..8b09471fd23 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
@@ -1,6 +1,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-a11y-keys/iron-a11y-keys.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-icons/iron-icons.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/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-icon-button/paper-icon-button.html">
@@ -37,19 +38,20 @@
<iron-a11y-keys id="keys" keys="enter esc"
on-keys-pressed="onKeysPress_"></iron-a11y-keys>
<paper-input id="newWord" no-label-float
- i18n-values="label:addDictionaryWordLabel"></paper-input>
- <paper-button on-tap="onAddWordTap_"
- i18n-content="addDictionaryWordButton"></paper-button>
+ label="$i18n{addDictionaryWordLabel}"></paper-input>
+ <paper-button on-tap="onAddWordTap_">
+ $i18n{addDictionaryWordButton}
+ </paper-button>
</div>
</div>
<div class="settings-box block">
- <h2 i18n-content="customDictionaryWords"></h2>
+ <h2>$i18n{customDictionaryWords}</h2>
<div class="list-frame">
<iron-list id="list" items="{{words_}}">
<template>
<div class="list-item">
<div class="word">[[item]]</div>
- <paper-icon-button icon="clear" on-tap="onRemoveWordTap_">
+ <paper-icon-button icon="cr:clear" on-tap="onRemoveWordTap_">
</paper-icon-button>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.html b/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.html
index 0c9203f7a4e..369acc6967e 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.html
@@ -43,37 +43,40 @@
disabled$="[[isUILanguageChangeDisabled_(
detail.language.code, prefs.intl.app_locale.value)]]">
</paper-toggle-button>
- <span i18n-content="isDisplayedInThisLanguage"
- hidden$="[[!isCurrentUILanguage_(
+ <span hidden$="[[!isCurrentUILanguage_(
detail.language.code, prefs.intl.app_locale.value)]]">
+ $i18n{isDisplayedInThisLanguage}
</span>
<span hidden$="[[isCurrentUILanguage_(
detail.language.code, prefs.intl.app_locale.value)]]">
- <span i18n-content="displayInThisLanguage"></span>
- <paper-button i18n-content="restart" on-tap="onRestartTap_"
+ <span>$i18n{displayInThisLanguage}</span>
+ <paper-button on-tap="onRestartTap_"
hidden$="[[!isRestartRequired_(
detail.language.code, prefs.intl.app_locale.value)]]">
+ $i18n{restart}
</paper-button>
</span>
<cr-policy-pref-indicator id="policyIndicator">
</cr-policy-pref-indicator>
</label>
- <span i18n-content="cannotBeDisplayedInThisLanguage"
- hidden$="[[detail.language.supportsUI]]"></span>
+ <span hidden$="[[detail.language.supportsUI]]">
+ $i18n{cannotBeDisplayedInThisLanguage}
+ </span>
</div>
</if>
<div class="list-item"
hidden$="[[shouldHideTranslate_(
detail.language.code, prefs.translate.enabled.value)]]">
- <paper-checkbox checked="[[detail.state.translateEnabled]]"
+ <paper-checkbox checked="[[detail.translateEnabled]]"
on-change="onTranslateEnabledChange_"
- i18n-content="offerToTranslateInThisLanguage"
hidden$="[[!detail.language.supportsTranslate]]"
disabled="[[isTranslateDisabled_(
detail.language.code, languages.translateTarget)]]">
+ $i18n{offerToTranslateInThisLanguage}
</paper-checkbox>
- <div i18n-content="cannotTranslateInThisLanguage"
- hidden$="[[detail.language.supportsTranslate]]"></div>
+ <div hidden$="[[detail.language.supportsTranslate]]">
+ $i18n{cannotTranslateInThisLanguage}
+ </div>
</div>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.js b/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.js
index f500dbead3b..921aed659f4 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/language_detail_page.js
@@ -21,20 +21,26 @@ Polymer({
/**
* Read-only reference to the languages model provided by the
* 'settings-languages' instance.
- * @type {LanguagesModel|undefined}
+ * @type {!LanguagesModel|undefined}
*/
languages: Object,
/**
* The language to display the details for.
- * @type {LanguageInfo|undefined}
+ * @type {!LanguageState|undefined}
*/
detail: Object,
+
+ /** @private {!LanguageHelper} */
+ languageHelper_: Object,
},
- /** @private {!LanguageHelper} */
- languageHelper_: LanguageHelperImpl.getInstance(),
+ /** @override */
+ created: function() {
+ this.languageHelper_ = LanguageHelperImpl.getInstance();
+ },
+ /** @override */
ready: function() {
// In a CrOS multi-user session, the primary user controls the UI language.
if (this.isSecondaryUser_()) {
@@ -51,7 +57,6 @@ Polymer({
}
},
-<if expr="chromeos or is_win">
/**
* Checks whether the prospective UI language (the pref that indicates what
* language to use in Chrome) matches the current language. This pref is only
@@ -63,6 +68,7 @@ Polymer({
* @private
*/
isProspectiveUILanguage_: function(languageCode, prospectiveUILanguage) {
+ assert(cr.isChromeOS || cr.isWindows);
return languageCode == this.languageHelper_.getProspectiveUILanguage();
},
@@ -74,10 +80,10 @@ Polymer({
* @private
*/
isCurrentUILanguage_: function(languageCode, prospectiveUILanguage) {
+ assert(cr.isChromeOS || cr.isWindows);
return languageCode == prospectiveUILanguage &&
languageCode == navigator.language;
},
-</if>
/**
* @param {string} languageCode The language code identifying a language.
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages.html b/chromium/chrome/browser/resources/settings/languages_page/languages.html
index c729b94578f..dfd19367ab7 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages.html
@@ -1,6 +1,7 @@
<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/html/promise_resolver.html">
<link rel="import" href="chrome://md-settings/prefs/prefs.html">
<link rel="import" href="chrome://md-settings/prefs/prefs_behavior.html">
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages.js b/chromium/chrome/browser/resources/settings/languages_page/languages.js
index cf7a7542d23..810281f90f6 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages.js
@@ -63,7 +63,7 @@ SettingsLanguagesSingletonElement = Polymer({
properties: {
/**
- * @type {LanguagesModel|undefined}
+ * @type {!LanguagesModel|undefined}
*/
languages: {
type: Object,
@@ -77,67 +77,114 @@ SettingsLanguagesSingletonElement = Polymer({
type: Object,
notify: true,
},
+
+ /**
+ * PromiseResolver to be resolved when the singleton has been initialized.
+ * @private {!PromiseResolver}
+ */
+ resolver_: {
+ type: Object,
+ value: function() {
+ return new PromiseResolver();
+ },
+ },
+
+ /** @type {!LanguageSettingsPrivate} */
+ languageSettingsPrivate: Object,
+
+ /** @type {!InputMethodPrivate} */
+ inputMethodPrivate: Object,
},
- /** @type {!LanguageSettingsPrivate} */
- languageSettingsPrivate: languageSettings.languageSettingsPrivateApiForTest ||
- /** @type {!LanguageSettingsPrivate} */(chrome.languageSettingsPrivate),
+ /**
+ * Hash map of supported languages by language codes for fast lookup.
+ * @private {!Map<string, !chrome.languageSettingsPrivate.Language>}
+ */
+ supportedLanguageMap_: new Map(),
/**
- * Hash map of languages.supportedLanguages using language codes as keys for
- * fast lookup.
- * @private {!Object<!chrome.languageSettingsPrivate.Language>}
+ * Hash set of enabled language codes for membership testing.
+ * @private {!Set<string>}
*/
- supportedLanguageMap_: {},
+ enabledLanguageSet_: new Set(),
/**
- * Hash map of languages.enabledLanguages using language codes as keys for
- * fast lookup.
- * @private {!Object<!LanguageInfo>}
+ * Hash map of supported input methods by ID for fast lookup.
+ * @private {!Map<string, chrome.languageSettingsPrivate.InputMethod>}
+ */
+ supportedInputMethodMap_: new Map(),
+
+ /**
+ * Hash map of input methods supported for each language.
+ * @type {!Map<string, !Array<!chrome.languageSettingsPrivate.InputMethod>>}
+ * @private
*/
- enabledLanguageMap_: {},
+ languageInputMethods_: new Map(),
observers: [
- 'preferredLanguagesPrefChanged_(prefs.' +
- preferredLanguagesPrefName + '.value)',
- 'spellCheckDictionariesPrefChanged_(prefs.spellcheck.dictionaries.value.*)',
- 'translateLanguagesPrefChanged_(prefs.translate_blocked_languages.value.*)',
+ 'preferredLanguagesPrefChanged_(' +
+ 'prefs.' + preferredLanguagesPrefName + '.value, languages)',
+ 'spellCheckDictionariesPrefChanged_(' +
+ 'prefs.spellcheck.dictionaries.value.*, languages)',
+ 'translateLanguagesPrefChanged_(' +
+ 'prefs.translate_blocked_languages.value.*, languages)',
+ 'prospectiveUILanguageChanged_(' +
+ 'prefs.intl.app_locale.value, languages)',
+ // Observe Chrome OS prefs (ignored for non-Chrome OS).
+ 'updateRemovableLanguages_(' +
+ 'prefs.settings.language.preload_engines.value, ' +
+ 'prefs.settings.language.enabled_extension_imes.value, ' +
+ 'languages)',
],
/** @override */
created: function() {
- var languageList;
- var translateTarget;
+ this.languageSettingsPrivate =
+ languageSettings.languageSettingsPrivateApiForTest ||
+ /** @type {!LanguageSettingsPrivate} */(chrome.languageSettingsPrivate);
- /**
- * Promise to be resolved when the languages singleton has been initialized.
- * @type {!Promise}
- */
- this.initialized = Promise.all([
- // Wait until prefs are initialized before creating the model, so we can
- // include information about enabled languages.
- CrSettingsPrefs.initialized,
-
- // Get the language list.
- new Promise(function(resolve) {
- this.languageSettingsPrivate.getLanguageList(function(list) {
- languageList = list;
- resolve();
+ this.inputMethodPrivate =
+ languageSettings.inputMethodPrivateApiForTest ||
+ /** @type {!InputMethodPrivate} */(chrome.inputMethodPrivate);
+
+ var promises = [];
+
+ // Wait until prefs are initialized before creating the model, so we can
+ // include information about enabled languages.
+ promises[0] = CrSettingsPrefs.initialized;
+
+ // Get the language list.
+ promises[1] = new Promise(function(resolve) {
+ this.languageSettingsPrivate.getLanguageList(resolve);
+ }.bind(this));
+
+ // Get the translate target language.
+ promises[2] = new Promise(function(resolve) {
+ this.languageSettingsPrivate.getTranslateTargetLanguage(resolve);
+ }.bind(this));
+
+ if (cr.isChromeOS) {
+ promises[3] = new Promise(function(resolve) {
+ this.languageSettingsPrivate.getInputMethodLists(function(lists) {
+ resolve(lists.componentExtensionImes.concat(
+ lists.thirdPartyExtensionImes));
});
- }.bind(this)),
-
- // Get the translate target language.
- new Promise(function(resolve) {
- this.languageSettingsPrivate.getTranslateTargetLanguage(
- function(targetLanguageCode) {
- translateTarget = targetLanguageCode;
- resolve();
- });
- }.bind(this)),
- ]).then(function() {
- this.createModel_(languageList, translateTarget);
- this.initialized_ = true;
+ }.bind(this));
+
+ promises[4] = new Promise(function(resolve) {
+ this.inputMethodPrivate.getCurrentInputMethod(resolve);
+ }.bind(this));
+ }
+
+ Promise.all(promises).then(function(results) {
+ this.createModel_(results[1], results[2], results[3], results[4]);
+ this.resolver_.resolve();
}.bind(this));
+
+ if (cr.isChromeOS) {
+ this.inputMethodPrivate.onChanged.addListener(
+ this.onInputMethodChanged_.bind(this));
+ }
},
/**
@@ -145,20 +192,16 @@ SettingsLanguagesSingletonElement = Polymer({
* @private
*/
preferredLanguagesPrefChanged_: function() {
- if (!this.initialized_)
- return;
+ var enabledLanguageStates =
+ this.getEnabledLanguageStates_(this.languages.translateTarget);
- var enabledLanguages =
- this.getEnabledLanguages_(this.languages.translateTarget);
+ // Recreate the enabled language set before updating languages.enabled.
+ this.enabledLanguageSet_.clear();
+ for (var languageState of enabledLanguageStates)
+ this.enabledLanguageSet_.add(languageState.language.code);
- // Reset the enabled language map before updating
- // languages.enabledLanguages.
- this.enabledLanguageMap_ = {};
- for (var i = 0; i < enabledLanguages.length; i++) {
- var languageInfo = enabledLanguages[i];
- this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
- }
- this.set('languages.enabledLanguages', enabledLanguages);
+ this.set('languages.enabled', enabledLanguageStates);
+ this.updateRemovableLanguages_();
},
/**
@@ -166,145 +209,234 @@ SettingsLanguagesSingletonElement = Polymer({
* @private
*/
spellCheckDictionariesPrefChanged_: function() {
- if (!this.initialized_)
- return;
-
- var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */(
+ var spellCheckSet = this.makeSetFromArray_(/** @type {!Array<string>} */(
this.getPref('spellcheck.dictionaries').value));
- for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
- var languageCode = this.languages.enabledLanguages[i].language.code;
- this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled',
- !!spellCheckMap[languageCode]);
+ for (var i = 0; i < this.languages.enabled.length; i++) {
+ var languageState = this.languages.enabled[i];
+ this.set('languages.enabled.' + i + '.spellCheckEnabled',
+ !!spellCheckSet.has(languageState.language.code));
}
},
/** @private */
translateLanguagesPrefChanged_: function() {
- if (!this.initialized_)
- return;
-
var translateBlockedPref = this.getPref('translate_blocked_languages');
- var translateBlockedMap = this.makeMapFromArray_(
+ var translateBlockedSet = this.makeSetFromArray_(
/** @type {!Array<string>} */(translateBlockedPref.value));
- for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
+ for (var i = 0; i < this.languages.enabled.length; i++) {
var translateCode = this.convertLanguageCodeForTranslate(
- this.languages.enabledLanguages[i].language.code);
+ this.languages.enabled[i].language.code);
this.set(
- 'languages.enabledLanguages.' + i + '.state.translateEnabled',
- !translateBlockedMap[translateCode]);
+ 'languages.enabled.' + i + '.translateEnabled',
+ !translateBlockedSet.has(translateCode));
}
},
+ /** @private */
+ prospectiveUILanguageChanged_: function() {
+ this.updateRemovableLanguages_();
+ },
+
/**
* Constructs the languages model.
* @param {!Array<!chrome.languageSettingsPrivate.Language>}
* supportedLanguages
* @param {string} translateTarget Language code of the default translate
* target language.
+ * @param {!Array<!chrome.languageSettingsPrivate.InputMethod>|undefined}
+ * supportedInputMethods Input methods (Chrome OS only).
+ * @param {string|undefined} currentInputMethodId ID of the currently used
+ * input method (Chrome OS only).
* @private
*/
- createModel_: function(supportedLanguages, translateTarget) {
+ createModel_: function(supportedLanguages, translateTarget,
+ supportedInputMethods, currentInputMethodId) {
// Populate the hash map of supported languages.
- for (var i = 0; i < supportedLanguages.length; i++) {
- var language = supportedLanguages[i];
+ for (var language of supportedLanguages) {
language.supportsUI = !!language.supportsUI;
language.supportsTranslate = !!language.supportsTranslate;
language.supportsSpellcheck = !!language.supportsSpellcheck;
- this.supportedLanguageMap_[language.code] = language;
+ this.supportedLanguageMap_.set(language.code, language);
}
- // Create a list of enabled language info from the supported languages.
- var enabledLanguages = this.getEnabledLanguages_(translateTarget);
- // Populate the hash map of enabled languages.
- for (var i = 0; i < enabledLanguages.length; i++) {
- var languageInfo = enabledLanguages[i];
- this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
+ if (supportedInputMethods) {
+ // Populate the hash map of supported input methods.
+ for (var inputMethod of supportedInputMethods) {
+ inputMethod.enabled = !!inputMethod.enabled;
+ // Add the input method to the map of IDs.
+ this.supportedInputMethodMap_.set(inputMethod.id, inputMethod);
+ // Add the input method to the list of input methods for each language
+ // it supports.
+ for (var languageCode of inputMethod.languageCodes) {
+ if (!this.supportedLanguageMap_.has(languageCode))
+ continue;
+ if (!this.languageInputMethods_.has(languageCode))
+ this.languageInputMethods_.set(languageCode, [inputMethod]);
+ else
+ this.languageInputMethods_.get(languageCode).push(inputMethod);
+ }
+ }
}
- // Initialize the Polymer languages model.
- this.languages = /** @type {!LanguagesModel} */({
- supportedLanguages: supportedLanguages,
- enabledLanguages: enabledLanguages,
+ // Create a list of enabled languages from the supported languages.
+ var enabledLanguageStates = this.getEnabledLanguageStates_(translateTarget);
+ // Populate the hash set of enabled languages.
+ for (var languageState of enabledLanguageStates)
+ this.enabledLanguageSet_.add(languageState.language.code);
+
+ var model = /** @type {!LanguagesModel} */({
+ supported: supportedLanguages,
+ enabled: enabledLanguageStates,
translateTarget: translateTarget,
});
+ if (cr.isChromeOS) {
+ model.inputMethods = /** @type {!InputMethodsModel} */({
+ supported: supportedInputMethods,
+ enabled: this.getEnabledInputMethods_(),
+ currentId: currentInputMethodId,
+ });
+ }
+
+ // Initialize the Polymer languages model.
+ this.languages = model;
},
/**
- * Returns a list of LanguageInfos for each enabled language in the supported
+ * Returns a list of LanguageStates for each enabled language in the supported
* languages list.
* @param {string} translateTarget Language code of the default translate
* target language.
- * @return {!Array<!LanguageInfo>}
+ * @return {!Array<!LanguageState>}
* @private
*/
- getEnabledLanguages_: function(translateTarget) {
+ getEnabledLanguageStates_: function(translateTarget) {
assert(CrSettingsPrefs.isInitialized);
var pref = this.getPref(preferredLanguagesPrefName);
var enabledLanguageCodes = pref.value.split(',');
- var enabledLanguages = /** @type {!Array<!LanguageInfo>} */ [];
-
var spellCheckPref = this.getPref('spellcheck.dictionaries');
- var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */(
+ var spellCheckSet = this.makeSetFromArray_(/** @type {!Array<string>} */(
spellCheckPref.value));
var translateBlockedPref = this.getPref('translate_blocked_languages');
- var translateBlockedMap = this.makeMapFromArray_(
+ var translateBlockedSet = this.makeSetFromArray_(
/** @type {!Array<string>} */(translateBlockedPref.value));
+ var enabledLanguageStates = [];
for (var i = 0; i < enabledLanguageCodes.length; i++) {
var code = enabledLanguageCodes[i];
- var language = this.supportedLanguageMap_[code];
+ var language = this.supportedLanguageMap_.get(code);
// Skip unsupported languages.
if (!language)
continue;
- var state = /** @type {LanguageState} */({});
- state.spellCheckEnabled = !!spellCheckMap[code];
+ var languageState = /** @type {LanguageState} */({});
+ languageState.language = language;
+ languageState.spellCheckEnabled = !!spellCheckSet.has(code);
// Translate is considered disabled if this language maps to any translate
// language that is blocked.
var translateCode = this.convertLanguageCodeForTranslate(code);
- state.translateEnabled = !!language.supportsTranslate &&
- !translateBlockedMap[translateCode] &&
+ languageState.translateEnabled = !!language.supportsTranslate &&
+ !translateBlockedSet.has(translateCode) &&
translateCode != translateTarget;
- enabledLanguages.push(/** @type {LanguageInfo} */(
- {language: language, state: state}));
+ enabledLanguageStates.push(languageState);
}
- return enabledLanguages;
+ return enabledLanguageStates;
},
/**
- * Creates an object whose keys are the elements of the list.
- * @param {!Array<string>} list
- * @return {!Object<boolean>}
+ * Returns a list of enabled input methods.
+ * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>}
* @private
*/
- makeMapFromArray_: function(list) {
- var map = {};
- for (var i = 0; i < list.length; i++)
- map[list[i]] = true;
- return map;
+ getEnabledInputMethods_: function() {
+ assert(cr.isChromeOS);
+ assert(CrSettingsPrefs.isInitialized);
+
+ var enabledInputMethodIds =
+ this.getPref('settings.language.preload_engines').value.split(',');
+ enabledInputMethodIds = enabledInputMethodIds.concat(this.getPref(
+ 'settings.language.enabled_extension_imes').value.split(','));
+
+ // Return only supported input methods.
+ return enabledInputMethodIds.map(function(id) {
+ return this.supportedInputMethodMap_.get(id);
+ }.bind(this)).filter(function(inputMethod) {
+ return !!inputMethod;
+ });
+ },
+
+ /** @private */
+ updateEnabledInputMethods_: function() {
+ assert(cr.isChromeOS);
+ var enabledInputMethods = this.getEnabledInputMethods_();
+ var enabledInputMethodSet = this.makeSetFromArray_(enabledInputMethods);
+
+ for (var i = 0; i < this.languages.inputMethods.supported.length; i++) {
+ this.set('languages.inputMethods.supported.' + i + '.enabled',
+ enabledInputMethodSet.has(this.languages.inputMethods.supported[i]));
+ }
+ this.set('languages.inputMethods.enabled', enabledInputMethods);
+ },
+
+ /**
+ * Updates the |removable| property of the enabled language states based
+ * on what other languages and input methods are enabled.
+ * @private
+ */
+ updateRemovableLanguages_: function() {
+ assert(this.languages);
+ // TODO(michaelpg): Enabled input methods can affect which languages are
+ // removable, so run updateEnabledInputMethods_ first (if it has been
+ // scheduled).
+ if (cr.isChromeOS)
+ this.updateEnabledInputMethods_();
+
+ for (var i = 0; i < this.languages.enabled.length; i++) {
+ var languageState = this.languages.enabled[i];
+ this.set('languages.enabled.' + i + '.removable',
+ this.canDisableLanguage(languageState.language.code));
+ }
+ },
+
+ /**
+ * Creates a Set from the elements of the array.
+ * @param {!Array<T>} list
+ * @return {!Set<T>}
+ * @template T
+ * @private
+ */
+ makeSetFromArray_: function(list) {
+ var set = new Set();
+ for (var item of list)
+ set.add(item);
+ return set;
},
// LanguageHelper implementation.
// TODO(michaelpg): replace duplicate docs with @override once b/24294625
// is fixed.
-<if expr="chromeos or is_win">
+ /** @return {!Promise} */
+ whenReady: function() {
+ return this.resolver_.promise;
+ },
+
/**
* Sets the prospective UI language to the chosen language. This won't affect
* the actual UI language until a restart.
* @param {string} languageCode
*/
setUILanguage: function(languageCode) {
+ assert(cr.isChromeOS || cr.isWindows);
chrome.send('setUILanguage', [languageCode]);
},
/** Resets the prospective UI language back to the actual UI language. */
resetUILanguage: function() {
+ assert(cr.isChromeOS || cr.isWindows);
chrome.send('setUILanguage', [navigator.language]);
},
-</if>
/**
* Returns the "prospective" UI language, i.e. the one to be used on next
@@ -322,7 +454,7 @@ SettingsLanguagesSingletonElement = Polymer({
* @return {boolean} True if the language is enabled.
*/
isLanguageEnabled: function(languageCode) {
- return !!this.enabledLanguageMap_[languageCode];
+ return this.enabledLanguageSet_.has(languageCode);
},
/**
@@ -355,6 +487,19 @@ SettingsLanguagesSingletonElement = Polymer({
// Remove the language from spell check.
this.deletePrefListItem('spellcheck.dictionaries', languageCode);
+ if (cr.isChromeOS) {
+ var inputMethods = this.languageInputMethods_.get(languageCode) || [];
+ for (var inputMethod of inputMethods) {
+ var supportsOtherEnabledLanguages = inputMethod.languageCodes.some(
+ function(inputMethodLanguageCode) {
+ return inputMethodLanguageCode != languageCode &&
+ this.isLanguageEnabled(languageCode);
+ }.bind(this));
+ if (!supportsOtherEnabledLanguages)
+ this.removeInputMethod(inputMethod.id);
+ }
+ }
+
// Remove the language from preferred languages.
var languageCodes =
this.getPref(preferredLanguagesPrefName).value.split(',');
@@ -378,10 +523,26 @@ SettingsLanguagesSingletonElement = Polymer({
}
// Cannot disable the only enabled language.
- if (this.languages.enabledLanguages.length == 1)
+ if (this.languages.enabled.length == 1)
return false;
- return true;
+ if (!cr.isChromeOS)
+ return true;
+
+ // If this is the only enabled language that is supported by all enabled
+ // component IMEs, it cannot be disabled because we need those IMEs.
+ var otherInputMethodsEnabled = this.languages.enabled.some(
+ function(languageState) {
+ var otherLanguageCode = languageState.language.code;
+ if (otherLanguageCode == languageCode)
+ return false;
+ var inputMethods = this.languageInputMethods_.get(otherLanguageCode);
+ return inputMethods && inputMethods.some(function(inputMethod) {
+ return this.isComponentIme(inputMethod) &&
+ this.supportedInputMethodMap_.get(inputMethod.id).enabled;
+ }, this);
+ }, this);
+ return otherInputMethodsEnabled;
},
/**
@@ -410,7 +571,7 @@ SettingsLanguagesSingletonElement = Polymer({
* @param {boolean} enable
*/
toggleSpellCheck: function(languageCode, enable) {
- if (!this.initialized_)
+ if (!this.languages)
return;
if (enable) {
@@ -445,11 +606,100 @@ SettingsLanguagesSingletonElement = Polymer({
},
/**
+ * Given a language code, returns just the base language. E.g., converts
+ * 'en-GB' to 'en'.
+ * @param {string} languageCode
+ * @return {string}
+ */
+ getLanguageCodeWithoutRegion: function(languageCode) {
+ // The Norwegian languages fall under the 'no' macrolanguage.
+ if (languageCode == 'nb' || languageCode == 'nn')
+ return 'no';
+
+ // Match the characters before the hyphen.
+ var result = languageCode.match(/^([^-]+)-?/);
+ assert(result.length == 2);
+ return result[1];
+ },
+
+ /**
* @param {string} languageCode
* @return {!chrome.languageSettingsPrivate.Language|undefined}
*/
getLanguage: function(languageCode) {
- return this.supportedLanguageMap_[languageCode];
+ return this.supportedLanguageMap_.get(languageCode);
+ },
+
+ /**
+ * @param {string} id
+ * @return {!chrome.languageSettingsPrivate.InputMethod|undefined}
+ */
+ getInputMethod: function(id) {
+ assert(cr.isChromeOS);
+ return this.supportedInputMethodMap_.get(id);
+ },
+
+ /** @param {string} id */
+ addInputMethod: function(id) {
+ assert(cr.isChromeOS);
+ if (!this.supportedInputMethodMap_.has(id))
+ return;
+ this.languageSettingsPrivate.addInputMethod(id);
+ },
+
+ /** @param {string} id */
+ removeInputMethod: function(id) {
+ assert(cr.isChromeOS);
+ if (!this.supportedInputMethodMap_.has(id))
+ return;
+ this.languageSettingsPrivate.removeInputMethod(id);
+ },
+
+ /** @param {string} id */
+ setCurrentInputMethod: function(id) {
+ assert(cr.isChromeOS);
+ this.inputMethodPrivate.setCurrentInputMethod(id);
+ },
+
+ /**
+ * param {string} languageCode
+ * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>}
+ */
+ getInputMethodsForLanguage: function(languageCode) {
+ return this.languageInputMethods_.get(languageCode) || [];
+ },
+
+ /**
+ * @param {!chrome.languageSettingsPrivate.InputMethod} inputMethod
+ * @return {boolean}
+ */
+ isComponentIme: function(inputMethod) {
+ assert(cr.isChromeOS);
+ return inputMethod.id.startsWith('_comp_');
+ },
+
+ /** @param {string} id Input method ID. */
+ openInputMethodOptions: function(id) {
+ assert(cr.isChromeOS);
+ this.inputMethodPrivate.openOptionsPage(id);
+ },
+
+ /** @param {string} id New current input method ID. */
+ onInputMethodChanged_: function(id) {
+ assert(cr.isChromeOS);
+ this.set('languages.inputMethods.currentId', id);
+ },
+
+ /** @param {string} id Added input method ID. */
+ onInputMethodAdded_: function(id) {
+ assert(cr.isChromeOS);
+ this.updateEnabledInputMethods_();
+ },
+
+ /** @param {string} id Removed input method ID. */
+ onInputMethodRemoved_: function(id) {
+ assert(cr.isChromeOS);
+ this.updateEnabledInputMethods_();
},
});
})();
@@ -471,16 +721,6 @@ Polymer({
properties: {
/**
- * Singleton element created at startup which provides the languages model.
- * @type {SettingsLanguagesSingletonElement}
- */
- singleton_: {
- type: Object,
- value: languageSettings.languageSettingsPrivateApiForTest ?
- undefined : LanguageHelperImpl.getInstance(),
- },
-
- /**
* A reference to the languages model from the singleton, exposed as a
* read-only property so hosts can bind to it, but not change it.
* @type {LanguagesModel|undefined}
@@ -493,13 +733,14 @@ Polymer({
},
ready: function() {
- this.singleton_.initialized.then(function() {
+ var singleton = /** @type {!SettingsLanguagesSingletonElement} */
+ (LanguageHelperImpl.getInstance());
+ singleton.whenReady().then(function() {
// Set the 'languages' property to reference the singleton's model.
- this._setLanguages(this.singleton_.languages);
+ this._setLanguages(singleton.languages);
// Listen for changes to the singleton's languages property, so we know
// when to notify hosts of changes to (our reference to) the property.
- this.listen(
- this.singleton_, 'languages-changed', 'singletonLanguagesChanged_');
+ this.listen(singleton, 'languages-changed', 'singletonLanguagesChanged_');
}.bind(this));
},
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 2af51df3dc8..a06ea18c2ef 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -1,13 +1,13 @@
<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/i18n_behavior.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/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.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.html">
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_subpage.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
@@ -19,6 +19,10 @@
<link rel="import" href="edit_dictionary_page.html">
</if>
+<if expr="chromeos">
+<link rel="import" href="manage_input_methods_page.html">
+</if>
+
<dom-module id="settings-languages-page">
<template>
<style include="settings-shared"></style>
@@ -28,9 +32,10 @@
<neon-animatable id="main">
<div class="settings-box first two-line">
<div class="start">
- <div i18n-content="languagesListTitle"></div>
+ <div>$i18n{languagesListTitle}</div>
<div class="secondary">
- [[getProspectiveUILanguageName_(prefs.intl.app_locale.value)]]
+ [[getProspectiveUILanguageName_(
+ languages, prefs.intl.app_locale.value)]]
</div>
</div>
<cr-expand-button expanded="{{languagesOpened_}}">
@@ -38,7 +43,7 @@
</div>
<iron-collapse id="languagesCollapse" opened="[[languagesOpened_]]">
<div class="list-frame vertical-list">
- <template is="dom-repeat" items="{{languages.enabledLanguages}}">
+ <template is="dom-repeat" items="[[languages.enabled]]">
<div class$="list-item [[getLanguageItemClass_(
item.language.code, prefs.intl.app_locale.value)]]"
on-tap="onLanguageTap_">
@@ -52,26 +57,28 @@
[[item.language.displayName]]
</div>
<div class="middle">
- <iron-icon icon="done"
+ <iron-icon icon="settings:done"
hidden$="[[!isProspectiveUILanguage_(
item.language.code, prefs.intl.app_locale.value)]]">
</iron-icon>
</div>
</if>
- <paper-icon-button icon="settings"
+ <paper-icon-button icon="cr:settings"
on-tap="onShowLanguageDetailTap_"></paper-icon-button>
</div>
</template>
- <div class="list-item list-button" i18n-content="manageLanguages"
- on-tap="onManageLanguagesTap_">
+ <div class="list-item list-button" on-tap="onManageLanguagesTap_">
+ $i18n{manageLanguages}
</div>
</div>
</iron-collapse>
<if expr="chromeos">
<div class="settings-box two-line">
<div class="start">
- <div i18n-content="inputMethodsListTitle"></div>
- <div class="secondary">[[inputMethodsSecondary_]]</div>
+ <div>$i18n{inputMethodsListTitle}</div>
+ <div class="secondary">
+ [[getInputMethodName_(languages.inputMethods.currentId)]]
+ </div>
</div>
<cr-expand-button expanded="{{inputMethodsOpened_}}">
</cr-expand-button>
@@ -79,21 +86,27 @@
<iron-collapse id="inputMethodsCollapse"
opened="[[inputMethodsOpened_]]">
<div class="list-frame vertical-list">
- <template is="dom-repeat" items="{{languages.inputMethods}}">
- <div class$=
- "list-item [[getInputMethodItemClass_(id, currentId)]]">
- <div class="start">
- <div>[[item.name]]</div>
- <iron-icon icon="done"
+ <template is="dom-repeat"
+ items="[[languages.inputMethods.enabled]]">
+ <div class$="list-item [[getInputMethodItemClass_(
+ item.id, languages.inputMethods.currentId)]]"
+ on-tap="onInputMethodTap_">
+ <div>[[item.displayName]]</div>
+ <div class="middle">
+ <iron-icon icon="settings:done"
hidden$="[[!isCurrentInputMethod_(
- item.id, languages.currentInputMethod)]]">
+ item.id, languages.inputMethods.currentId)]]">
</iron-icon>
</div>
- <paper-icon-button icon="settings"></paper-icon-button>
+ <paper-icon-button icon="cr:settings"
+ on-tap="onInputMethodOptionsTap_"
+ hidden$="[[!item.hasOptionsPage]]">
+ </paper-icon-button>
</div>
</template>
<div class="list-item list-button"
- i18n-content="manageInputMethods">
+ on-tap="onManageInputMethodsTap_">
+ $i18n{manageInputMethods}
</div>
</div>
</iron-collapse>
@@ -101,7 +114,7 @@
<if expr="not is_macosx">
<div class="settings-box two-line">
<div class="start">
- <div i18n-content="spellCheckListTitle"></div>
+ <div>$i18n{spellCheckListTitle}</div>
<div class="secondary">[[spellCheckSecondary_]]</div>
</div>
<cr-expand-button expanded="{{spellCheckOpened_}}">
@@ -110,28 +123,28 @@
<iron-collapse id="spellCheckCollapse" opened="[[spellCheckOpened_]]">
<div class="list-frame vertical-list">
<template is="dom-repeat"
- items="[[spellCheckLanguages_(languages.enabledLanguages.*)]]">
+ items="[[spellCheckLanguages_(languages.enabled.*)]]">
<div class="list-item">
<div class="start">
<paper-checkbox
- checked="[[item.state.spellCheckEnabled]]"
+ checked="[[item.spellCheckEnabled]]"
on-change="onSpellCheckChange_">
[[item.language.displayName]]
</paper-checkbox>
</div>
- <paper-icon-button icon="settings"
+ <paper-icon-button icon="cr:settings"
on-tap="onShowLanguageDetailTap_"></paper-icon-button>
</div>
</template>
- <div class="list-item list-button" i18n-content="manageSpellCheck"
- on-tap="onEditDictionaryTap_">
+ <div class="list-item list-button" on-tap="onEditDictionaryTap_">
+ $i18n{manageSpellCheck}
</div>
</div>
</iron-collapse>
</if>
</neon-animatable>
<template is="dom-if" name="manage-languages">
- <settings-subpage page-title="[[i18n('manageLanguagesPageTitle')]]">
+ <settings-subpage page-title="$i18n{manageLanguagesPageTitle}">
<settings-manage-languages-page
prefs="{{prefs}}"></settings-manage-languages-page>
</settings-subpage>
@@ -144,9 +157,17 @@
</settings-language-detail-page>
</settings-subpage>
</template>
+<if expr="chromeos">
+ <template is="dom-if" name="manage-input-methods">
+ <settings-subpage page-title="$i18n{manageInputMethods}">
+ <settings-manage-input-methods-page>
+ </settings-manage-input-methods-page>
+ </settings-subpage>
+ </template>
+</if>
<if expr="not is_macosx">
<template is="dom-if" name="edit-dictionary">
- <settings-subpage page-title="[[i18n('editDictionaryPageTitle')]]">
+ <settings-subpage page-title="$i18n{editDictionaryPageTitle}">
<settings-edit-dictionary-page></settings-edit-dictionary-page>
</settings-subpage>
</template>
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 fe4f6a00e48..b2be1d210cf 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages_page.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -12,10 +12,6 @@
Polymer({
is: 'settings-languages-page',
- behaviors: [
- I18nBehavior,
- ],
-
properties: {
/**
* The current active route.
@@ -36,7 +32,7 @@ Polymer({
/**
* Read-only reference to the languages model provided by the
* 'settings-languages' instance.
- * @type {LanguagesModel|undefined}
+ * @type {!LanguagesModel|undefined}
*/
languages: {
type: Object,
@@ -44,12 +40,6 @@ Polymer({
},
/** @private */
- inputMethodsSecondary_: {
- type: String,
- value: 'Placeholder, e.g. US keyboard',
- },
-
- /** @private */
spellCheckSecondary_: {
type: String,
value: 'Placeholder, e.g. English (United States)',
@@ -57,19 +47,24 @@ Polymer({
/**
* The language to display the details for.
- * @type {!LanguageInfo|undefined}
+ * @type {!LanguageState|undefined}
* @private
*/
detailLanguage_: Object,
+
+ /** @private {!LanguageHelper} */
+ languageHelper_: Object,
},
- /** @private {!LanguageHelper} */
- languageHelper_: LanguageHelperImpl.getInstance(),
+ /** @override */
+ created: function() {
+ this.languageHelper_ = LanguageHelperImpl.getInstance();
+ },
/**
* Handler for clicking a language on the main page, which selects the
* language as the prospective UI language on Chrome OS and Windows.
- * @param {!{model: !{item: !LanguageInfo}}} e
+ * @param {!{model: !{item: !LanguageState}}} e
*/
onLanguageTap_: function(e) {
// Only change the UI language on platforms that allow it.
@@ -87,7 +82,7 @@ Polymer({
/**
* Handler for enabling or disabling spell check.
- * @param {!{target: Element, model: !{item: !LanguageInfo}}} e
+ * @param {!{target: Element, model: !{item: !LanguageState}}} e
*/
onSpellCheckChange_: function(e) {
this.languageHelper_.toggleSpellCheck(e.model.item.language.code,
@@ -110,7 +105,7 @@ Polymer({
/**
* Opens the Language Detail page for the language.
- * @param {!{model: !{item: !LanguageInfo}}} e
+ * @param {!{model: !{item: !LanguageState}}} e
* @private
*/
onShowLanguageDetailTap_: function(e) {
@@ -118,14 +113,52 @@ Polymer({
this.$.pages.setSubpageChain(['language-detail']);
},
-<if expr="not is_macosx">
+ /**
+ * Opens the Manage Input Methods page.
+ * @private
+ */
+ onManageInputMethodsTap_: function() {
+ assert(cr.isChromeOS);
+ this.$.pages.setSubpageChain(['manage-input-methods']);
+ },
+
+ /**
+ * Handler for clicking an input method on the main page, which sets it as
+ * the current input method.
+ * @param {!{model: !{item: !chrome.languageSettingsPrivate.InputMethod},
+ * target: !{tagName: string}}} e
+ */
+ onInputMethodTap_: function(e) {
+ assert(cr.isChromeOS);
+
+ // Taps on the paper-icon-button are handled in onInputMethodOptionsTap_.
+ if (e.target.tagName == 'PAPER-ICON-BUTTON')
+ return;
+
+ // Set the input method.
+ this.languageHelper_.setCurrentInputMethod(e.model.item.id);
+ },
+
+ /**
+ * Opens the input method extension's options page in a new tab (or focuses
+ * an existing instance of the IME's options).
+ * @param {!{model: !{item: chrome.languageSettingsPrivate.InputMethod}}} e
+ * @private
+ */
+ onInputMethodOptionsTap_: function(e) {
+ assert(cr.isChromeOS);
+ this.languageHelper_.openInputMethodOptions(e.model.item.id);
+ },
+
/**
* Returns the enabled languages which support spell check.
+ * @return {!Array<!LanguageState>}
* @private
*/
spellCheckLanguages_: function() {
- return this.languages.enabledLanguages.filter(function(languageInfo) {
- return languageInfo.language.supportsSpellcheck;
+ assert(!cr.isMac);
+ return this.languages.enabled.filter(function(languageState) {
+ return languageState.language.supportsSpellcheck;
});
},
@@ -134,12 +167,11 @@ Polymer({
* @private
*/
onEditDictionaryTap_: function() {
+ assert(!cr.isMac);
this.$.pages.setSubpageChain(['edit-dictionary']);
this.forceRenderList_('settings-edit-dictionary-page');
},
-</if>
-<if expr="chromeos or is_win">
/**
* Checks whether the prospective UI language (the pref that indicates what
* language to use in Chrome) matches the current language. This pref is only
@@ -151,9 +183,9 @@ Polymer({
* @private
*/
isProspectiveUILanguage_: function(languageCode, prospectiveUILanguage) {
+ assert(cr.isChromeOS || cr.isWindows);
return languageCode == this.languageHelper_.getProspectiveUILanguage();
},
-</if>
/**
* @return {string}
@@ -174,14 +206,13 @@ Polymer({
* @private
*/
getLanguageItemClass_: function(languageCode, prospectiveUILanguage) {
-<if expr="chromeos or is_win">
- if (this.isProspectiveUILanguage_(languageCode, prospectiveUILanguage))
+ if ((cr.isChromeOS || cr.isWindows) &&
+ this.isProspectiveUILanguage_(languageCode, prospectiveUILanguage)) {
return 'selected';
-</if>
+ }
return '';
},
-<if expr="chromeos">
/**
* @param {string} id The input method ID.
* @param {string} currentId The ID of the currently enabled input method.
@@ -200,9 +231,18 @@ Polymer({
* @private
*/
getInputMethodItemClass_: function(id, currentId) {
+ assert(cr.isChromeOS);
return this.isCurrentInputMethod_(id, currentId) ? 'selected' : '';
},
-</if>
+
+ getInputMethodName_: function(id) {
+ assert(cr.isChromeOS);
+ var inputMethod = this.languages.inputMethods.enabled.find(
+ function(inputMethod) {
+ return inputMethod.id == id;
+ });
+ return inputMethod ? inputMethod.displayName : '';
+ },
/**
* HACK(michaelpg): This is necessary to show the list when navigating to
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages_types.js b/chromium/chrome/browser/resources/settings/languages_page/languages_types.js
index 0fe9220e23d..0492dd19aa7 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages_types.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages_types.js
@@ -8,28 +8,41 @@
*/
/**
- * Current properties of a language.
- * @typedef {{spellCheckEnabled: boolean, translateEnabled: boolean,
- * removable: boolean}} */
+ * Settings and state for a particular enabled language.
+ * @typedef {{
+ * language: !chrome.languageSettingsPrivate.Language,
+ * removable: boolean,
+ * spellCheckEnabled: boolean,
+ * translateEnabled: boolean,
+ * }}
+ */
var LanguageState;
/**
- * Information about a language including intrinsic information (|language|)
- * and the |state| of the language.
- * @typedef {{language: !chrome.languageSettingsPrivate.Language,
- * state: !LanguageState}}
+ * Input method data to expose to consumers (Chrome OS only).
+ * supported: an array of supported input methods set once at initialization.
+ * enabled: an array of the currently enabled input methods.
+ * currentId: ID of the currently active input method.
+ * @typedef {{
+ * supported: !Array<!chrome.languageSettingsPrivate.InputMethod>,
+ * enabled: !Array<!chrome.languageSettingsPrivate.InputMethod>,
+ * currentId: string,
+ * }}
*/
-var LanguageInfo;
+var InputMethodsModel;
/**
* Languages data to expose to consumers.
- * supportedLanguages: an array of languages, ordered alphabetically.
- * enabledLanguages: an array of enabled language info, ordered by preference.
+ * supported: an array of languages, ordered alphabetically, set once
+ * at initialization.
+ * enabled: an array of enabled language states, ordered by preference.
* translateTarget: the default language to translate into.
+ * inputMethods: the InputMethodsModel (Chrome OS only).
* @typedef {{
- * supportedLanguages: !Array<!chrome.languageSettingsPrivate.Language>,
- * enabledLanguages: !Array<!LanguageInfo>,
- * translateTarget: string
+ * supported: !Array<!chrome.languageSettingsPrivate.Language>,
+ * enabled: !Array<!LanguageState>,
+ * translateTarget: string,
+ * inputMethods: (!InputMethodsModel|undefined),
* }}
*/
var LanguagesModel;
@@ -45,7 +58,9 @@ var LanguageHelper = function() {};
LanguageHelper.prototype = {
-<if expr="chromeos or is_win">
+ /** @return {!Promise} */
+ whenReady: assertNotReached,
+
/**
* Sets the prospective UI language to the chosen language. This won't affect
* the actual UI language until a restart.
@@ -55,7 +70,6 @@ LanguageHelper.prototype = {
/** Resets the prospective UI language back to the actual UI language. */
resetUILanguage: assertNotReached,
-</if>
/**
* Returns the "prospective" UI language, i.e. the one to be used on next
@@ -120,8 +134,55 @@ LanguageHelper.prototype = {
convertLanguageCodeForTranslate: assertNotReached,
/**
+ * Given a language code, returns just the base language. E.g., converts
+ * 'en-GB' to 'en'.
+ * @param {string} languageCode
+ * @return {string}
+ */
+ getLanguageCodeWithoutRegion: assertNotReached,
+
+ /**
* @param {string} languageCode
* @return {!chrome.languageSettingsPrivate.Language|undefined}
*/
getLanguage: assertNotReached,
+
+ /**
+ * @param {string} id
+ * @return {!chrome.languageSettingsPrivate.InputMethod|undefined}
+ */
+ getInputMethod: assertNotReached,
+
+ /** @param {string} id */
+ addInputMethod: assertNotReached,
+
+ /** @param {string} id */
+ removeInputMethod: assertNotReached,
+
+ /** @param {string} id */
+ setCurrentInputMethod: assertNotReached,
+
+ /**
+ * param {string} languageCode
+ * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>}
+ */
+ getInputMethodsForLanguage: assertNotReached,
+
+ /**
+ * @param {!chrome.languageSettingsPrivate.InputMethod} inputMethod
+ * @return {boolean}
+ */
+ isComponentIme: assertNotReached,
+
+ /** @param {string} id Input method ID. */
+ openInputMethodOptions: assertNotReached,
+
+ /** @param {string} id New current input method ID. */
+ onInputMethodChanged_: assertNotReached,
+
+ /** @param {string} id Added input method ID. */
+ onInputMethodAdded_: assertNotReached,
+
+ /** @param {string} id Removed input method ID. */
+ onInputMethodRemoved_: assertNotReached,
};
diff --git a/chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html b/chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html
new file mode 100644
index 00000000000..6973f876b8d
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.html
@@ -0,0 +1,33 @@
+<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/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+<link rel="import" href="languages.html">
+
+<dom-module id="settings-manage-input-methods-page">
+ <template>
+ <style include="settings-shared"></style>
+ <settings-languages languages="{{languages}}"></settings-languages>
+ <div class="settings-box first block">
+ <template is="dom-repeat" items="[[languageList_]]">
+ <h2>[[item.language.displayName]]</h2>
+ <div class="list-frame vertical-list">
+ <template is="dom-repeat" items="[[item.inputMethods]]">
+ <div class="list-item">
+ <div class="language-name">
+ <paper-checkbox checked="[[item.enabled]]"
+ on-change="onCheckboxChange_"
+ disabled="[[!enableInputMethodCheckbox_(
+ item, languages.inputMethods.enabled.*)]]">
+ <span>[[item.displayName]]</span>
+ </paper-checkbox>
+ </div>
+ </div>
+ </template>
+ </div>
+ </template>
+ </div>
+ </template>
+ <script src="manage_input_methods_page.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js b/chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js
new file mode 100644
index 00000000000..cb794f52b96
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/languages_page/manage_input_methods_page.js
@@ -0,0 +1,197 @@
+// 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-manage-input-methods-page' is a sub-page for enabling
+ * and disabling input methods. Input methods are grouped by base languages to
+ * avoid showing duplicate or ambiguous input methods.
+ *
+ * @group Chrome Settings Elements
+ * @element settings-manage-input-methods-page
+ */
+Polymer({
+ is: 'settings-manage-input-methods-page',
+
+ properties: {
+ /** @type {!LanguagesModel|undefined} */
+ languages: {
+ type: Object,
+ notify: true,
+ },
+
+ /**
+ * List of enabled languages with the input methods to show.
+ * @private {!Array<
+ * !{language: !chrome.languageSettingsPrivate.Language,
+ * inputMethods: !Array<!chrome.languageSettingsPrivate.InputMethod>
+ * }>}
+ */
+ languageList_: {
+ type: Array,
+ value: function() { return []; },
+ },
+ },
+
+ observers: [
+ 'availableInputMethodsChanged_(languages.enabled.*,' +
+ 'languages.inputMethods.supported.*)',
+ 'enabledInputMethodsChanged_(languages.inputMethods.enabled.*)',
+ ],
+
+ /** @override */
+ created: function() {
+ this.languageHelper_ = LanguageHelperImpl.getInstance();
+ },
+
+ /** @private */
+ availableInputMethodsChanged_: function() {
+ this.populateLanguageList_();
+ },
+
+ /** @private */
+ enabledInputMethodsChanged_: function() {
+ this.populateLanguageList_();
+ },
+
+ /**
+ * Handler for an input method checkbox.
+ * @param {!{model: !{item: chrome.languageSettingsPrivate.InputMethod},
+ * target: !PaperCheckboxElement}} e
+ * @private
+ */
+ onCheckboxChange_: function(e) {
+ // TODO(michaelpg): Show confirmation dialog for 3rd-party IMEs.
+ var id = e.model.item.id;
+ if (e.target.checked)
+ this.languageHelper_.addInputMethod(id);
+ else
+ this.languageHelper_.removeInputMethod(id);
+ },
+
+ /**
+ * Returns true if the input method can be removed.
+ * @param {!chrome.languageSettingsPrivate.InputMethod} targetInputMethod
+ * @param {!Object} change Polymer change object (provided in the HTML so this
+ * gets called whenever languages.inputMethods.enabled.* changes).
+ * @return {boolean}
+ * @private
+ */
+ enableInputMethodCheckbox_: function(targetInputMethod, change) {
+ if (!targetInputMethod.enabled)
+ return true;
+
+ // Third-party IMEs can always be removed.
+ if (!this.languageHelper_.isComponentIme(targetInputMethod))
+ return true;
+
+ // Can be removed as long as there is another component IME.
+ return this.languages.inputMethods.enabled.some(function(inputMethod) {
+ return inputMethod != targetInputMethod &&
+ this.languageHelper_.isComponentIme(inputMethod);
+ }, this);
+ },
+
+ /**
+ * Creates the list of languages and their input methods as the data source
+ * for the view.
+ * @private
+ */
+ populateLanguageList_: function() {
+ var languageList = [];
+
+ // Languages that have already been listed further up.
+ var /** !Set<string> */ usedLanguages = new Set();
+
+ // Add languages in preference order. However, if there are multiple
+ // enabled variants of the same base language, group them all as the base
+ // language instead of showing each variant individually. This prevents us
+ // from displaying duplicate input methods under different variants.
+ for (var i = 0; i < this.languages.enabled.length; i++) {
+ var languageState = this.languages.enabled[i];
+ // Skip the language if we have already included it or its base language.
+ if (usedLanguages.has(languageState.language.code))
+ continue;
+ var baseLanguageCode = this.languageHelper_.getLanguageCodeWithoutRegion(
+ languageState.language.code);
+ if (usedLanguages.has(baseLanguageCode))
+ continue;
+
+ // Find the other languages further down in the preferred languages list
+ // which also use this language's base language code.
+ var languageFamilyCodes = [languageState.language.code];
+ for (var j = i + 1; j < this.languages.enabled.length; j++) {
+ var otherCode = this.languages.enabled[j].language.code;
+ if (this.languageHelper_.getLanguageCodeWithoutRegion(otherCode) ==
+ baseLanguageCode) {
+ languageFamilyCodes.push(this.languages.enabled[j].language.code);
+ }
+ }
+
+ var combinedInputMethods =
+ this.getInputMethodsForLanguages(languageFamilyCodes);
+
+ // Skip the language if it has no new input methods.
+ if (!combinedInputMethods.length)
+ continue;
+
+ // Add the language or base language.
+ var displayLanguage = languageState.language;
+ if (languageFamilyCodes.length > 1) {
+ var baseLanguage = this.languageHelper_.getLanguage(baseLanguageCode);
+ if (baseLanguage)
+ displayLanguage = baseLanguage;
+ }
+ languageList.push({
+ language: displayLanguage,
+ inputMethods: combinedInputMethods,
+ });
+ for (var languageCode of languageFamilyCodes)
+ usedLanguages.add(languageCode);
+ }
+
+ this.languageList_ = languageList;
+ this.notifyInputMethodsChanged_();
+ },
+
+ /**
+ * Returns the input methods that support any of the given languages.
+ * @param {!Array<string>} languageCodes
+ * @return {!Array<!chrome.languageSettingsPrivate.InputMethod>}
+ * @private
+ */
+ getInputMethodsForLanguages: function(languageCodes) {
+ // Input methods that have already been listed for this language.
+ var /** !Set<string> */ usedInputMethods = new Set();
+ /** @type {!Array<chrome.languageSettingsPrivate.InputMethod>} */
+ var combinedInputMethods = [];
+ for (var languageCode of languageCodes) {
+ var inputMethods = this.languageHelper_.getInputMethodsForLanguage(
+ languageCode);
+ // Get the language's unused input methods and mark them as used.
+ var newInputMethods = inputMethods.filter(function(inputMethod) {
+ if (usedInputMethods.has(inputMethod.id))
+ return false;
+ usedInputMethods.add(inputMethod.id);
+ return true;
+ });
+ [].push.apply(combinedInputMethods, newInputMethods);
+ }
+ return combinedInputMethods;
+ },
+
+ // TODO(Polymer/polymer#3603): We have to notify Polymer of properties that
+ // may have changed on nested objects, even when the outer property itself
+ // is set to a new array.
+ // TODO(michaelpg): Test this behavior.
+ /** @private */
+ notifyInputMethodsChanged_: function() {
+ for (var i = 0; i < this.languageList_.length; i++) {
+ for (var j = 0; j < this.languageList_[i].inputMethods.length; j++) {
+ this.notifyPath(
+ 'languageList_.' + i + '.inputMethods.' + j + '.enabled',
+ this.languageList_[i].inputMethods[j].enabled);
+ }
+ }
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.html b/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.html
index d193e594431..fb77e2b5b55 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.html
@@ -1,7 +1,7 @@
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<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/iron-list/iron-list.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">
@@ -22,38 +22,35 @@
}
</style>
<settings-languages languages="{{languages}}"></settings-languages>
- <div class="settings-box first content">
- <div class="start">
- <h2 i18n-content="enabledLanguages"></h2>
- <div class="list-frame vertical-list">
- <template is="dom-repeat" items="{{languages.enabledLanguages}}">
+ <div class="settings-box first block">
+ <h2>$i18n{enabledLanguages}</h2>
+ <div class="list-frame vertical-list">
+ <template is="dom-repeat" items="{{languages.enabled}}">
+ <div class="list-item">
+ <div class="start" title="[[item.language.nativeDisplayName]]">
+ [[item.language.displayName]]
+ </div>
+ <paper-icon-button icon="cr:clear"
+ on-tap="onRemoveLanguageTap_" hidden$="[[!item.removable]]">
+ </paper-icon-button>
+ </div>
+ </template>
+ </div>
+ <h2>$i18n{allLanguages}</h2>
+ <div class="list-frame vertical-list">
+ <iron-list items="{{languages.supported}}">
+ <template>
<div class="list-item">
- <div class="start" title="[[item.language.nativeDisplayName]]">
- [[item.language.displayName]]
- </div>
- <paper-icon-button icon="clear" on-tap="onRemoveLanguageTap_"
- hidden$="[[!canRemoveLanguage_(
- item.language.code, prefs.intl.app_locale.value)]]">
- </paper-icon-button>
+ <paper-checkbox
+ checked="[[isCheckboxChecked_(item, languages.enabled.*)]]"
+ disabled="[[isLanguageRequired_(item, languages.enabled.*)]]"
+ title$="[[item.nativeDisplayName]]"
+ on-change="onLanguageCheckboxChange_">
+ [[item.displayName]]
+ </paper-checkbox>
</div>
</template>
- </div>
- <h2 i18n-content="allLanguages"></h2>
- <div class="list-frame vertical-list">
- <iron-list items="{{availableLanguages_}}" as="item">
- <template>
- <div class="list-item">
- <paper-checkbox checked="[[item.enabled]]"
- title$="[[item.nativeDisplayName]]"
- disabled="[[!canRemoveLanguage_(
- item.code, prefs.intl.app_locale.value)]]"
- on-change="onLanguageCheckboxChange_">
- [[item.displayName]]
- </paper-checkbox>
- </div>
- </template>
- </iron-list>
- </div>
+ </iron-list>
</div>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.js b/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.js
index c7e44bfad36..2de5a18198b 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/manage_languages_page.js
@@ -26,24 +26,45 @@ Polymer({
notify: true,
},
- /**
- * @private {!Array<!{code: string, displayName: string,
- * nativeDisplayName: string, enabled: boolean}>|
- * undefined}
- */
- availableLanguages_: Array,
+ /** @private {!LanguageHelper} */
+ languageHelper_: Object,
},
- /** @private {!LanguageHelper} */
- languageHelper_: LanguageHelperImpl.getInstance(),
+ /** @override */
+ created: function() {
+ this.languageHelper_ = LanguageHelperImpl.getInstance();
+ },
- observers: [
- 'enabledLanguagesChanged_(languages.enabledLanguages.*)',
- ],
+ /**
+ * @param {!chrome.languageSettingsPrivate.Language} language
+ * @param {!Object} change Polymer change object (provided in the HTML so this
+ * gets called whenever languages.enabled.* changes).
+ * @return {boolean}
+ * @private
+ */
+ isCheckboxChecked_: function(language, change) {
+ return this.languageHelper_.isLanguageEnabled(language.code);
+ },
+
+ /**
+ * Determines whether a language must be enabled. If so, the checkbox in the
+ * available languages list should not be changeable.
+ * @param {!chrome.languageSettingsPrivate.Language} language
+ * @param {!Object} change Polymer change object (provided in the HTML so this
+ * gets called whenever languages.enabled.* changes).
+ * @return {boolean}
+ * @private
+ */
+ isLanguageRequired_: function(language, change) {
+ // This check only applies to enabled languages.
+ if (!this.languageHelper_.isLanguageEnabled(language.code))
+ return false;
+ return !this.languageHelper_.canDisableLanguage(language.code);
+ },
/**
* Handler for removing a language.
- * @param {!{model: !{item: !LanguageInfo}}} e
+ * @param {!{model: !{item: !LanguageState}}} e
* @private
*/
onRemoveLanguageTap_: function(e) {
@@ -63,48 +84,4 @@ Polymer({
else
this.languageHelper_.disableLanguage(code);
},
-
- /**
- * True if a language is not the current or prospective UI language, ie,
- * it could be disabled.
- * @param {string} languageCode
- * @param {string} prospectiveUILanguageCode
- * @return {boolean}
- * @private
- */
- canRemoveLanguage_: function(languageCode, prospectiveUILanguageCode) {
- if (languageCode == navigator.language ||
- languageCode == prospectiveUILanguageCode) {
- return false;
- }
- return true;
- },
-
- /**
- * Updates the available languages that are bound to the iron-list.
- * @private
- */
- enabledLanguagesChanged_: function() {
- if (!this.availableLanguages_) {
- var availableLanguages = [];
- for (var i = 0; i < this.languages.supportedLanguages.length; i++) {
- var language = this.languages.supportedLanguages[i];
- availableLanguages.push({
- code: language.code,
- displayName: language.displayName,
- nativeDisplayName: language.nativeDisplayName,
- enabled: this.languageHelper_.isLanguageEnabled(language.code),
- });
- }
- // Set the Polymer property after building the full array.
- this.availableLanguages_ = availableLanguages;
- } else {
- // Update the available languages in place.
- for (var i = 0; i < this.availableLanguages_.length; i++) {
- this.set('availableLanguages_.' + i + '.enabled',
- this.languageHelper_.isLanguageEnabled(
- this.availableLanguages_[i].code));
- }
- }
- },
});
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 d7d853145da..5e63905cfb7 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
@@ -12,10 +12,9 @@
'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:promise_resolver',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'startup_urls_page_browser_proxy',
+ 'startup_url_entry',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -24,10 +23,18 @@
'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:promise_resolver',
'<(EXTERNS_GYP):chrome_send',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'startup_url_entry',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
+ '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 e51905bca65..2e00c1e00ce 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
@@ -25,8 +25,7 @@
</div>
<template is="dom-if"
if="[[showStartupUrls_(prefs.session.restore_on_startup.value)]]">
- <settings-startup-urls-page prefs="{{prefs}}">
- </settings-startup-urls-page>
+ <settings-startup-urls-page></settings-startup-urls-page>
</template>
</template>
<script src="on_startup_page.js"></script>
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
new file mode 100644
index 00000000000..17b885cadc0
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.html
@@ -0,0 +1,30 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://md-settings/on_startup_page/startup_urls_page_browser_proxy.html">
+<link rel="import" href="chrome://md-settings/settings_dialog.html">
+
+<dom-module id="settings-startup-url-dialog">
+ <template>
+ <style include="settings-shared"></style>
+ <settings-dialog id="dialog">
+ <div class="title">[[dialogTitle_]]</div>
+ <div class="body">
+ <paper-input always-float-label id="url"
+ value="{{url_}}" on-input="validate_">
+ $i18n{onStartupSiteUrl}
+ </paper-input>
+ </div>
+ <div class="button-container">
+ <div class="action-buttons">
+ <paper-button class="cancel-button" on-tap="onCancelTap_"
+ id="cancel">$i18n{cancel}</paper-button>
+ <paper-button id="actionButton" class="action-button"
+ on-tap="onActionButtonTap_">[[actionButtonText_]]</paper-button>
+ </div>
+ </div>
+ </settings-dialog>
+ </template>
+ <script src="startup_url_dialog.js"></script>
+</dom-module>
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
new file mode 100644
index 00000000000..516d7304d88
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.js
@@ -0,0 +1,76 @@
+// 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-startup-url-dialog' is a component for adding
+ * or editing a startup URL entry.
+ */
+Polymer({
+ is: 'settings-startup-url-dialog',
+
+ properties: {
+ /** @private {string} */
+ url_: String,
+
+ /**
+ * If specified the dialog acts as an "Edit page" dialog, otherwise as an
+ * "Add new page" dialog.
+ * @type {?StartupPageInfo}
+ */
+ model: Object,
+
+ /** @private {string} */
+ dialogTitle_: String,
+
+ /** @private {string} */
+ actionButtonText_: String,
+ },
+
+ /** @private {!settings.SearchEnginesBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ attached: function() {
+ this.browserProxy_ = settings.StartupUrlsPageBrowserProxyImpl.getInstance();
+
+ if (this.model) {
+ this.dialogTitle_ = loadTimeData.getString('onStartupEditPage');
+ this.actionButtonText_ = loadTimeData.getString('onStartupEdit');
+ this.$.actionButton.disabled = false;
+ // Pre-populate the input field.
+ this.url_ = this.model.url;
+ } else {
+ this.dialogTitle_ = loadTimeData.getString('onStartupAddNewPage');
+ this.actionButtonText_ = loadTimeData.getString('add');
+ this.$.actionButton.disabled = true;
+ }
+ this.$.dialog.open();
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ this.$.dialog.close();
+ },
+
+ /** @private */
+ onActionButtonTap_: function() {
+ var whenDone = this.model ?
+ this.browserProxy_.editStartupPage(this.model.modelIndex, this.url_) :
+ this.browserProxy_.addStartupPage(this.url_);
+
+ whenDone.then(function(success) {
+ if (success)
+ this.$.dialog.close();
+ // If the URL was invalid, there is nothing to do, just leave the dialog
+ // open and let the user fix the URL or cancel.
+ }.bind(this));
+ },
+
+ /** @private */
+ validate_: function() {
+ this.browserProxy_.validateStartupPage(this.url_).then(function(isValid) {
+ this.$.actionButton.disabled = !isValid;
+ }.bind(this));
+ },
+});
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
new file mode 100644
index 00000000000..6f50afea6d2
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html
@@ -0,0 +1,46 @@
+<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/icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.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-item/paper-item.html">
+<link rel="import" href="chrome://md-settings/on_startup_page/startup_urls_page_browser_proxy.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+
+<dom-module id="settings-startup-url-entry">
+ <template>
+ <style include="settings-shared">
+ .dropdown-content {
+ background: white;
+ box-shadow: 0 2px 6px grey;
+ }
+
+ paper-item:hover {
+ background-color: var(--settings-hover-color);
+ }
+ </style>
+ <div class="list-item underbar">
+ <div class="favicon-image"
+ style="background-image: [[getIconSet_(model.url)]]">
+ </div>
+ <div class="middle">
+ <div class="text-elide">[[model.title]]</div>
+ <div class="text-elide secondary">[[model.url]]</div>
+ </div>
+ <paper-icon-button id="dots" icon="cr:more-vert" toggles
+ active="{{menuOpened}}"></paper-icon-button>
+ <template is="dom-if" if="[[menuOpened]]">
+ <iron-dropdown vertical-align="top" horizontal-align="right"
+ opened="{{menuOpened}}">
+ <div class="dropdown-content">
+ <paper-item on-tap="onEditTap_">$i18n{onStartupEdit}</paper-item>
+ <paper-item id="remove" on-tap="onRemoveTap_">
+ $i18n{onStartupRemove}
+ </paper-item>
+ </div>
+ </iron-dropdown>
+ </template>
+ </div>
+ </template>
+ <script src="startup_url_entry.js"></script>
+</dom-module>
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
new file mode 100644
index 00000000000..a42b8eb9028
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js
@@ -0,0 +1,49 @@
+// 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-startup-url-entry represents a UI component that
+ * displayes a URL that is loaded during startup. It includes a menu that allows
+ * the user to edit/remove the entry.
+ */
+
+cr.exportPath('settings');
+
+/**
+ * The name of the event fired from this element when the "Edit" option is
+ * tapped.
+ * @const {string}
+ */
+settings.EDIT_STARTUP_URL_EVENT = 'edit-startup-url';
+
+Polymer({
+ is: 'settings-startup-url-entry',
+
+ properties: {
+ /** @type {!StartupPageInfo} */
+ model: Object,
+ },
+
+ /**
+ * @param {string} url Location of an image to get a set of icons for.
+ * @return {string} A set of icon URLs.
+ * @private
+ */
+ getIconSet_: function(url) {
+ return cr.icon.getFaviconImageSet(url);
+ },
+
+ /** @private */
+ onRemoveTap_: function() {
+ this.$$('iron-dropdown').close();
+ settings.StartupUrlsPageBrowserProxyImpl.getInstance().removeStartupPage(
+ this.model.modelIndex);
+ },
+
+ /** @private */
+ onEditTap_: function() {
+ this.$$('iron-dropdown').close();
+ this.fire(settings.EDIT_STARTUP_URL_EVENT, this.model);
+ },
+});
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 725325a374f..4576fffdbfe 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
@@ -1,59 +1,29 @@
<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/paper-input/paper-input.html">
-<link rel="import" href="chrome://md-settings/settings_dialog.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+<link rel="import" href="chrome://md-settings/on_startup_page/startup_url_dialog.html">
+<link rel="import" href="chrome://md-settings/on_startup_page/startup_url_entry.html">
<link rel="import" href="chrome://md-settings/on_startup_page/startup_urls_page_browser_proxy.html">
<dom-module id="settings-startup-urls-page">
<link rel="import" type="css" href="on_startup_shared.css">
<template>
- <style include="settings-shared">
- .favicon-image {
- background-size: contain;
- background-repeat: no-repeat;
- height: 16px;
- width: 16px;
- }
- </style>
+ <style include="settings-shared"></style>
<div class="list-frame vertical-list">
<template is="dom-repeat" items="[[startupPages_]]">
- <div class="list-item">
- <div class="favicon-image"
- style="background-image: [[getIconSet_(item.url)]]">
- </div>
- <div class="middle">
- <div class="text-elide">[[item.title]]</div>
- <div class="text-elide secondary">[[item.url]]</div>
- </div>
- <iron-icon on-tap="onRemoveUrlTap_" icon="clear"></iron-icon>
- </div>
+ <settings-startup-url-entry model="[[item]]">
+ </settings-startup-url-entry>
</template>
<div class="list-item list-button" id="addPage" on-tap="onAddPageTap_">
$i18n{onStartupAddNewPage}
</div>
- <div class="list-item list-button" on-tap="onUseCurrentPagesTap_">
- $i18n{onStartupUseCurrent}
- </div>
+ <div class="list-item list-button" id="useCurrentPages"
+ on-tap="onUseCurrentPagesTap_">$i18n{onStartupUseCurrent}</div>
</div>
-
- <settings-dialog id="addUrlDialog">
- <div class="title">$i18n{onStartupAddNewPage}</div>
- <div class="body">
- <paper-input class="flex" always-float-label id="newUrl"
- label="$i18n{onStartupSiteUrl}" value="{{newUrl_}}">
- </paper-input>
- </div>
- <div class="button-container">
- <div class="action-buttons">
- <paper-button class="cancel-button" on-tap="onCancelTap_"
- id="cancel">$i18n{cancel}</paper-button>
- <paper-button id="add" class="action-button" on-tap="onAddTap_"
- disabled="[[!isNewUrlValid_]]">$i18n{add}</paper-button>
- </div>
- </div>
- </settings-dialog>
+ <template is="dom-if" if="[[showStartupUrlDialog_]]" restamp>
+ <settings-startup-url-dialog model="[[startupUrlDialogModel_]]">
+ </settings-startup-url-dialog>
+ </template>
</template>
<script src="startup_urls_page.js"></script>
</dom-module>
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 51669432735..6941c08dfaa 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
@@ -3,133 +3,71 @@
// found in the LICENSE file.
/**
- * @typedef {{
- * 'title': string,
- * 'tooltip': string,
- * 'url': string
- * }}
- */
-var StartupPageInfo;
-
-/**
* @fileoverview 'settings-startup-urls-page' is the settings page
* containing the urls that will be opened when chrome is started.
- *
- * Example:
- *
- * <neon-animated-pages>
- * <settings-startup-urls-page prefs="{{prefs}}">
- * </settings-startup-urls-page>
- * ... other pages ...
- * </neon-animated-pages>
*/
+
Polymer({
is: 'settings-startup-urls-page',
behaviors: [WebUIListenerBehavior],
properties: {
- /**
- * Preferences state.
- */
- prefs: {
- type: Object,
- notify: true,
- },
-
/** @type {settings.StartupUrlsPageBrowserProxy} */
browserProxy_: Object,
- /** @private {string} */
- newUrl_: {
- observer: 'newUrlChanged_',
- type: String,
- value: '',
- },
-
- isNewUrlValid_: {
- type: Boolean,
- value: false,
- },
-
/**
* Pages to load upon browser startup.
* @private {!Array<!StartupPageInfo>}
*/
startupPages_: Array,
- },
- created: function() {
- this.browserProxy_ = settings.StartupUrlsPageBrowserProxyImpl.getInstance();
+ /** @private */
+ showStartupUrlDialog_: Boolean,
+
+ /** @private {?StartupPageInfo} */
+ startupUrlDialogModel_: Object,
},
+ /** @override */
attached: function() {
- this.addWebUIListener('update-startup-pages',
- this.updateStartupPages_.bind(this));
+ this.browserProxy_ = settings.StartupUrlsPageBrowserProxyImpl.getInstance();
+ this.addWebUIListener('update-startup-pages', function(startupPages) {
+ this.startupPages_ = startupPages;
+ }.bind(this));
this.browserProxy_.loadStartupPages();
- },
- /**
- * @param {string} url Location of an image to get a set of icons fors.
- * @return {string} A set of icon URLs.
- * @private
- */
- getIconSet_: function(url) {
- return getFaviconImageSet(url);
- },
-
- /** @private */
- updateStartupPages_: function(startupPages) {
- this.startupPages_ = startupPages;
+ this.addEventListener(settings.EDIT_STARTUP_URL_EVENT, function(event) {
+ this.startupUrlDialogModel_ = event.detail;
+ this.openDialog_();
+ event.stopPropagation();
+ }.bind(this));
},
/** @private */
onAddPageTap_: function() {
- this.newUrl_ = '';
- this.$.addUrlDialog.open();
- },
-
- /** @private */
- onUseCurrentPagesTap_: function() {
- this.browserProxy_.useCurrentPages();
- },
-
- /** @private */
- onCancelTap_: function() {
- this.$.addUrlDialog.close();
+ this.openDialog_();
},
/**
- * @param {string} newUrl
+ * Opens the dialog and registers a listener for removing the dialog from the
+ * DOM once is closed. The listener is destroyed when the dialog is removed
+ * (because of 'restamp').
* @private
*/
- newUrlChanged_: function(newUrl) {
- if (this.validationResolver_)
- this.validationResolver_.reject(false);
-
- /** @type {?PromiseResolver<boolean>} */
- this.validationResolver_ = this.browserProxy_.validateStartupPage(newUrl);
-
- this.validationResolver_.promise.then(function(isValid) {
- this.isNewUrlValid_ = isValid;
- this.validationResolver_ = null;
- }.bind(this), function() {
- // Squelchs console errors.
- });
+ openDialog_: function() {
+ this.showStartupUrlDialog_ = true;
+ this.async(function() {
+ var dialog = this.$$('settings-startup-url-dialog');
+ dialog.addEventListener('iron-overlay-closed', function() {
+ this.showStartupUrlDialog_ = false;
+ this.startupUrlDialogModel_ = null;
+ }.bind(this));
+ }.bind(this));
},
/** @private */
- onAddTap_: function() {
- assert(this.isNewUrlValid_);
- this.browserProxy_.addStartupPage(this.newUrl_);
- this.$.addUrlDialog.close();
- },
-
- /**
- * @param {!{model: !{index: number}}} e
- * @private
- */
- onRemoveUrlTap_: function(e) {
- this.browserProxy_.removeStartupPage(e.model.index);
+ onUseCurrentPagesTap_: function() {
+ this.browserProxy_.useCurrentPages();
},
});
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.js b/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.js
index 025748f5009..b33e31ae931 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.js
@@ -2,6 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/**
+ * @typedef {{
+ * modelIndex: number,
+ * title: string,
+ * tooltip: string,
+ * url: string
+ * }}
+ */
+var StartupPageInfo;
+
cr.define('settings', function() {
/** @interface */
function StartupUrlsPageBrowserProxy() {}
@@ -13,13 +23,25 @@ cr.define('settings', function() {
/**
* @param {string} url
- * @return {!PromiseResolver<boolean>} Whether the URL is valid.
+ * @return {!Promise<boolean>} Whether the URL is valid.
*/
validateStartupPage: assertNotReached,
- /** @param {string} url */
+ /**
+ * @param {string} url
+ * @return {!Promise<boolean>} Whether the URL was actually added, or
+ * ignored because it was invalid.
+ */
addStartupPage: assertNotReached,
+ /**
+ * @param {number} modelIndex
+ * @param {string} url
+ * @return {!Promise<boolean>} Whether the URL was actually edited, or
+ * ignored because it was invalid.
+ */
+ editStartupPage: assertNotReached,
+
/** @param {number} index */
removeStartupPage: assertNotReached,
};
@@ -45,15 +67,17 @@ cr.define('settings', function() {
/** @override */
validateStartupPage: function(url) {
- var resolver = new PromiseResolver();
- resolver.promise = url.trim().length == 0 ? Promise.resolve(false) :
- cr.sendWithPromise('validateStartupPage', url);
- return resolver;
+ return cr.sendWithPromise('validateStartupPage', url);
},
/** @override */
addStartupPage: function(url) {
- chrome.send('addStartupPage', [url.trim()]);
+ return cr.sendWithPromise('addStartupPage', url);
+ },
+
+ /** @override */
+ editStartupPage: function(modelIndex, url) {
+ return cr.sendWithPromise('editStartupPage', modelIndex, url);
},
/** @override */
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
new file mode 100644
index 00000000000..15cd965831a
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
@@ -0,0 +1,78 @@
+<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/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="chrome://md-settings/passwords_and_forms_page/passwords_shared_css.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+
+<dom-module id="settings-autofill-section">
+ <template>
+ <style include="settings-shared passwords-shared">
+ .link-item {
+ border-top: var(--settings-separator-line);
+ }
+
+ .type-column {
+ align-items: center;
+ flex: 2;
+ }
+
+ .expiration-column {
+ align-items: center;
+ display: flex;
+ flex: 1;
+ }
+
+ .expiration-date {
+ flex: 1;
+ }
+ </style>
+ <div class="heading">$i18n{addresses}</div>
+ <div class="item-list">
+ <iron-list id="addressList" items="[[addresses]]"
+ class="vertical-list list-section">
+ <template>
+ <div class="list-item two-line">
+ <div id="addressSummary" class="start">[[address_(item)]]</div>
+ <paper-icon-button id="addressMenu" icon="more-vert"
+ tabindex$="[[tabIndex]]">
+ </paper-icon-button>
+ </div>
+ </template>
+ </iron-list>
+ <div class="list-item link-item">
+ <a is="action-link" on-tap="onAddAddressTap_">$i18n{addAddress}</a>
+ </div>
+ </div>
+ <div class="heading">$i18n{creditCards}</div>
+ <div class="item-list">
+ <div class="list-item column-header">
+ <div class="type-column">$i18n{creditCardType}</div>
+ <div class="expiration-column">$i18n{creditCardExpiration}</div>
+ </div>
+ <iron-list id="creditCardList" items="[[creditCards]]"
+ class="vertical-list list-section list-with-header">
+ <template>
+ <div class="list-item two-line">
+ <div id="creditCardLabel"
+ class="type-column">[[item.metadata.summaryLabel]]</div>
+ <div class="expiration-column">
+ <div id="creditCardExpiration"
+ class="expiration-date">[[expiration_(item)]]</div>
+ <paper-icon-button icon="more-vert"
+ tabindex$="[[tabIndex]]">
+ </paper-icon-button>
+ </div>
+ </div>
+ </template>
+ </iron-list>
+ <div class="list-item link-item">
+ <a is="action-link" on-tap="onAddCreditCardTap_">
+ $i18n{addCreditCard}
+ </a>
+ </div>
+ </div>
+ </template>
+ <link rel="import" type="css" href="chrome://resources/css/action_link.css">
+ <script src="chrome://md-settings/passwords_and_forms_page/autofill_section.js"></script>
+</dom-module>
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
new file mode 100644
index 00000000000..1aa535287a7
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
@@ -0,0 +1,69 @@
+// 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-autofill-section' is the section containing saved
+ * addresses and credit cards for use in autofill.
+ */
+(function() {
+ 'use strict';
+
+ Polymer({
+ is: 'settings-autofill-section',
+
+ properties: {
+ /**
+ * An array of saved addresses.
+ * @type {!Array<!chrome.autofillPrivate.AddressEntry>}
+ */
+ addresses: {
+ type: Array,
+ },
+
+ /**
+ * An array of saved addresses.
+ * @type {!Array<!chrome.autofillPrivate.CreditCardEntry>}
+ */
+ creditCards: {
+ type: Array,
+ },
+ },
+
+ /**
+ * Formats an AddressEntry so it's displayed as an address.
+ * @param {!chrome.autofillPrivate.AddressEntry} item
+ * @return {!string}
+ */
+ address_: function(item) {
+ return item.metadata.summaryLabel + item.metadata.summarySublabel;
+ },
+
+ /**
+ * Formats the expiration date so it's displayed as MM/YYYY.
+ * @param {!chrome.autofillPrivate.CreditCardEntry} item
+ * @return {!string}
+ */
+ expiration_: function(item) {
+ return item.expirationMonth + '/' + item.expirationYear;
+ },
+
+ /**
+ * Handles tapping on the "Add address" button.
+ * @param {!Event} e
+ */
+ onAddAddressTap_: function(e) {
+ // TODO(hcarmona): implement this.
+ e.preventDefault();
+ },
+
+ /**
+ * Handles tapping on the "Add credit card" button.
+ * @param {!Event} e
+ */
+ onAddCreditCardTap_: function(e) {
+ // TODO(hcarmona): implement this.
+ e.preventDefault();
+ },
+ });
+})();
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 cec537426c7..9395fccc595 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
@@ -10,14 +10,21 @@
'../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:cr',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):passwords_private',
'<(EXTERNS_GYP):settings_private',
+ 'autofill_section',
'passwords_section',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'autofill_section',
+ 'dependencies': [
+ '<(EXTERNS_GYP):autofill_private',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'passwords_section',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp:cr_shared_menu',
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 604142e565d..1a5b0422c65 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
@@ -2,6 +2,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="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_dialog.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
@@ -23,31 +24,30 @@
}
</style>
<settings-dialog id="dialog">
- <div class="title" i18n-content="editPasswordTitle"></div>
+ <div class="title">$i18n{editPasswordTitle}</div>
<div class="body">
- <paper-input id="websiteInput"
- i18n-values="label:editPasswordWebsiteLabel"
+ <paper-input id="websiteInput" label="$i18n{editPasswordWebsiteLabel}"
value="[[item.loginPair.originUrl]]">
</paper-input>
- <paper-input id="usernameInput"
- i18n-values="label:editPasswordUsernameLabel"
+ <paper-input id="usernameInput" label="$i18n{editPasswordUsernameLabel}"
value="[[item.loginPair.username]]">
</paper-input>
<div id="passwordGroup">
<paper-input id="passwordInput"
- i18n-values="label:editPasswordPasswordLabel"
+ label="$i18n{editPasswordPasswordLabel}"
type="[[getPasswordInputType_(password)]]"
value="[[getPassword_(item, password)]]">
</paper-input>
- <paper-icon-button id="showPasswordButton" icon="icons:visibility"
- on-tap="onShowPasswordButtonTap_"></paper-icon-button>
+ <paper-icon-button id="showPasswordButton"
+ icon="settings:visibility" on-tap="onShowPasswordButtonTap_">
+ </paper-icon-button>
</div>
</div>
<div class="button-container">
- <paper-button id="cancelButton" i18n-content="cancel"
- on-tap="onCancelButtonTap_"></paper-button>
- <paper-button id="saveButton" class="action-button" i18n-content="save"
- on-tap="onSaveButtonTap_"></paper-button>
+ <paper-button id="cancelButton"
+ on-tap="onCancelButtonTap_">$i18n{cancel}</paper-button>
+ <paper-button id="saveButton" class="action-button"
+ on-tap="onSaveButtonTap_">$i18n{save}</paper-button>
</div>
</settings-dialog>
</template>
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 a949532cf0e..68b70b3836d 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
@@ -1,9 +1,9 @@
<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/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-toggle-button/paper-toggle-button.html">
+<link rel="import" href="chrome://md-settings/passwords_and_forms_page/autofill_section.html">
<link rel="import" href="chrome://md-settings/passwords_and_forms_page/passwords_section.html">
<link rel="import" href="chrome://md-settings/prefs/prefs_behavior.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
@@ -16,27 +16,33 @@
<settings-animated-pages id="pages" current-route="{{currentRoute}}"
section="passwordsAndForms">
<neon-animatable id="main">
- <div class="settings-box first two-line">
+ <div class="settings-box first two-line" on-tap="onAutofillTap_">
<div class="start">
- <div>[[i18n('autofill')]]</div>
- <div class="secondary">[[i18n('autofillDetail')]]</div>
+ <div>$i18n{autofill}</div>
+ <div class="secondary">$i18n{autofillDetail}</div>
</div>
- <paper-toggle-button
+ <paper-toggle-button id="autofillToggle"
checked="{{prefs.autofill.enabled.value}}">
</paper-toggle-button>
</div>
<div class="settings-box two-line" on-tap="onPasswordsTap_">
<div class="start">
- <div>[[i18n('passwords')]]</div>
- <div class="secondary">[[i18n('passwordsDetail')]]</div>
+ <div>$i18n{passwords}</div>
+ <div class="secondary">$i18n{passwordsDetail}</div>
</div>
<paper-toggle-button id="passwordToggle"
checked="{{prefs.profile.password_manager_enabled.value}}">
</paper-toggle-button>
</div>
</neon-animatable>
+ <template is="dom-if" name="manage-autofill">
+ <settings-subpage page-title="$i18n{autofill}">
+ <settings-autofill-section id="autofillSection">
+ </settings-autofill-section>
+ </settings-subpage>
+ </template>
<template is="dom-if" name="manage-passwords">
- <settings-subpage page-title="[[i18n('passwords')]]">
+ <settings-subpage page-title="$i18n{passwords}">
<passwords-section saved-passwords="[[savedPasswords]]"
id="passwordSection" password-exceptions="[[passwordExceptions]]">
</passwords-section>
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 17cb463942f..f0c52b28b69 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
@@ -19,16 +19,18 @@ PasswordManager.PasswordUiEntry;
/** @typedef {chrome.passwordsPrivate.LoginPair} */
PasswordManager.LoginPair;
+/** @typedef {chrome.passwordsPrivate.ExceptionPair} */
+PasswordManager.ExceptionPair;
+
/** @typedef {chrome.passwordsPrivate.PlaintextPasswordEventParameters} */
PasswordManager.PlaintextPasswordEvent;
PasswordManager.prototype = {
/**
- * Register a callback for when the list of passwords is updated.
- * Calling this function should trigger an update.
+ * Request the list of saved passwords and observe future changes.
* @param {function(!Array<!PasswordManager.PasswordUiEntry>):void} callback
*/
- onSavedPasswordListChangedCallback: assertNotReached,
+ setSavedPasswordListChangedCallback: assertNotReached,
/**
* Should remove the saved password and notify that the list has changed.
@@ -38,11 +40,10 @@ PasswordManager.prototype = {
removeSavedPassword: assertNotReached,
/**
- * Register a callback for when the list of exceptions is updated.
- * Calling this function should trigger an update.
- * @param {function(!Array<!string>):void} callback
+ * Request the list of password exceptions and observe future changes.
+ * @param {function(!Array<!PasswordManager.ExceptionPair>):void} callback
*/
- onExceptionListChangedCallback: assertNotReached,
+ setExceptionListChangedCallback: assertNotReached,
/**
* Should remove the password exception and notify that the list has changed.
@@ -77,7 +78,10 @@ PasswordManagerImpl.prototype = {
__proto__: PasswordManager,
/** @override */
- onSavedPasswordListChangedCallback: function(callback) {
+ setSavedPasswordListChangedCallback: function(callback) {
+ // Get the list of passwords...
+ chrome.passwordsPrivate.getSavedPasswordList(callback);
+ // ...and listen for future changes.
chrome.passwordsPrivate.onSavedPasswordsListChanged.addListener(callback);
},
@@ -87,7 +91,10 @@ PasswordManagerImpl.prototype = {
},
/** @override */
- onExceptionListChangedCallback: function(callback) {
+ setExceptionListChangedCallback: function(callback) {
+ // Get the list of exceptions...
+ chrome.passwordsPrivate.getPasswordExceptionList(callback);
+ // ...and listen for future changes.
chrome.passwordsPrivate.onPasswordExceptionsListChanged.addListener(
callback);
},
@@ -115,7 +122,6 @@ Polymer({
is: 'settings-passwords-and-forms-page',
behaviors: [
- I18nBehavior,
PrefsBehavior,
],
@@ -143,7 +149,7 @@ Polymer({
/**
* An array of sites to display.
- * @type {!Array<!string>}
+ * @type {!Array<!PasswordManager.ExceptionPair>}
*/
passwordExceptions: {
type: Array,
@@ -161,10 +167,10 @@ Polymer({
ready: function() {
this.passwordManager_ = PasswordManagerImpl.getInstance();
- this.passwordManager_.onSavedPasswordListChangedCallback(function(list) {
+ this.passwordManager_.setSavedPasswordListChangedCallback(function(list) {
this.savedPasswords = list;
}.bind(this));
- this.passwordManager_.onExceptionListChangedCallback(function(list) {
+ this.passwordManager_.setExceptionListChangedCallback(function(list) {
this.passwordExceptions = list;
}.bind(this));
this.passwordManager_.onPlaintextPasswordRequestedCallback(function(e) {
@@ -191,6 +197,19 @@ Polymer({
},
/**
+ * Shows the manage autofill sub page.
+ * @param {!Event} event
+ * @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) {
+ this.$.pages.setSubpageChain(['manage-autofill']);
+ }
+ },
+
+ /**
* Shows the manage passwords sub page.
* @param {!Event} event
* @private
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 2626e429c14..2bd4e32df8f 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
@@ -1,29 +1,20 @@
+<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/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="chrome://resources/cr_elements/cr_shared_menu/cr_shared_menu.html">
<link rel="import" href="chrome://md-settings/passwords_and_forms_page/password_edit_dialog.html">
+<link rel="import" href="chrome://md-settings/passwords_and_forms_page/passwords_shared_css.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="passwords-section">
<template>
- <style include="settings-shared"></style>
- <style>
- :host {
- display: flex;
- flex-direction: column;
- }
-
+ <style include="settings-shared passwords-shared">
#manageLink {
- -webkit-margin-start: 20px;
margin-bottom: 24px;
}
- .heading {
- -webkit-margin-start: 20px;
- margin-bottom: 8px;
- }
-
#password {
background-color: transparent;
border: none;
@@ -32,17 +23,6 @@
width: 0;
}
- #saved-password-columns {
- -webkit-margin-end: 20px;
- -webkit-margin-start: 56px;
- color: var(--google-grey-500);
- font-weight: 500;
- }
-
- #passwordList > div:first-of-type {
- border-top: 1px solid #e0e0e0;
- }
-
.website-column {
flex: 3;
}
@@ -59,81 +39,86 @@
flex: 2;
}
+ .selectable {
+ -webkit-user-select: text;
+ }
+
/* TODO(hcarmona): Grow menu width by 64px if content is wider */
.menu-item {
-webkit-padding-start: 24px;
width: 104px;
}
- paper-icon-button {
- -webkit-margin-end: 0;
- -webkit-margin-start: 20px;
- -webkit-padding-end: 0;
- -webkit-padding-start: 0;
- color: var(--google-grey-600);
- width: 20px;
+ .list-link {
+ color: black;
+ text-decoration: none;
}
- iron-list {
- -webkit-margin-end: 20px;
- -webkit-margin-start: 56px;
- margin-bottom: 16px;
+ .list-link:hover {
+ text-decoration: underline;
}
</style>
- <!-- TODO(hcarmona): i18n this string and link -->
- <div id="manageLink">Access your passwords from any device at
- <a target="_blank"
- href="https://passwords.google.com">passwords.google.com</a></div>
- <div class="heading" i18n-content="savedPasswordsHeading"></div>
- <div id="saved-password-columns" class="list-item">
- <div class="website-column" i18n-content="editPasswordWebsiteLabel"></div>
- <div class="username-column"
- i18n-content="editPasswordUsernameLabel"></div>
- <div class="password-column"
- i18n-content="editPasswordPasswordLabel"></div>
- </div>
- <iron-list id="passwordList" class="vertical-list list-section"
- items="[[savedPasswords]]">
- <template>
- <div class="list-item">
- <div id="originUrl"
- class="website-column">[[item.loginPair.originUrl]]</div>
- <div id="username"
- class="username-column">[[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="more-vert"
- on-tap="onPasswordMenuTap_" i18n-values="alt:passwordMenu"
- tabindex$="[[tabIndex]]">
- </paper-icon-button>
- </div>
+ <div id="manageLink">$i18nRaw{managePasswordsLabel}</div>
+ <div class="heading">$i18n{savedPasswordsHeading}</div>
+ <div class="item-list">
+ <div class="list-item column-header">
+ <div class="website-column">$i18n{editPasswordWebsiteLabel}</div>
+ <div class="username-column">
+ $i18n{editPasswordUsernameLabel}
</div>
- </template>
- </iron-list>
+ <div class="password-column">
+ $i18n{editPasswordPasswordLabel}
+ </div>
+ </div>
+ <iron-list id="passwordList" items="[[savedPasswords]]"
+ class="vertical-list list-section list-with-header">
+ <template>
+ <div class="list-item">
+ <div class="website-column">
+ <a id="originUrl" target="_blank" class="list-link selectable"
+ href="[[item.linkUrl]]">[[item.loginPair.originUrl]]</a>
+ </div>
+ <div class="username-column selectable"
+ 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"
+ on-tap="onPasswordMenuTap_" alt="$i18n{passwordMenu}"
+ tabindex$="[[tabIndex]]">
+ </paper-icon-button>
+ </div>
+ </div>
+ </template>
+ </iron-list>
+ </div>
<cr-shared-menu id="menu">
<div id="menuEditPassword" class="list-item menu-item"
- i18n-content="editPassword" on-tap="onMenuEditPasswordTap_"
- hidden="[[!showPasswords]]"></div>
+ on-tap="onMenuEditPasswordTap_"
+ hidden="[[!showPasswords]]">$i18n{editPassword}</div>
<div id="menuRemovePassword" class="list-item menu-item"
- i18n-content="removePassword" on-tap="onMenuRemovePasswordTap_">
- </div>
+ on-tap="onMenuRemovePasswordTap_">$i18n{removePassword}</div>
</cr-shared-menu>
<password-edit-dialog id="passwordEditDialog"></password-edit-dialog>
- <div class="heading" i18n-content="passwordExceptionsHeading"></div>
- <iron-list id="passwordExceptionsList" class="vertical-list list-section"
- items="[[passwordExceptions]]">
+ <div class="heading">$i18n{passwordExceptionsHeading}</div>
+ <iron-list id="passwordExceptionsList" items="[[passwordExceptions]]"
+ class="vertical-list list-section item-list">
<template>
<div class="list-item two-line">
- <div id="exception" class="start">[[item]]</div>
- <paper-icon-button id="removeExceptionButton" icon="close"
- on-tap="onRemoveExceptionButtonTap_" tabindex$="[[tabIndex]]"
- i18n-values="alt:deletePasswordException"></paper-icon-button>
+ <a id="exception" href="[[item.linkUrl]]" target="_blank"
+ class="start list-link">[[item.exceptionUrl]]</a>
+ <paper-icon-button id="removeExceptionButton"
+ icon="cr:close" on-tap="onRemoveExceptionButtonTap_"
+ tabindex$="[[tabIndex]]"
+ alt="$i18n{deletePasswordException}">
+ </paper-icon-button>
</div>
</template>
</iron-list>
</template>
+ <!-- action_link.css is needed for the |managePasswordsLabel| link -->
+ <link rel="import" type="css" href="chrome://resources/css/action_link.css">
<script src="chrome://md-settings/passwords_and_forms_page/passwords_section.js"></script>
</dom-module>
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 ea16cf493dc..447315621d0 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
@@ -11,6 +11,9 @@
/** @typedef {!{model: !{item: !chrome.passwordsPrivate.PasswordUiEntry}}} */
var PasswordUiEntryEvent;
+/** @typedef {!{model: !{item: !chrome.passwordsPrivate.ExceptionPair}}} */
+var ExceptionPairEntryEvent;
+
(function() {
'use strict';
@@ -37,7 +40,7 @@ Polymer({
/**
* An array of sites to display.
- * @type {!Array<!string>}
+ * @type {!Array<!chrome.passwordsPrivate.ExceptionPair>}
*/
passwordExceptions: {
type: Array,
@@ -91,11 +94,11 @@ Polymer({
/**
* Fires an event that should delete the password exception.
- * @param {!{model: !{item: !string}}} e The polymer event.
+ * @param {!ExceptionPairEntryEvent} e The polymer event.
* @private
*/
onRemoveExceptionButtonTap_: function(e) {
- this.fire('remove-password-exception', e.model.item);
+ this.fire('remove-password-exception', e.model.item.exceptionUrl);
},
/**
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
new file mode 100644
index 00000000000..8f3eef527ee
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
@@ -0,0 +1,40 @@
+<!-- Common styles for Passwords and Forms -->
+<dom-module id="passwords-shared">
+ <template>
+ <style>
+ :host {
+ -webkit-margin-end: 20px;
+ -webkit-margin-start: 20px;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .column-header {
+ color: var(--google-grey-500);
+ font-weight: 500;
+ }
+
+ .heading {
+ margin-bottom: 8px;
+ }
+
+ paper-icon-button {
+ -webkit-margin-end: 0;
+ -webkit-margin-start: 20px;
+ -webkit-padding-end: 0;
+ -webkit-padding-start: 0;
+ color: var(--google-grey-600);
+ width: 20px;
+ }
+
+ .item-list {
+ -webkit-margin-start: 36px;
+ margin-bottom: 16px;
+ }
+
+ .list-with-header > div:first-of-type {
+ border-top: var(--settings-separator-line);
+ }
+ </style>
+ </template>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/people_page/camera.html b/chromium/chrome/browser/resources/settings/people_page/camera.html
index 9d73b384cd6..2f176b04297 100644
--- a/chromium/chrome/browser/resources/settings/people_page/camera.html
+++ b/chromium/chrome/browser/resources/settings/people_page/camera.html
@@ -1,9 +1,8 @@
-<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/util.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/image-icons.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-spinner/paper-spinner.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-camera">
@@ -18,13 +17,13 @@
</div>
</div>
<div id="cameraControls">
- <paper-icon-button id="flipPhoto" tabindex="2" icon="image:flip"
- i18n-values="title:flipPhoto" on-tap="onTapFlipPhoto_"
- disabled="[[!cameraOnline_]]">
+ <paper-icon-button id="flipPhoto" tabindex="2"
+ icon="settings:flip" title="$i18n{flipPhoto}"
+ on-tap="onTapFlipPhoto_" disabled="[[!cameraOnline_]]">
</paper-icon-button>
- <paper-icon-button id="takePhoto" tabindex="1" icon="image:camera-alt"
- i18n-values="title:takePhoto" on-tap="takePhoto"
- disabled="[[!cameraOnline_]]">
+ <paper-icon-button id="takePhoto" tabindex="1"
+ icon="settings:camera-alt" title="$i18n{takePhoto}"
+ on-tap="takePhoto" disabled="[[!cameraOnline_]]">
</paper-icon-button>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/settings/people_page/camera.js b/chromium/chrome/browser/resources/settings/people_page/camera.js
index 91a8f7d03ae..e31a25d1711 100644
--- a/chromium/chrome/browser/resources/settings/people_page/camera.js
+++ b/chromium/chrome/browser/resources/settings/people_page/camera.js
@@ -21,10 +21,6 @@ var CAPTURE_SIZE = {
Polymer({
is: 'settings-camera',
- behaviors: [
- I18nBehavior,
- ],
-
properties: {
/**
* True if the user has selected the camera as the user image source.
@@ -33,6 +29,7 @@ Polymer({
cameraActive: {
type: Boolean,
observer: 'cameraActiveChanged_',
+ value: false,
},
/**
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 b16553d17f1..037ef85de5f 100644
--- a/chromium/chrome/browser/resources/settings/people_page/change_picture.html
+++ b/chromium/chrome/browser/resources/settings/people_page/change_picture.html
@@ -3,10 +3,10 @@
<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-a11y-keys/iron-a11y-keys.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/image-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/iron-selector/iron-selector.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/people_page/camera.html">
<link rel="import" href="chrome://md-settings/people_page/change_picture_browser_proxy.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
@@ -22,24 +22,28 @@
<div id="availableIcons" class="start">
<iron-selector id="selector" on-iron-activate="onImageActivate_"
selected-item="{{selectedItem_}}">
- <iron-icon id="cameraImage" data-type="camera" icon="image:camera-alt"
- i18n-values="alt:takePhoto" hidden="[[!cameraPresent_]]">
+ <iron-icon id="cameraImage"
+ data-type$="[[selectionTypesEnum_.CAMERA]]"
+ icon="settings:camera-alt" alt="$i18n{takePhoto}"
+ hidden="[[!cameraPresent_]]">
</iron-icon>
- <iron-icon data-type="file" icon="folder"
- i18n-values="alt:chooseFile">
+ <iron-icon data-type$="[[selectionTypesEnum_.FILE]]"
+ icon="settings:folder" alt="$i18n{chooseFile}">
</iron-icon>
- <img id="profileImage" data-type="profile"
- src="[[profileImageUrl_]]" i18n-values="alt:profilePhotoLoading">
- <img id="oldImage" data-type="old"
+ <img id="profileImage"
+ data-type$="[[selectionTypesEnum_.PROFILE]]"
+ src="[[profileImageUrl_]]" alt="$i18n{profilePhotoLoading}">
+ <img id="oldImage" data-type$="[[selectionTypesEnum_.OLD]]"
src="[[oldImageUrl_]]" hidden="[[!oldImageUrl_]]">
<template is="dom-repeat" items="[[defaultImages_]]">
- <img data-type="default" data-default-image-index$="[[index]]"
- src="[[item.url]]" alt="[[item.title]]">
+ <img data-type$="[[selectionTypesEnum_.DEFAULT]]"
+ data-default-image-index$="[[index]]" src="[[item.url]]"
+ alt="[[item.title]]">
</template>
</iron-selector>
<template is="dom-if" if="[[isAuthorCreditShown_(selectedItem_)]]">
<div id="authorCredit">
- [[i18n('authorCredit')]]
+ $i18n{authorCredit}
[[getAuthorName_(selectedItem_, defaultImages_)]]
<a href="[[getAuthorWebsite_(selectedItem_, defaultImages_)]]"
target="_blank">
@@ -49,11 +53,13 @@
</template>
</div>
<div id="previewPane">
- <img i18n-values="alt:previewAltText" src="[[selectedItem_.src]]"
+ <img alt="$i18n{previewAltText}" src="[[selectedItem_.src]]"
hidden="[[isPreviewImageHidden_(selectedItem_)]]">
- <div id="discardControlBar" hidden="[[isDiscardHidden_(selectedItem_)]]">
- <paper-icon-button id="discardOldImage" tabindex="0" icon="delete"
- i18n-values="title:discardPhoto" on-tap="onTapDiscardOldImage_">
+ <div id="discardControlBar"
+ hidden="[[isDiscardHidden_(selectedItem_)]]">
+ <paper-icon-button id="discardOldImage" tabindex="0"
+ icon="settings:delete" title="$i18n{discardPhoto}"
+ on-tap="onTapDiscardOldImage_">
</paper-icon-button>
</div>
<settings-camera id="camera"
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 57d0e24f8b5..3beff43583e 100644
--- a/chromium/chrome/browser/resources/settings/people_page/change_picture.js
+++ b/chromium/chrome/browser/resources/settings/people_page/change_picture.js
@@ -2,22 +2,29 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-cr.exportPath('settings_test');
-
-/** @type {boolean} */
-settings_test.changePictureNotifyForTest;
+/**
+ * Contains the possible types of Change Picture selections.
+ * @enum {string}
+ */
+var ChangePictureSelectionTypes = {
+ CAMERA: 'camera',
+ FILE: 'file',
+ PROFILE: 'profile',
+ OLD: 'old',
+ DEFAULT: 'default',
+};
/**
* An image element.
* @typedef {{
* dataset: {
- * type: string,
+ * type: !ChangePictureSelectionTypes,
* defaultImageIndex: ?number,
* },
* src: string,
* }}
*/
-settings.ChangePictureImageElement;
+var ChangePictureImageElement;
/**
* @fileoverview
@@ -44,16 +51,14 @@ Polymer({
/**
* The currently selected item. This property is bound to the iron-selector
- * and never directly assigned.
- * @private {settings.ChangePictureImageElement}
+ * and never directly assigned. This may be undefined momentarily as
+ * the selection changes due to iron-selector implementation details.
+ * @private {?ChangePictureImageElement}
*/
- selectedItem_: {
- type: settings.ChangePictureImageElement,
- notify: !!settings_test.changePictureNotifyForTest,
- },
+ selectedItem_: Object,
/**
- * The url of the 'old' image, which is the existing image sourced from
+ * The url of the Old image, which is the existing image sourced from
* the camera, a file, or a deprecated default image. It defaults to an
* empty string instead of undefined, because Polymer bindings don't behave
* as expected with undefined properties.
@@ -83,14 +88,11 @@ Polymer({
},
/**
- * The fallback image to be selected when the user discards the 'old' image.
- * This may be null if the user started with the 'old' image.
- * @private {?settings.ChangePictureImageElement}
+ * The fallback image to be selected when the user discards the Old image.
+ * This may be null if the user started with the Old image.
+ * @private {?ChangePictureImageElement}
*/
- fallbackImage_: {
- type: settings.ChangePictureImageElement,
- value: null,
- },
+ fallbackImage_: Object,
/**
* Type of the last selected icon. This is used to jump back to the camera
@@ -102,6 +104,13 @@ Polymer({
value: '',
},
+ /** @private */
+ selectionTypesEnum_: {
+ type: Object,
+ value: ChangePictureSelectionTypes,
+ readOnly: true,
+ },
+
/** @private {!settings.ChangePictureBrowserProxyImpl} */
browserProxy_: {
type: Object,
@@ -144,21 +153,24 @@ Polymer({
*/
receiveSelectedImage_: function(imageUrl) {
var index = this.$.selector.items.findIndex(function(image) {
- return image.dataset.type == 'default' && image.src == imageUrl;
+ return image.dataset.type == ChangePictureSelectionTypes.DEFAULT &&
+ image.src == imageUrl;
});
assert(index != -1, 'Default image not found: ' + imageUrl);
this.fallbackImage_ = this.$.selector.items[index];
// If user is currently taking a photo, do not steal the focus.
- if (!this.selectedItem_ || this.selectedItem_.dataset.type != 'camera')
+ if (!this.selectedItem_ ||
+ this.selectedItem_.dataset.type != ChangePictureSelectionTypes.CAMERA) {
this.$.selector.select(index);
+ }
},
/**
- * Handler for the 'old-image-changed' event. The 'old' image is any selected
+ * Handler for the 'old-image-changed' event. The Old image is any selected
* non-profile and non-default image. It can be from the camera, a file, or a
- * deprecated default image. When this method is called, the old image
+ * deprecated default image. When this method is called, the Old image
* becomes the selected image.
* @param {string} imageUrl
* @private
@@ -184,8 +196,10 @@ Polymer({
this.fallbackImage_ = this.$.profileImage;
// If user is currently taking a photo, do not steal the focus.
- if (!this.selectedItem_ || this.selectedItem_.dataset.type != 'camera')
+ if (!this.selectedItem_ ||
+ this.selectedItem_.dataset.type != ChangePictureSelectionTypes.CAMERA) {
this.$.selector.select(this.$.selector.indexOf(this.$.profileImage));
+ }
},
/**
@@ -199,24 +213,24 @@ Polymer({
/**
* Selects an image element.
- * @param {!settings.ChangePictureImageElement} image
+ * @param {!ChangePictureImageElement} image
* @private
*/
selectImage_: function(image) {
switch (image.dataset.type) {
- case 'camera':
+ case ChangePictureSelectionTypes.CAMERA:
// Nothing needs to be done.
break;
- case 'file':
+ case ChangePictureSelectionTypes.FILE:
this.browserProxy_.chooseFile();
break;
- case 'profile':
+ case ChangePictureSelectionTypes.PROFILE:
this.browserProxy_.selectProfileImage();
break;
- case 'old':
+ case ChangePictureSelectionTypes.OLD:
this.browserProxy_.selectOldImage();
break;
- case 'default':
+ case ChangePictureSelectionTypes.DEFAULT:
this.browserProxy_.selectDefaultImage(image.src);
break;
default:
@@ -269,12 +283,15 @@ Polymer({
case 'enter':
case 'space':
- if (this.selectedItem_.dataset.type == 'camera') {
+ if (this.selectedItem_.dataset.type ==
+ ChangePictureSelectionTypes.CAMERA) {
var /** SettingsCameraElement */ camera = this.$.camera;
camera.takePhoto();
- } else if (this.selectedItem_.dataset.type == 'file') {
+ } else if (this.selectedItem_.dataset.type ==
+ ChangePictureSelectionTypes.FILE) {
this.browserProxy_.chooseFile();
- } else if (this.selectedItem_.dataset.type == 'old') {
+ } else if (this.selectedItem_.dataset.type ==
+ ChangePictureSelectionTypes.OLD) {
this.onTapDiscardOldImage_();
}
break;
@@ -302,14 +319,14 @@ Polymer({
},
/**
- * Discard currently selected old image. Selects the first default icon.
+ * Discard currently selected Old image. Selects the first default icon.
* Returns to the camera stream if the user had just taken a picture.
* @private
*/
onTapDiscardOldImage_: function() {
this.oldImageUrl_ = '';
- if (this.lastSelectedImageType_ == 'camera')
+ if (this.lastSelectedImageType_ == ChangePictureSelectionTypes.CAMERA)
this.$.selector.select(this.$.selector.indexOf(this.$.cameraImage));
if (this.fallbackImage_ != null) {
@@ -322,20 +339,19 @@ Polymer({
assert(this.defaultImages_.length > 0);
this.browserProxy_.selectDefaultImage(this.defaultImages_[0].url);
- announceAccessibleMessage(
- loadTimeData.getString('photoDiscardAccessibleText'));
+ announceAccessibleMessage(this.i18n('photoDiscardAccessibleText'));
},
/**
* @param {string} oldImageUrl
- * @return {boolean} True if there is no old image and the old image icon
+ * @return {boolean} True if there is no Old image and the Old image icon
* should be hidden.
* @private
*/
isOldImageHidden_: function(oldImageUrl) { return oldImageUrl.length == 0; },
/**
- * @param {settings.ChangePictureImageElement} selectedItem
+ * @param {ChangePictureImageElement} selectedItem
* @return {boolean} True if the preview image should be hidden.
* @private
*/
@@ -344,39 +360,44 @@ Polymer({
return true;
var type = selectedItem.dataset.type;
- return type != 'default' && type != 'profile' && type != 'old';
+ return type != ChangePictureSelectionTypes.DEFAULT &&
+ type != ChangePictureSelectionTypes.PROFILE &&
+ type != ChangePictureSelectionTypes.OLD;
},
/**
- * @param {settings.ChangePictureImageElement} selectedItem
+ * @param {boolean} cameraPresent
+ * @param {ChangePictureImageElement} selectedItem
* @return {boolean} True if the camera is selected in the image grid.
* @private
*/
isCameraActive_: function(cameraPresent, selectedItem) {
return cameraPresent && selectedItem &&
- selectedItem.dataset.type == 'camera';
+ selectedItem.dataset.type == ChangePictureSelectionTypes.CAMERA;
},
/**
- * @param {settings.ChangePictureImageElement} selectedItem
+ * @param {ChangePictureImageElement} selectedItem
* @return {boolean} True if the discard controls should be hidden.
* @private
*/
isDiscardHidden_: function(selectedItem) {
- return !selectedItem || selectedItem.dataset.type != 'old';
+ return !selectedItem ||
+ selectedItem.dataset.type != ChangePictureSelectionTypes.OLD;
},
/**
- * @param {settings.ChangePictureImageElement} selectedItem
+ * @param {ChangePictureImageElement} selectedItem
* @return {boolean} True if the author credit text is shown.
* @private
*/
isAuthorCreditShown_: function(selectedItem) {
- return selectedItem && selectedItem.dataset.type == 'default';
+ return selectedItem &&
+ selectedItem.dataset.type == ChangePictureSelectionTypes.DEFAULT;
},
/**
- * @param {!settings.ChangePictureImageElement} selectedItem
+ * @param {!ChangePictureImageElement} selectedItem
* @param {!Array<!settings.DefaultImage>} defaultImages
* @return {string} The author name for the selected default image. An empty
* string is returned if there is no valid author name.
@@ -392,7 +413,7 @@ Polymer({
},
/**
- * @param {!settings.ChangePictureImageElement} selectedItem
+ * @param {!ChangePictureImageElement} selectedItem
* @param {!Array<!settings.DefaultImage>} defaultImages
* @return {string} The author website for the selected default image. An
* empty string is returned if there is no valid author name.
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 2d63ef94272..4bdc528fa18 100644
--- a/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -8,7 +8,6 @@
'dependencies': [
'<(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/compiled_resources2.gyp:i18n_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -42,8 +41,8 @@
{
'target_name': 'easy_unlock_turn_off_dialog',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(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',
'easy_unlock_browser_proxy',
],
@@ -70,12 +69,19 @@
'dependencies': [
'<(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:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
'easy_unlock_browser_proxy',
'easy_unlock_turn_off_dialog',
- 'sync_private_api',
+ 'profile_info_browser_proxy',
+ 'sync_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'profile_info_browser_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -83,18 +89,20 @@
'target_name': 'sync_page',
'dependencies': [
'<(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: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',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
- 'sync_private_api',
+ 'sync_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'sync_private_api',
+ 'target_name': 'sync_browser_proxy',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/third_party/closure_compiler/externs/compiled_resources2.gyp:metrics_private',
'<(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/people_page/easy_unlock_turn_off_dialog.html b/chromium/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.html
index 3c3df6e57fb..eb202b305aa 100644
--- a/chromium/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.html
+++ b/chromium/chrome/browser/resources/settings/people_page/easy_unlock_turn_off_dialog.html
@@ -1,3 +1,4 @@
+<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/paper-button/paper-button.html">
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 9ca6f77c773..a4e832fde50 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.html
@@ -1,4 +1,3 @@
-<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/neon-animation/neon-animatable.html">
@@ -7,13 +6,15 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-dialog/paper-dialog.html">
<link rel="import" href="chrome://md-settings/controls/settings_checkbox.html">
<link rel="import" href="chrome://md-settings/people_page/sync_page.html">
-<link rel="import" href="chrome://md-settings/people_page/sync_private_api.html">
+<link rel="import" href="chrome://md-settings/people_page/profile_info_browser_proxy.html">
+<link rel="import" href="chrome://md-settings/people_page/sync_browser_proxy.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
<link rel="import" href="chrome://md-settings/settings_page/settings_subpage.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<if expr="chromeos">
<link rel="import" href="chrome://md-settings/people_page/change_picture.html">
+<link rel="import" href="chrome://md-settings/people_page/pin_keyboard.html">
<link rel="import" href="chrome://md-settings/people_page/easy_unlock_browser_proxy.html">
<link rel="import" href="chrome://md-settings/people_page/easy_unlock_turn_off_dialog.html">
<link rel="import" href="chrome://md-settings/people_page/users_page.html">
@@ -25,8 +26,12 @@
<dom-module id="settings-people-page">
<template>
<style include="settings-shared">
- #account-picture {
- -webkit-margin-end: 4px;
+ setting-box.middle {
+ /* Per spec, middle text is indented 20px in this section. */
+ -webkit-margin-start: 20px;
+ }
+
+ #profile-icon {
border-radius: 20px;
height: 40px;
object-fit: cover;
@@ -34,7 +39,8 @@
width: 40px;
}
- #account-picture:hover {
+ #profile-icon:hover,
+ #activity-controls:hover {
cursor: pointer;
}
@@ -43,12 +49,37 @@
cursor: pointer;
}
</if>
+
+ #sync-icon {
+ margin: 0 10px;
+ }
+
+ iron-icon[icon="settings:sync-problem"] {
+ --iron-icon-fill-color: var(--settings-error-color);
+ }
+
+ .settings-box .sync-error {
+ color: var(--settings-error-color);
+ }
+
+ #googleg-logo-container {
+ display: flex;
+ justify-content: center;
+ width: 40px;
+ }
+
+ #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);
+ }
</style>
<settings-animated-pages id="pages" current-route="{{currentRoute}}"
section="people">
<neon-animatable id="main">
<div class="settings-box first two-line">
- <img id="account-picture" src="[[profileIconUrl_]]"
+ <img id="profile-icon" src="[[profileIconUrl_]]"
on-tap="onPictureTap_">
<div class="middle">
<if expr="chromeos">
@@ -66,82 +97,105 @@
<template is="dom-if" if="[[!syncStatus.signedIn]]">
<paper-button class="action-button" on-tap="onSigninTap_"
disabled="[[syncStatus.setupInProgress]]">
- [[i18n('syncSignin')]]
+ $i18n{syncSignin}
</paper-button>
</template>
<template is="dom-if" if="[[syncStatus.signedIn]]">
<span class="secondary-action">
<paper-button class="secondary-button" on-tap="onDisconnectTap_"
disabled="[[syncStatus.setupInProgress]]">
- [[i18n('syncDisconnect')]]
+ $i18n{syncDisconnect}
</paper-button>
</span>
</template>
</if>
</div>
<div class="settings-box two-line" hidden="[[syncStatus.signedIn]]">
- [[i18n('syncOverview')]]
- </div>
-
- <div class="settings-box" hidden="[[!isStatusTextSet_(syncStatus)]]">
- <span id="syncStatusText"></span>
- <paper-button on-tap="onActionLinkTap_">
- [[syncStatus.actionLinkText]]
- </paper-button>
+ $i18n{syncOverview}
</div>
<template is="dom-if"
if="[[isAdvancedSyncSettingsVisible_(syncStatus)]]">
- <div class="settings-box">
- <paper-button on-tap="onSyncTap_" class="primary-button">
- [[i18n('syncPageTitle')]]
- </paper-button>
+ <div class="settings-box two-line" on-tap="onSyncTap_">
+ <iron-icon id="sync-icon" icon$="[[getSyncIcon_(syncStatus)]]">
+ </iron-icon>
+ <div class="middle">
+ <div>$i18n{sync}</div>
+ <div class="secondary" hidden="[[syncStatus.hasError]]">
+ [[syncStatus.statusText]]
+ </div>
+ <div class="secondary sync-error"
+ hidden="[[!syncStatus.hasError]]">
+ [[syncStatus.statusText]]
+ </div>
+ </div>
</div>
</template>
+ <div class="settings-box" id="activity-controls"
+ on-tap="onActivityControlsTap_">
+ <div id="googleg-logo-container">
+ <div id="googleg-logo"></div>
+ </div>
+ <div class="middle">
+ <div>$i18n{personalizeGoogleServicesTitle}</div>
+ <div class="secondary">$i18n{personalizeGoogleServicesText}</div>
+ </div>
+ </div>
+
<if expr="chromeos">
+ <!-- TODO(jdufault): Confirm if this goes above or below easy unlock
+ settings. -->
+ <template is="dom-if" if=[[pinUnlockAllowed_]]>
+ <div class="settings-box">
+ <!-- TODO(jdufault): i18n -->
+ <p>Quick Unlock PIN</p>
+ <pin-keyboard></pin-keyboard>
+ </div>
+ </template>
+
<div class="settings-box">
<settings-checkbox pref="{{prefs.settings.enable_screen_lock}}"
- i18n-values="label:enableScreenlock">
+ label="$i18n{enableScreenlock}">
</settings-checkbox>
</div>
- <template is="dom-if" if=[[easyUnlockAllowed_]]>
+ <template is="dom-if" if="[[easyUnlockAllowed_]]">
<div class="settings-box">
<div class="middle">
- <div>[[i18n('easyUnlockSectionTitle')]]</div>
+ <div>$i18n{easyUnlockSectionTitle}</div>
<div class="secondary">
- <template is="dom-if" if=[[!easyUnlockEnabled_]]>
- [[i18n('easyUnlockSetupIntro')]]
+ <template is="dom-if" if="[[!easyUnlockEnabled_]]">
+ $i18n{easyUnlockSetupIntro}
</template>
- <template is="dom-if" if=[[easyUnlockEnabled_]]>
- [[i18n('easyUnlockDescription')]]
+ <template is="dom-if" if="[[easyUnlockEnabled_]]">
+ $i18n{easyUnlockDescription}
</template>
- <a target="_blank" href$="[[i18n('easyUnlockLearnMoreURL')]]">
- [[i18n('learnMore')]]
+ <a target="_blank" href$="$i18n{easyUnlockLearnMoreURL}">
+ $i18n{learnMore}
</a>
- <template is="dom-if" if=[[easyUnlockEnabled_]]>
+ <template is="dom-if" if="[[easyUnlockEnabled_]]">
<template is="dom-if"
- if=[[easyUnlockProximityDetectionAllowed_]]>
+ if="[[easyUnlockProximityDetectionAllowed_]]">
<settings-checkbox
pref="{{prefs.easy_unlock.proximity_required}}"
- i18n-values="label:easyUnlockRequireProximityLabel">
+ label="$i18n{easyUnlockRequireProximityLabel}">
</settings-checkbox>
</template>
</template>
</div>
</div>
<div class="secondary-action">
- <template is="dom-if" if=[[!easyUnlockEnabled_]]>
+ <template is="dom-if" if="[[!easyUnlockEnabled_]]">
<paper-button id="easyUnlockSetup" class="secondary-button"
on-tap="onEasyUnlockSetupTap_">
- [[i18n('easyUnlockSetupButton')]]
+ $i18n{easyUnlockSetupButton}
</paper-button>
</template>
- <template is="dom-if" if=[[easyUnlockEnabled_]]>
+ <template is="dom-if" if="[[easyUnlockEnabled_]]">
<paper-button id="easyUnlockTurnOff" class="secondary-button"
on-tap="onEasyUnlockTurnOffTap_">
- [[i18n('easyUnlockTurnOffButton')]]
+ $i18n{easyUnlockTurnOffButton}
</paper-button>
</template>
</div>
@@ -150,32 +204,32 @@
</if>
<div class="settings-box">
- <paper-button class="primary-button" i18n-content="manageOtherPeople"
- on-tap="onManageOtherPeople_">
+ <paper-button class="primary-button" on-tap="onManageOtherPeople_">
+ $i18n{manageOtherPeople}
</paper-button>
</div>
</neon-animatable>
<template is="dom-if" name="sync">
- <settings-subpage page-title="[[i18n('syncPageTitle')]]">
+ <settings-subpage page-title="$i18n{syncPageTitle}">
<settings-sync-page current-route="[[currentRoute]]">
</settings-sync-page>
</settings-subpage>
</template>
<if expr="chromeos">
<template is="dom-if" name="users">
- <settings-subpage page-title="[[i18n('usersPageTitle')]]">
+ <settings-subpage page-title="$i18n{usersPageTitle}">
<settings-users-page prefs="{{prefs}}"></settings-users-page>
</settings-subpage>
</template>
<template is="dom-if" name="changePicture">
- <settings-subpage page-title="[[i18n('changePictureTitle')]]">
+ <settings-subpage page-title="$i18n{changePictureTitle}">
<settings-change-picture></settings-change-picture>
</settings-subpage>
</template>
</if>
<if expr="not chromeos">
<template is="dom-if" name="manageProfile">
- <settings-subpage page-title="[[i18n('editPerson')]]">
+ <settings-subpage page-title="$i18n{editPerson}">
<settings-manage-profile profile-icon-url="[[profileIconUrl_]]"
profile-name="[[profileName_]]">
</settings-manage-profile>
@@ -185,18 +239,18 @@
</settings-animated-pages>
<paper-dialog modal id="disconnectDialog">
- <h2 i18n-content="syncDisconnectTitle"></h2>
- <div i18n-values=".innerHTML:syncDisconnectExplanation"></div>
+ <h2>$i18n{syncDisconnectTitle}</h2>
+ <div>$i18nRaw{syncDisconnectExplanation}"</div>
<if expr="(not chromeos and is_posix) or is_win or is_macosx">
- <paper-checkbox id="deleteProfile"
- i18n-content="syncDisconnectDeleteProfile">
+ <paper-checkbox id="deleteProfile">
+ $i18n{syncDisconnectDeleteProfile}
</paper-checkbox>
</if>
<div class="button-strip">
- <paper-button dialog-dismiss i18n-content="cancel">
- </paper-button>
+ <paper-button dialog-dismiss>$i18n{cancel}</paper-button>
<paper-button dialog-confirm class="action-button"
- on-tap="onDisconnectConfirm_" i18n-content="syncDisconnectConfirm">
+ on-tap="onDisconnectConfirm_">
+ $i18n{syncDisconnectConfirm}
</paper-button>
</div>
</paper-dialog>
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 88d361689a4..7330a8ccb98 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.js
@@ -5,19 +5,11 @@
/**
* @fileoverview
* 'settings-people-page' is the settings page containing sign-in settings.
- *
- * Example:
- *
- * <iron-animated-pages>
- * <settings-people-page prefs="{{prefs}}"></settings-people-page>
- * ... other pages ...
- * </iron-animated-pages>
*/
Polymer({
is: 'settings-people-page',
behaviors: [
- I18nBehavior,
WebUIListenerBehavior,
],
@@ -39,7 +31,7 @@ Polymer({
},
/**
- * The current sync status, supplied by settings.SyncPrivateApi.
+ * The current sync status, supplied by SyncBrowserProxy.
* @type {?settings.SyncStatus}
*/
syncStatus: Object,
@@ -54,9 +46,29 @@ Polymer({
*/
profileName_: String,
+ /** @private {!settings.SyncBrowserProxyImpl} */
+ syncBrowserProxy_: {
+ type: Object,
+ value: function() {
+ return settings.SyncBrowserProxyImpl.getInstance();
+ },
+ },
+
<if expr="chromeos">
+ /**
+ * True if Pin Unlock is allowed on this machine.
+ */
+ pinUnlockAllowed_: {
+ type: Boolean,
+ value: function() {
+ /* TODO(jdufault): Return a real value via quickUnlockPrivate API. */
+ return false;
+ },
+ readOnly: true,
+ },
+
/** @private {!settings.EasyUnlockBrowserProxyImpl} */
- browserProxy_: {
+ easyUnlockBrowserProxy_: {
type: Object,
value: function() {
return settings.EasyUnlockBrowserProxyImpl.getInstance();
@@ -100,16 +112,22 @@ Polymer({
/** @override */
attached: function() {
- settings.SyncPrivateApi.getProfileInfo(this.handleProfileInfo_.bind(this));
- settings.SyncPrivateApi.getSyncStatus(
- this.handleSyncStatusFetched_.bind(this));
+ settings.ProfileInfoBrowserProxyImpl.getInstance().getProfileInfo().then(
+ this.handleProfileInfo_.bind(this));
+ this.addWebUIListener('profile-info-changed',
+ this.handleProfileInfo_.bind(this));
+
+ this.syncBrowserProxy_.getSyncStatus().then(
+ 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.browserProxy_.getEnabledStatus().then(
+ this.easyUnlockBrowserProxy_.getEnabledStatus().then(
this.handleEasyUnlockEnabledStatusChanged_.bind(this));
}
</if>
@@ -118,24 +136,20 @@ Polymer({
/**
* Handler for when the profile's icon and name is updated.
* @private
- * @param {!string} name
- * @param {!string} iconUrl
+ * @param {!settings.ProfileInfo} info
*/
- handleProfileInfo_: function(name, iconUrl) {
- this.profileName_ = name;
- this.profileIconUrl_ = iconUrl;
+ handleProfileInfo_: function(info) {
+ this.profileName_ = info.name;
+ this.profileIconUrl_ = info.iconUrl;
},
/**
- * Handler for when the sync state is pushed from settings.SyncPrivateApi.
+ * Handler for when the sync state is pushed from the browser.
+ * @param {?settings.SyncStatus} syncStatus
* @private
*/
- handleSyncStatusFetched_: function(syncStatus) {
+ handleSyncStatus_: function(syncStatus) {
this.syncStatus = syncStatus;
-
- // TODO(tommycli): Remove once we figure out how to refactor the sync
- // code to not include HTML in the status messages.
- this.$.syncStatusText.innerHTML = syncStatus.statusText;
},
<if expr="chromeos">
@@ -149,11 +163,6 @@ Polymer({
</if>
/** @private */
- onActionLinkTap_: function() {
- settings.SyncPrivateApi.showSetupUI();
- },
-
- /** @private */
onPictureTap_: function() {
<if expr="chromeos">
this.$.pages.setSubpageChain(['changePicture']);
@@ -171,8 +180,13 @@ Polymer({
</if>
/** @private */
+ onActivityControlsTap_: function() {
+ this.syncBrowserProxy_.openActivityControlsUrl();
+ },
+
+ /** @private */
onSigninTap_: function() {
- settings.SyncPrivateApi.startSignIn();
+ this.syncBrowserProxy_.startSignIn();
},
/** @private */
@@ -183,20 +197,26 @@ Polymer({
/** @private */
onDisconnectConfirm_: function() {
var deleteProfile = this.$.deleteProfile && this.$.deleteProfile.checked;
- settings.SyncPrivateApi.disconnect(deleteProfile);
+ this.syncBrowserProxy_.signOut(deleteProfile);
// Dialog automatically closed because button has dialog-confirm attribute.
},
/** @private */
onSyncTap_: function() {
+ assert(this.syncStatus.signedIn);
+ assert(this.syncStatus.syncSystemEnabled);
+
+ if (this.syncStatus.managed)
+ return;
+
this.$.pages.setSubpageChain(['sync']);
},
<if expr="chromeos">
/** @private */
onEasyUnlockSetupTap_: function() {
- this.browserProxy_.startTurnOnFlow();
+ this.easyUnlockBrowserProxy_.startTurnOnFlow();
},
/** @private */
@@ -208,7 +228,7 @@ Polymer({
/** @private */
onManageOtherPeople_: function() {
<if expr="not chromeos">
- settings.SyncPrivateApi.manageOtherPeople();
+ this.syncBrowserProxy_.manageOtherPeople();
</if>
<if expr="chromeos">
this.$.pages.setSubpageChain(['users']);
@@ -217,18 +237,27 @@ Polymer({
/**
* @private
+ * @param {?settings.SyncStatus} syncStatus
* @return {boolean}
*/
- isStatusTextSet_: function(syncStatus) {
- return syncStatus && syncStatus.statusText.length > 0;
+ isAdvancedSyncSettingsVisible_: function(syncStatus) {
+ return !!syncStatus && !!syncStatus.signedIn &&
+ !!syncStatus.syncSystemEnabled;
},
/**
* @private
- * @return {boolean}
+ * @param {?settings.SyncStatus} syncStatus
+ * @return {string}
*/
- isAdvancedSyncSettingsVisible_: function(syncStatus) {
- return syncStatus && syncStatus.signedIn && !syncStatus.managed &&
- syncStatus.syncSystemEnabled;
+ getSyncIcon_: function(syncStatus) {
+ if (!syncStatus)
+ return '';
+ if (syncStatus.hasError)
+ return 'settings:sync-problem';
+ if (syncStatus.managed)
+ return 'settings:sync-disabled';
+
+ return 'settings:done';
},
});
diff --git a/chromium/chrome/browser/resources/settings/people_page/pin_keyboard.html b/chromium/chrome/browser/resources/settings/people_page/pin_keyboard.html
new file mode 100644
index 00000000000..65056df0516
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/pin_keyboard.html
@@ -0,0 +1 @@
+<include src="../../chromeos/quick_unlock/pin_keyboard.html">
diff --git a/chromium/chrome/browser/resources/settings/people_page/pin_keyboard.js b/chromium/chrome/browser/resources/settings/people_page/pin_keyboard.js
new file mode 100644
index 00000000000..2d63b655879
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/pin_keyboard.js
@@ -0,0 +1,5 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+<include src="../../chromeos/quick_unlock/pin_keyboard.js">
diff --git a/chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.html b/chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.html
new file mode 100644
index 00000000000..4db4d195fe3
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://md-settings/people_page/profile_info_browser_proxy.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.js b/chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.js
new file mode 100644
index 00000000000..fda3cd48744
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.js
@@ -0,0 +1,50 @@
+// 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 A helper object used from the the People section to get the
+ * profile info, which consists of the profile name and icon. Used for both
+ * Chrome browser and ChromeOS.
+ */
+cr.exportPath('settings');
+
+/**
+ * An object describing the profile.
+ * @typedef {{
+ * name: string,
+ * iconUrl: string
+ * }}
+ */
+settings.ProfileInfo;
+
+cr.define('settings', function() {
+ /** @interface */
+ function ProfileInfoBrowserProxy() {}
+
+ ProfileInfoBrowserProxy.prototype = {
+ /**
+ * Returns a Promise for the profile info.
+ * @return {!Promise<!settings.ProfileInfo>}
+ */
+ getProfileInfo: function() {},
+ };
+
+ /**
+ * @constructor
+ * @implements {ProfileInfoBrowserProxy}
+ */
+ function ProfileInfoBrowserProxyImpl() {}
+ cr.addSingletonGetter(ProfileInfoBrowserProxyImpl);
+
+ ProfileInfoBrowserProxyImpl.prototype = {
+ /** @override */
+ getProfileInfo: function() {
+ return cr.sendWithPromise('getProfileInfo');
+ },
+ };
+
+ return {
+ ProfileInfoBrowserProxyImpl: ProfileInfoBrowserProxyImpl,
+ };
+});
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.html b/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.html
new file mode 100644
index 00000000000..c758d1ce6ee
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.html
@@ -0,0 +1,3 @@
+<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://md-settings/people_page/sync_browser_proxy.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js b/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
new file mode 100644
index 00000000000..7be36fa3271
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
@@ -0,0 +1,216 @@
+// 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 A helper object used from the the People section to get the
+ * status of the sync backend and user preferences on what data to sync. Used
+ * for both Chrome browser and ChromeOS.
+ */
+cr.exportPath('settings');
+
+/**
+ * @typedef {{actionLinkText: (string|undefined),
+ * childUser: (boolean|undefined),
+ * hasError: (boolean|undefined),
+ * hasUnrecoverableError: (boolean|undefined),
+ * managed: (boolean|undefined),
+ * setupCompleted: (boolean|undefined),
+ * setupInProgress: (boolean|undefined),
+ * signedIn: (boolean|undefined),
+ * signinAllowed: (boolean|undefined),
+ * signoutAllowed: (boolean|undefined),
+ * statusText: (string|undefined),
+ * supervisedUser: (boolean|undefined),
+ * syncSystemEnabled: (boolean|undefined)}}
+ * @see chrome/browser/ui/webui/settings/people_handler.cc
+ */
+settings.SyncStatus;
+
+/**
+ * The state of sync. This is the data structure sent back and forth between
+ * C++ and JS. Its naming and structure is not optimal, but changing it would
+ * require changes to the C++ handler, which is already functional.
+ * @typedef {{
+ * appsEnforced: boolean,
+ * appsRegistered: boolean,
+ * appsSynced: boolean,
+ * autofillEnforced: boolean,
+ * autofillRegistered: boolean,
+ * autofillSynced: boolean,
+ * bookmarksEnforced: boolean,
+ * bookmarksRegistered: boolean,
+ * bookmarksSynced: boolean,
+ * encryptAllData: boolean,
+ * encryptAllDataAllowed: boolean,
+ * enterGooglePassphraseBody: (string|undefined),
+ * enterPassphraseBody: (string|undefined),
+ * extensionsEnforced: boolean,
+ * extensionsRegistered: boolean,
+ * extensionsSynced: boolean,
+ * fullEncryptionBody: string,
+ * passphrase: (string|undefined),
+ * passphraseRequired: boolean,
+ * passphraseTypeIsCustom: boolean,
+ * passwordsEnforced: boolean,
+ * passwordsRegistered: boolean,
+ * passwordsSynced: boolean,
+ * preferencesEnforced: boolean,
+ * preferencesRegistered: boolean,
+ * preferencesSynced: boolean,
+ * setNewPassphrase: (boolean|undefined),
+ * syncAllDataTypes: boolean,
+ * tabsEnforced: boolean,
+ * tabsRegistered: boolean,
+ * tabsSynced: boolean,
+ * themesEnforced: boolean,
+ * themesRegistered: boolean,
+ * themesSynced: boolean,
+ * typedUrlsEnforced: boolean,
+ * typedUrlsRegistered: boolean,
+ * typedUrlsSynced: boolean,
+ * }}
+ */
+settings.SyncPrefs;
+
+/**
+ * @enum {string}
+ */
+settings.PageStatus = {
+ SPINNER: 'spinner', // Before the page has loaded.
+ CONFIGURE: 'configure', // Preferences ready to be configured.
+ TIMEOUT: 'timeout', // Preferences loading has timed out.
+ DONE: 'done', // Sync subpage can be closed now.
+ PASSPHRASE_FAILED: 'passphraseFailed', // Error in the passphrase.
+};
+
+cr.define('settings', function() {
+ /** @interface */
+ function SyncBrowserProxy() {}
+
+ SyncBrowserProxy.prototype = {
+<if expr="not chromeos">
+ /**
+ * Starts the signin process for the user. Does nothing if the user is
+ * already signed in.
+ */
+ startSignIn: function() {},
+
+ /**
+ * Signs out the signed-in user.
+ * @param {boolean} deleteProfile
+ */
+ signOut: function(deleteProfile) {},
+
+ /**
+ * Opens the multi-profile user manager.
+ */
+ manageOtherPeople: function() {},
+</if>
+
+ /**
+ * Gets the current sync status.
+ * @return {!Promise<!settings.SyncStatus>}
+ */
+ getSyncStatus: function() {},
+
+ /**
+ * Function to invoke when the sync page has been navigated to. This
+ * registers the UI as the "active" sync UI so that if the user tries to
+ * open another sync UI, this one will be shown instead.
+ */
+ didNavigateToSyncPage: function() {},
+
+ /**
+ * Function to invoke when leaving the sync page so that the C++ layer can
+ * be notified that the sync UI is no longer open.
+ */
+ didNavigateAwayFromSyncPage: function() {},
+
+ /**
+ * Sets which types of data to sync.
+ * @param {!settings.SyncPrefs} syncPrefs
+ * @return {!Promise<!settings.PageStatus>}
+ */
+ setSyncDatatypes: function(syncPrefs) {},
+
+ /**
+ * Sets the sync encryption options.
+ * @param {!settings.SyncPrefs} syncPrefs
+ * @return {!Promise<!settings.PageStatus>}
+ */
+ setSyncEncryption: function(syncPrefs) {},
+
+ /**
+ * Opens the Google Activity Controls url in a new tab.
+ */
+ openActivityControlsUrl: function() {},
+ };
+
+ /**
+ * @constructor
+ * @implements {SyncBrowserProxy}
+ */
+ function SyncBrowserProxyImpl() {}
+ cr.addSingletonGetter(SyncBrowserProxyImpl);
+
+ SyncBrowserProxyImpl.prototype = {
+<if expr="not chromeos">
+ /** @override */
+ startSignIn: function() {
+ // TODO(tommycli): Currently this is always false, but this will become
+ // a parameter once supervised users are implemented in MD Settings.
+ var creatingSupervisedUser = false;
+ chrome.send('SyncSetupStartSignIn', [creatingSupervisedUser]);
+ },
+
+ /** @override */
+ signOut: function(deleteProfile) {
+ chrome.send('SyncSetupStopSyncing', [deleteProfile]);
+ },
+
+ /** @override */
+ manageOtherPeople: function() {
+ chrome.send('SyncSetupManageOtherPeople');
+ },
+</if>
+
+ /** @override */
+ getSyncStatus: function() {
+ return cr.sendWithPromise('SyncSetupGetSyncStatus');
+ },
+
+ /** @override */
+ didNavigateToSyncPage: function() {
+ chrome.send('SyncSetupShowSetupUI');
+ },
+
+ /** @override */
+ didNavigateAwayFromSyncPage: function() {
+ chrome.send('SyncSetupDidClosePage');
+ },
+
+ /** @override */
+ setSyncDatatypes: function(syncPrefs) {
+ return cr.sendWithPromise('SyncSetupSetDatatypes',
+ JSON.stringify(syncPrefs));
+ },
+
+ /** @override */
+ setSyncEncryption: function(syncPrefs) {
+ return cr.sendWithPromise('SyncSetupSetEncryption',
+ JSON.stringify(syncPrefs));
+ },
+
+ /** @override */
+ openActivityControlsUrl: function() {
+ chrome.metricsPrivate.recordUserAction(
+ 'Signin_AccountSettings_GoogleActivityControlsClicked');
+ window.open(loadTimeData.getString('activityControlsUrl'));
+ }
+ };
+
+ return {
+ SyncBrowserProxyImpl: SyncBrowserProxyImpl,
+ };
+});
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_page.css b/chromium/chrome/browser/resources/settings/people_page/sync_page.css
deleted file mode 100644
index 743c1a6d271..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.css
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright (c) 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. */
-
-paper-checkbox {
- margin-bottom: 10px;
-}
-
-paper-radio-button {
- display: block;
-}
-
-#sync-item-list {
- -webkit-margin-start: 32px;
-}
-
-#sync-item-list paper-checkbox {
- display: block;
-}
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 70437ff71d3..cdf2e67beea 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.html
@@ -1,4 +1,6 @@
+<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-pages/iron-pages.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">
@@ -7,123 +9,171 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html">
<link rel="import" href="chrome://md-settings/controls/settings_checkbox.html">
-<link rel="import" href="chrome://md-settings/people_page/sync_private_api.html">
+<link rel="import" href="chrome://md-settings/people_page/sync_browser_proxy.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<dom-module id="settings-sync-page">
- <link rel="import" type="css" href="sync_page.css">
<template>
- <style include="settings-shared"></style>
- <iron-pages id="pages" selected="loading" attr-for-selected="id">
- <div id="loading" i18n-content="syncLoading"></div>
- <div id="timeout" i18n-content="syncTimeout"></div>
- <div id="main">
- <div class="settings-box">
- <paper-checkbox checked="{{syncPrefs.syncAllDataTypes}}"
+ <style include="settings-shared">
+ #create-password-box {
+ /* The password fields line up with the encryption radio box text. */
+ -webkit-margin-start: 36px;
+ }
+
+ paper-input {
+ width: var(--paper-input-max-width);
+ }
+ </style>
+ <iron-pages id="pages" selected="[[selectedPage_]]" attr-for-selected="id">
+ <div id="[[pages.SPINNER]]" class="settings-box first">
+ $i18n{syncLoading}
+ </div>
+ <div id="[[pages.TIMEOUT]]" class="settings-box first">
+ $i18n{syncTimeout}
+ </div>
+ <div id="[[pages.CONFIGURE]]">
+ <div class="settings-box first">
+ <paper-checkbox id="syncAllDataTypesCheckbox"
+ checked="{{syncPrefs.syncAllDataTypes}}"
on-change="onSyncAllDataTypesChanged_">
- <span i18n-content="syncEverythingCheckboxLabel">
+ $i18n{syncEverythingCheckboxLabel}
</paper-checkbox>
+ </div>
- <div id="sync-item-list">
- <paper-checkbox checked="{{syncPrefs.appsSynced}}"
- hidden="[[!syncPrefs.appsRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.appsEnforced)]]">
- <span i18n-content="appCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.autofillSynced}}"
- hidden="[[!syncPrefs.autofillRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.autofillEnforced)]]">
- <span i18n-content="autofillCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.bookmarksSynced}}"
- hidden="[[!syncPrefs.bookmarksRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.bookmarksEnforced)]]">
- <span i18n-content="bookmarksCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.extensionsSynced}}"
- hidden="[[!syncPrefs.extensionsRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.extensionsEnforced)]]">
- <span i18n-content="extensionsCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.typedUrlsSynced}}"
- hidden="[[!syncPrefs.typedUrlsRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.typedUrlsEnforced)]]">
- <span i18n-content="historyCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.passwordsSynced}}"
- hidden="[[!syncPrefs.passwordsRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.passwordsEnforced)]]">
- <span i18n-content="passwordsCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.preferencesSynced}}"
- hidden="[[!syncPrefs.preferencesRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.preferencesEnforced)]]">
- <span i18n-content="settingsCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.themesSynced}}"
- hidden="[[!syncPrefs.themesRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.themesEnforced)]]">
- <span i18n-content="themesAndWallpapersCheckboxLabel"></span>
- </paper-checkbox>
- <paper-checkbox checked="{{syncPrefs.tabsSynced}}"
- hidden="[[!syncPrefs.tabsRegistered]]"
- disabled="[[shouldSyncCheckboxBeDisabled_(syncPrefs.syncAllDataTypes, syncPrefs.tabsEnforced)]]">
- <span i18n-content="openTabsCheckboxLabel"></span>
- </paper-checkbox>
- </div>
+ <div class="list-frame">
+ <paper-checkbox checked="{{syncPrefs.appsSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.appsRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.appsEnforced)]]">
+ $i18n{appCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.autofillSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.autofillRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.autofillEnforced)]]">
+ $i18n{autofillCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.bookmarksSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.bookmarksRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.bookmarksEnforced)]]">
+ $i18n{bookmarksCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.extensionsSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.extensionsRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.extensionsEnforced)]]">
+ $i18n{extensionsCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.typedUrlsSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.typedUrlsRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.typedUrlsEnforced)]]">
+ $i18n{historyCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.passwordsSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.passwordsRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.passwordsEnforced)]]">
+ $i18n{passwordsCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.preferencesSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.preferencesRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.preferencesEnforced)]]">
+ $i18n{settingsCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.themesSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.themesRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.themesEnforced)]]">
+ $i18n{themesAndWallpapersCheckboxLabel}
+ </paper-checkbox>
+ <paper-checkbox checked="{{syncPrefs.tabsSynced}}"
+ on-change="onSingleSyncDataTypeChanged_" class="list-item"
+ hidden="[[!syncPrefs.tabsRegistered]]"
+ disabled="[[shouldSyncCheckboxBeDisabled_(
+ syncPrefs.syncAllDataTypes, syncPrefs.tabsEnforced)]]">
+ $i18n{openTabsCheckboxLabel}
+ </paper-checkbox>
</div>
- <div class="settings-box">
- <h2 i18n-content="encryptionOptionsTitle"></h2>
- <p i18n-content="syncDataEncryptedText"></p>
+ <div class="settings-box two-line">
+ <div class="start">
+ $i18n{encryptionOptionsTitle}
+ <div class="secondary">
+ $i18n{syncDataEncryptedText}
+ </div>
+ </div>
+ </div>
- <template is="dom-if" if="[[!syncPrefs.showPassphrase]]">
- <paper-radio-group id="encryptRadioGroup"
- selected="[[selectedEncryptionRadio_(syncPrefs.usePassphrase, syncPrefs.encryptAllData)]]"
- on-paper-radio-group-changed="onEncryptionRadioSelectionChanged_">
- <paper-radio-button name="encrypt-with-google"
- disabled="[[encryptionRadiosDisabled_(syncPrefs.usePassphrase, syncPrefs.encryptAllData)]]">
- <span>[[i18n('encryptWithGoogleCredentialsLabel')]]</span>
- </paper-radio-button>
- <paper-radio-button name="encrypt-with-passphrase"
- disabled="[[encryptionRadiosDisabled_(syncPrefs.usePassphrase, syncPrefs.encryptAllData)]]">
- <span>[[encryptWithPassphraseBody_(syncPrefs.fullEncryptionBody)]]</span>
- </paper-radio-button>
- </paper-radio-group>
- </template>
+ <div id="encryptionRadioGroupContainer" class="list-frame"
+ hidden="[[syncPrefs.passphraseRequired]]">
+ <paper-radio-group
+ selected="[[selectedEncryptionRadio_(
+ syncPrefs.passphraseTypeIsCustom)]]"
+ on-paper-radio-group-changed="onEncryptionRadioSelectionChanged_">
+ <paper-radio-button name="encrypt-with-google"
+ class="list-item" disabled="[[syncPrefs.encryptAllData]]">
+ $i18n{encryptWithGoogleCredentialsLabel}
+ </paper-radio-button>
+ <paper-radio-button name="encrypt-with-passphrase"
+ class="list-item" disabled="[[syncPrefs.encryptAllData]]">
+ <span>
+ [[encryptWithPassphraseBody_(syncPrefs.fullEncryptionBody)]]
+ </span>
+ </paper-radio-button>
+ </paper-radio-group>
+ </div>
- <template is="dom-if" if="[[creatingNewPassphrase]]">
- <div>[[i18n('passphraseExplanationText')]]</div>
- <paper-input id="passphraseInput" type="password"
- placeholder="[[i18n('passphrasePlaceholder')]]">
- </paper-input>
- <paper-input id="passphraseConfirmationInput" type="password"
- placeholder="[[i18n('passphraseConfirmationPlaceholder')]]">
- </paper-input>
- <div id="emptyPassphraseError" hidden>[[i18n('emptyPassphraseError')]]</div>
- <div id="mismatchedPassphraseError" hidden>[[i18n('mismatchedPassphraseError')]]</div>
- </template>
+ <template is="dom-if" if="[[creatingNewPassphrase_]]">
+ <div class="list-frame">
+ <div id="create-password-box">
+ <div>$i18n{passphraseExplanationText}</div>
+ <paper-input id="passphraseInput" type="password"
+ placeholder="$i18n{passphrasePlaceholder}"
+ error-message="$i18n{emptyPassphraseError}">
+ </paper-input>
+ <paper-input id="passphraseConfirmationInput" type="password"
+ placeholder="$i18n{passphraseConfirmationPlaceholder}"
+ error-message="$i18n{mismatchedPassphraseError}">
+ </paper-input>
+ <paper-button id="saveNewPassphrase"
+ on-tap="onSaveNewPassphraseTap_" class="action-button">
+ $i18n{save}
+ </paper-button>
+ </div>
+ </div>
+ </template>
- <template is="dom-if" if="[[syncPrefs.showPassphrase]]">
+ <template is="dom-if" if="[[syncPrefs.passphraseRequired]]">
+ <div class="list-frame">
<div id="askCustomPassphraseMessage"
- hidden="[[askOldGooglePassphrase]]">[[syncPrefs.enterPassphraseBody]]</div>
+ hidden$="[[!syncPrefs.passphraseTypeIsCustom]]">
+ [[syncPrefs.enterPassphraseBody]]
+ </div>
<div id="askOldGooglePassphraseMessage"
- hidden="[[!askOldGooglePassphrase]]">[[syncPrefs.enterGooglePassphraseBody]]</div>
+ hidden$="[[syncPrefs.passphraseTypeIsCustom]]">
+ [[syncPrefs.enterGooglePassphraseBody]]
+ </div>
<paper-input id="existingPassphraseInput" type="password"
- placeholder="[[i18n('passphrasePlaceholder')]]">
+ placeholder="$i18n{passphrasePlaceholder}"
+ error-message="$i18n{incorrectPassphraseError}">
</paper-input>
- <div id="incorrectPassphraseError" hidden>[[i18n('incorrectPassphraseError')]]</div>
- </template>
- </div>
-
- <div class="settings-box">
- <paper-button i18n-content="cancel" on-tap="onCancelTap_">
- </paper-button>
- <paper-button i18n-content="ok" on-tap="onOkTap_"
- class="action-button">
- </paper-button>
- </div>
+ <paper-button id="submitExistingPassphrase"
+ on-tap="onSubmitExistingPassphraseTap_" class="action-button">
+ $i18n{submitPassphraseButton}
+ </paper-button>
+ </div>
+ </template>
</div>
</iron-pages>
</template>
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 c7b2dcfa3c2..67df7f28542 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.js
@@ -30,9 +30,26 @@ Polymer({
behaviors: [
I18nBehavior,
+ WebUIListenerBehavior,
],
properties: {
+ /** @private */
+ pages: {
+ type: Object,
+ value: settings.PageStatus,
+ readOnly: true,
+ },
+
+ /**
+ * The curerntly displayed page.
+ * @private {!settings.PageStatus}
+ */
+ selectedPage_: {
+ type: String,
+ value: settings.PageStatus.SPINNER,
+ },
+
/**
* The current active route.
*/
@@ -42,7 +59,7 @@ Polymer({
},
/**
- * The current sync preferences, supplied by settings.SyncPrivateApi.
+ * The current sync preferences, supplied by SyncBrowserProxy.
* @type {?settings.SyncPrefs}
*/
syncPrefs: {
@@ -53,64 +70,112 @@ Polymer({
* Whether the "create passphrase" inputs should be shown. These inputs
* give the user the opportunity to use a custom passphrase instead of
* authenticating with his Google credentials.
+ * @private
*/
- creatingNewPassphrase: {
+ creatingNewPassphrase_: {
type: Boolean,
value: false,
},
+ /** @private {!settings.SyncBrowserProxyImpl} */
+ browserProxy_: {
+ type: Object,
+ value: function() {
+ return settings.SyncBrowserProxyImpl.getInstance();
+ },
+ },
+
/**
- * True if subpage needs the user's old Google password. This can happen
- * when the user changes his password after encrypting his sync data.
- *
- * TODO(tommycli): FROM the C++ handler, the syncPrefs.usePassphrase field
- * is true if and only if there is a custom non-Google Sync password.
- *
- * But going TO the C++ handler, the syncPrefs.usePassphrase field is true
- * if there is either a custom or Google password. There is a separate
- * syncPrefs.isGooglePassphrase field.
- *
- * We keep an extra state variable here because we mutate the
- * syncPrefs.usePassphrase field in the OK button handler.
- * Remove this once we fix refactor the legacy SyncSetupHandler.
+ * The unload callback is needed because the sign-in flow needs to know
+ * if the user has closed the tab with the sync settings. This property is
+ * non-null if the user is currently navigated on the sync settings route.
+ * @private {Function}
*/
- askOldGooglePassphrase: {
- type: Boolean,
- value: false,
+ unloadCallback_: {
+ type: Object,
+ value: null,
},
},
- created: function() {
- settings.SyncPrivateApi.setSyncPrefsCallback(
- this.handleSyncPrefsFetched_.bind(this));
+ /** @override */
+ attached: function() {
+ this.addWebUIListener('page-status-changed',
+ this.handlePageStatusChanged_.bind(this));
+ this.addWebUIListener('sync-prefs-changed',
+ this.handleSyncPrefsChanged_.bind(this));
+
+ if (this.isCurrentRouteOnSyncPage_())
+ this.onNavigateToPage_();
+ },
+
+ /** @override */
+ detached: function() {
+ if (this.isCurrentRouteOnSyncPage_())
+ this.onNavigateAwayFromPage_();
+ },
+
+ /**
+ * @private
+ * @return {boolean} Whether the current route shows the sync page.
+ */
+ isCurrentRouteOnSyncPage_: function() {
+ return this.currentRoute &&
+ this.currentRoute.section == 'people' &&
+ this.currentRoute.subpage.length == 1 &&
+ this.currentRoute.subpage[0] == 'sync';
},
/** @private */
currentRouteChanged_: function() {
- if (this.currentRoute.section == 'people' &&
- this.currentRoute.subpage.length == 1 &&
- this.currentRoute.subpage[0] == 'sync') {
- // Display loading page until the settings have been retrieved.
- this.$.pages.selected = 'loading';
- settings.SyncPrivateApi.didNavigateToSyncPage();
- } else {
- settings.SyncPrivateApi.didNavigateAwayFromSyncPage();
- }
+ if (!this.isAttached)
+ return;
+
+ if (this.isCurrentRouteOnSyncPage_())
+ this.onNavigateToPage_();
+ else
+ this.onNavigateAwayFromPage_();
+ },
+
+ /** @private */
+ onNavigateToPage_: function() {
+ // The element is not ready for C++ interaction until it is attached.
+ assert(this.isAttached);
+ assert(this.isCurrentRouteOnSyncPage_());
+
+ if (this.unloadCallback_)
+ return;
+
+ // Display loading page until the settings have been retrieved.
+ this.selectedPage_ = settings.PageStatus.SPINNER;
+
+ this.browserProxy_.didNavigateToSyncPage();
+
+ this.unloadCallback_ = this.onNavigateAwayFromPage_.bind(this);
+ window.addEventListener('unload', this.unloadCallback_);
+ },
+
+ /** @private */
+ onNavigateAwayFromPage_: function() {
+ if (!this.unloadCallback_)
+ return;
+
+ this.browserProxy_.didNavigateAwayFromSyncPage();
+
+ window.removeEventListener('unload', this.unloadCallback_);
+ this.unloadCallback_ = null;
},
/**
- * Handler for when the sync state is pushed from settings.SyncPrivateApi.
+ * Handler for when the sync preferences are updated.
* @private
*/
- handleSyncPrefsFetched_: function(syncPrefs) {
+ handleSyncPrefsChanged_: function(syncPrefs) {
this.syncPrefs = syncPrefs;
+ this.selectedPage_ = settings.PageStatus.CONFIGURE;
- this.askOldGooglePassphrase =
- this.syncPrefs.showPassphrase && !this.syncPrefs.usePassphrase;
-
- this.creatingNewPassphrase = false;
-
- this.$.pages.selected = 'main';
+ // Hide the new passphrase box if the sync data has been encrypted.
+ if (this.syncPrefs.encryptAllData)
+ this.creatingNewPassphrase_ = false;
},
/**
@@ -131,57 +196,83 @@ Polymer({
this.set('syncPrefs.passwordsSynced', true);
this.set('syncPrefs.tabsSynced', true);
}
+
+ this.onSingleSyncDataTypeChanged_();
},
- /** @private */
- onCancelTap_: function() {
- // Event is caught by settings-animated-pages.
- this.fire('subpage-back');
+ /**
+ * Handler for when any sync data type checkbox is changed.
+ * @private
+ */
+ onSingleSyncDataTypeChanged_: function() {
+ this.browserProxy_.setSyncDatatypes(this.syncPrefs).then(
+ this.handlePageStatusChanged_.bind(this));
},
/**
- * Sets the sync data by sending it to the settings.SyncPrivateApi.
+ * Sends the newly created custom sync passphrase to the browser.
* @private
*/
- onOkTap_: function() {
- if (this.creatingNewPassphrase) {
- // If a new password has been entered but it is invalid, do not send the
- // sync state to the API.
- if (!this.validateCreatedPassphrases_())
- return;
+ onSaveNewPassphraseTap_: function() {
+ assert(this.creatingNewPassphrase_);
- this.syncPrefs.encryptAllData = true;
- }
+ // If a new password has been entered but it is invalid, do not send the
+ // sync state to the API.
+ if (!this.validateCreatedPassphrases_())
+ return;
- this.syncPrefs.isGooglePassphrase = this.askOldGooglePassphrase;
- this.syncPrefs.usePassphrase =
- this.creatingNewPassphrase || this.syncPrefs.showPassphrase;
+ this.syncPrefs.encryptAllData = true;
+ this.syncPrefs.setNewPassphrase = true;
+ this.syncPrefs.passphrase = this.$$('#passphraseInput').value;
- if (this.syncPrefs.usePassphrase) {
- var field = this.creatingNewPassphrase ?
- this.$$('#passphraseInput') : this.$$('#existingPassphraseInput');
- this.syncPrefs.passphrase = field.value;
- field.value = '';
- }
+ this.browserProxy_.setSyncEncryption(this.syncPrefs).then(
+ this.handlePageStatusChanged_.bind(this));
+ },
- settings.SyncPrivateApi.setSyncPrefs(
- this.syncPrefs, this.setPageStatusCallback_.bind(this));
+ /**
+ * Sends the user-entered existing password to re-enable sync.
+ * @private
+ */
+ onSubmitExistingPassphraseTap_: function() {
+ assert(!this.creatingNewPassphrase_);
+
+ this.syncPrefs.setNewPassphrase = false;
+
+ var existingPassphraseInput = this.$$('#existingPassphraseInput');
+ this.syncPrefs.passphrase = existingPassphraseInput.value;
+ existingPassphraseInput.value = '';
+
+ this.browserProxy_.setSyncEncryption(this.syncPrefs).then(
+ this.handlePageStatusChanged_.bind(this));
},
/**
- * Callback invoked from calling settings.SyncPrivateApi.setSyncPrefs().
- * @param {!settings.PageStatus} callbackState
+ * Called when the page status updates.
+ * @param {!settings.PageStatus} pageStatus
* @private
*/
- setPageStatusCallback_: function(callbackState) {
- if (callbackState == settings.PageStatus.DONE) {
- this.onCancelTap_();
- } else if (callbackState == settings.PageStatus.TIMEOUT) {
- this.$.pages.selected = 'timeout';
- } else if (callbackState ==
- settings.PageStatus.PASSPHRASE_ERROR) {
- this.$$('#incorrectPassphraseError').hidden = false;
+ handlePageStatusChanged_: function(pageStatus) {
+ switch (pageStatus) {
+ case settings.PageStatus.SPINNER:
+ case settings.PageStatus.TIMEOUT:
+ case settings.PageStatus.CONFIGURE:
+ this.selectedPage_ = pageStatus;
+ return;
+ case settings.PageStatus.DONE:
+ if (this.isCurrentRouteOnSyncPage_()) {
+ // Event is caught by settings-animated-pages.
+ this.fire('subpage-back');
+ }
+ return;
+ case settings.PageStatus.PASSPHRASE_FAILED:
+ if (this.selectedPage_ == this.pages.CONFIGURE &&
+ this.syncPrefs && this.syncPrefs.passphraseRequired) {
+ this.$$('#existingPassphraseInput').invalid = true;
+ }
+ return;
}
+
+ assertNotReached();
},
/**
@@ -189,7 +280,7 @@ Polymer({
* @private
*/
onEncryptionRadioSelectionChanged_: function(event) {
- this.creatingNewPassphrase =
+ this.creatingNewPassphrase_ =
event.target.selected == RadioButtonNames.ENCRYPT_WITH_PASSPHRASE;
},
@@ -198,20 +289,12 @@ Polymer({
* @private
*/
selectedEncryptionRadio_: function() {
- return this.encryptionRadiosDisabled_() ?
+ return this.syncPrefs.encryptAllData || this.creatingNewPassphrase_ ?
RadioButtonNames.ENCRYPT_WITH_PASSPHRASE :
RadioButtonNames.ENCRYPT_WITH_GOOGLE;
},
/**
- * Computed binding returning the selected encryption radio button.
- * @private
- */
- encryptionRadiosDisabled_: function() {
- return this.syncPrefs.usePassphrase || this.syncPrefs.encryptAllData;
- },
-
- /**
* Computed binding returning the encryption text body.
* @private
*/
@@ -240,22 +323,20 @@ Polymer({
* @private
*/
validateCreatedPassphrases_: function() {
- this.$$('#emptyPassphraseError').hidden = true;
- this.$$('#mismatchedPassphraseError').hidden = true;
+ var passphraseInput = this.$$('#passphraseInput');
+ var passphraseConfirmationInput = this.$$('#passphraseConfirmationInput');
- var passphrase = this.$$('#passphraseInput').value;
- if (!passphrase) {
- this.$$('#emptyPassphraseError').hidden = false;
- return false;
- }
+ var passphrase = passphraseInput.value;
+ var confirmation = passphraseConfirmationInput.value;
- var confirmation = this.$$('#passphraseConfirmationInput').value;
- if (passphrase != confirmation) {
- this.$$('#mismatchedPassphraseError').hidden = false;
- return false;
- }
+ var emptyPassphrase = !passphrase;
+ var mismatchedPassphrase = passphrase != confirmation;
+
+ passphraseInput.invalid = emptyPassphrase;
+ passphraseConfirmationInput.invalid =
+ !emptyPassphrase && mismatchedPassphrase;
- return true;
+ return !emptyPassphrase && !mismatchedPassphrase;
},
});
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_private_api.html b/chromium/chrome/browser/resources/settings/people_page/sync_private_api.html
deleted file mode 100644
index a909061145f..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/sync_private_api.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="chrome://md-settings/people_page/sync_private_api.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_private_api.js b/chromium/chrome/browser/resources/settings/people_page/sync_private_api.js
deleted file mode 100644
index 17e4752163d..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/sync_private_api.js
+++ /dev/null
@@ -1,265 +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.exportPath('settings');
-
-/**
- * The state of sync. This is the data structure sent back and forth between
- * C++ and JS. Its naming and structure is not optimal, but changing it would
- * require changes to the C++ handler, which is already functional.
- * @typedef {{
- * appsEnforced: boolean,
- * appsRegistered: boolean,
- * appsSynced: boolean,
- * autofillEnforced: boolean,
- * autofillRegistered: boolean,
- * autofillSynced: boolean,
- * bookmarksEnforced: boolean,
- * bookmarksRegistered: boolean,
- * bookmarksSynced: boolean,
- * encryptAllData: boolean,
- * encryptAllDataAllowed: boolean,
- * enterGooglePassphraseBody: (string|undefined),
- * enterPassphraseBody: (string|undefined),
- * extensionsEnforced: boolean,
- * extensionsRegistered: boolean,
- * extensionsSynced: boolean,
- * fullEncryptionBody: string,
- * isGooglePassphrase: (boolean|undefined),
- * passphrase: (string|undefined),
- * passphraseFailed: boolean,
- * passwordsEnforced: boolean,
- * passwordsRegistered: boolean,
- * passwordsSynced: boolean,
- * preferencesEnforced: boolean,
- * preferencesRegistered: boolean,
- * preferencesSynced: boolean,
- * showPassphrase: boolean,
- * syncAllDataTypes: boolean,
- * syncNothing: boolean,
- * tabsEnforced: boolean,
- * tabsRegistered: boolean,
- * tabsSynced: boolean,
- * themesEnforced: boolean,
- * themesRegistered: boolean,
- * themesSynced: boolean,
- * typedUrlsEnforced: boolean,
- * typedUrlsRegistered: boolean,
- * typedUrlsSynced: boolean,
- * usePassphrase: boolean,
- * wifiCredentialsEnforced: (boolean|undefined),
- * wifiCredentialsSynced: (boolean|undefined)
- * }}
- */
-settings.SyncPrefs;
-
-/**
- * @typedef {{actionLinkText: (string|undefined),
- * childUser: (boolean|undefined),
- * hasError: (boolean|undefined),
- * hasUnrecoverableError: (boolean|undefined),
- * managed: (boolean|undefined),
- * setupCompleted: (boolean|undefined),
- * setupInProgress: (boolean|undefined),
- * signedIn: (boolean|undefined),
- * signinAllowed: (boolean|undefined),
- * signoutAllowed: (boolean|undefined),
- * statusText: (string|undefined),
- * supervisedUser: (boolean|undefined),
- * syncSystemEnabled: (boolean|undefined)}}
- * @see chrome/browser/ui/webui/settings/sync_handler.cc
- */
-settings.SyncStatus;
-
-/**
- * @enum {string}
- */
-settings.PageStatus = {
- SPINNER: 'spinner', // Before the page has loaded.
- CONFIGURE: 'configure', // Preferences ready to be configured.
- TIMEOUT: 'timeout', // Preferences loading has timed out.
- DONE: 'done', // Sync subpage can be closed now.
- PASSPHRASE_ERROR: 'passphraseError', // Error in the passphrase.
-};
-
-cr.define('settings', function() {
- /**
- * API which encapsulates messaging between JS and C++ for the sync page.
- * @constructor
- */
- function SyncPrivateApi() {}
-
- /** @private {?function(!string, !string)} */
- SyncPrivateApi.getProfileInfoCallback_ = null;
-
- /** @private {?function(settings.SyncPrefs)} */
- SyncPrivateApi.syncPrefsCallback_ = null;
-
- /** @private {?function(settings.PageStatus)} */
- SyncPrivateApi.setPageStatusCallback_ = null;
-
- /**
- * Called from JavaScript. Gets the current profile name and icon.
- * @param {?function(!string, !string)} callback
- */
- SyncPrivateApi.getProfileInfo = function(callback) {
- SyncPrivateApi.getProfileInfoCallback_ = callback;
- chrome.send('getProfileInfo');
- };
-
- /**
- * Called from C++ as a response to getIconsAndNames.
- * @param {!string} name The current profile name.
- * @param {!string} iconUrl The current profile icon's URL. Can be a data URL.
- */
- SyncPrivateApi.receiveProfileInfo = function(name, iconUrl) {
- if (SyncPrivateApi.getProfileInfoCallback_)
- SyncPrivateApi.getProfileInfoCallback_(name, iconUrl);
- };
-
- /**
- * Starts the signin process for the user. Does nothing if the user is
- * already signed in.
- * @private
- */
- SyncPrivateApi.startSignIn = function() {
- // TODO(tommycli): Currently this is always false, but this will become
- // a parameter once supervised users are implemented in MD Settings.
- var creatingSupervisedUser = false;
- chrome.send('SyncSetupStartSignIn', [creatingSupervisedUser]);
- };
-
- /**
- * Disconnects the signed in user.
- * @param {!boolean} deleteProfile
- * @private
- */
- SyncPrivateApi.disconnect = function(deleteProfile) {
- chrome.send('SyncSetupStopSyncing', [deleteProfile]);
- };
-
- /**
- * Determines the appropriate page to show in the Sync Setup UI based on
- * the state of the Sync backend. Does nothing if the user is not signed in.
- * @private
- */
- SyncPrivateApi.showSetupUI = function() {
- chrome.send('SyncSetupShowSetupUI');
- chrome.send('coreOptionsUserMetricsAction', ['Options_ShowSyncAdvanced']);
- };
-
- /**
- * Function to invoke when the sync page has been navigated to. This registers
- * the UI as the "active" sync UI so that if the user tries to open another
- * sync UI, this one will be shown instead.
- */
- SyncPrivateApi.didNavigateToSyncPage = function() {
- chrome.send('SyncSetupShowSetupUI');
- };
-
- /**
- * Function to invoke when leaving the sync page so that the C++ layer can be
- * notified that the sync UI is no longer open.
- */
- SyncPrivateApi.didNavigateAwayFromSyncPage = function() {
- SyncPrivateApi.setPageStatusCallback_ = null;
- chrome.send('SyncSetupDidClosePage');
- };
-
- /**
- * Sets the callback to be invoked when sync data has been fetched.
- * @param {!function(settings.SyncPrefs)} callback
- */
- SyncPrivateApi.setSyncPrefsCallback = function(callback) {
- SyncPrivateApi.syncPrefsCallback_ = callback;
- };
-
- /**
- * Handler for when state has been fetched from C++.
- * @param {!settings.SyncPrefs} syncPrefsFromCpp
- * @private
- */
- SyncPrivateApi.sendSyncPrefs_ = function(syncPrefsFromCpp) {
- if (SyncPrivateApi.syncPrefsCallback_)
- SyncPrivateApi.syncPrefsCallback_(syncPrefsFromCpp);
- };
-
- /**
- * Sets the sync state by sending it to the C++ layer.
- * @param {!settings.SyncPrefs} syncPrefs
- * @param {!function(settings.PageStatus)} callback
- */
- SyncPrivateApi.setSyncPrefs = function(syncPrefs, callback) {
- SyncPrivateApi.setPageStatusCallback_ = callback;
- chrome.send('SyncSetupConfigure', [JSON.stringify(syncPrefs)]);
- };
-
- /**
- * Handler for when setSyncPrefs() has either succeeded or failed.
- * @param {!settings.PageStatus} status
- * @private
- */
- SyncPrivateApi.setPageStatus_ = function(status) {
- if (SyncPrivateApi.setPageStatusCallback_)
- SyncPrivateApi.setPageStatusCallback_(status);
-
- SyncPrivateApi.setPageStatusCallback_ = null;
- };
-
- /**
- * Sends a request from JS to C++ for the current sync status.
- * @param {!function(settings.SyncStatus)} callback
- */
- SyncPrivateApi.getSyncStatus = function(callback) {
- SyncPrivateApi.syncStatusCallback_ = callback;
- chrome.send('SyncSetupGetSyncStatus');
- };
-
- /**
- * Handler for when sync status has been fetched from C++.
- * @param {!settings.SyncStatus} syncStatusFromCpp
- * @private
- */
- SyncPrivateApi.sendSyncStatus = function(syncStatusFromCpp) {
- if (SyncPrivateApi.syncStatusCallback_)
- SyncPrivateApi.syncStatusCallback_(syncStatusFromCpp);
- };
-
- /**
- * Sends a request from JS to C++ to open the multi-profile User Manager.
- */
- SyncPrivateApi.manageOtherPeople = function() {
- chrome.send('SyncSetupManageOtherPeople');
- };
-
- /**
- * This function encapsulates the logic that maps from the legacy
- * SyncSettingsHandler to an API natural to the new Polymer implementation.
- * @param {!settings.PageStatus} status
- * @param {!settings.SyncPrefs} prefs
- */
- SyncPrivateApi.showSyncSetupPage = function(status, prefs) {
- switch (status) {
- case settings.PageStatus.TIMEOUT:
- case settings.PageStatus.DONE:
- SyncPrivateApi.setPageStatus_(status);
- break;
- case settings.PageStatus.CONFIGURE:
- if (prefs.passphraseFailed) {
- SyncPrivateApi.setPageStatus_(
- settings.PageStatus.PASSPHRASE_ERROR);
- return;
- }
-
- SyncPrivateApi.sendSyncPrefs_(prefs);
- break;
- default:
- // Other statuses (i.e. "spinner") are ignored.
- }
- };
-
- return {
- SyncPrivateApi: SyncPrivateApi,
- };
-});
diff --git a/chromium/chrome/browser/resources/settings/people_page/user_list.css b/chromium/chrome/browser/resources/settings/people_page/user_list.css
deleted file mode 100644
index c870237f7d4..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/user_list.css
+++ /dev/null
@@ -1,26 +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. */
-
-.soft-border {
- border: 1px solid #c4c4c4;
- border-radius: 2px;
-}
-
-.user {
- -webkit-padding-end: 8px;
- -webkit-padding-start: 20px;
- font-size: 0.75em;
- height: 34px;
-}
-
-.user:hover {
- background-color: #f0f0f0;
-}
-
-.user-list {
- border: 1px solid gray;
- height: 160px;
- overflow-y: auto;
- padding: 10px 0;
-}
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 7a19bcf6fa3..ac6ebda1d71 100644
--- a/chromium/chrome/browser/resources/settings/people_page/user_list.html
+++ b/chromium/chrome/browser/resources/settings/people_page/user_list.html
@@ -1,19 +1,42 @@
+<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-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-user-list">
- <link rel="import" type="css" href="user_list.css">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ .soft-border {
+ border: 1px solid #c4c4c4;
+ border-radius: 2px;
+ }
+
+ .user {
+ -webkit-padding-end: 8px;
+ -webkit-padding-start: 20px;
+ font-size: 0.75em;
+ height: 34px;
+ }
+
+ .user:hover {
+ background-color: #f0f0f0;
+ }
+
+ .user-list {
+ border: 1px solid gray;
+ height: 160px;
+ overflow-y: auto;
+ padding: 10px 0;
+ }
+ </style>
<div class="user-list soft-border">
<template is="dom-repeat" items="[[users]]">
<div class="user layout horizontal justified">
<div class="layout vertical center-justified">[[item.email]]</div>
<div class="close-button"
hidden$="[[shouldHideCloseButton_(disabled, item.isOwner)]]">
- <paper-icon-button icon="clear" class="clear-icon"
+ <paper-icon-button icon="cr:clear" class="clear-icon"
on-tap="removeUser_">
</paper-icon-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/people_page/users_page.css b/chromium/chrome/browser/resources/settings/people_page/users_page.css
deleted file mode 100644
index 46166f5c039..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/users_page.css
+++ /dev/null
@@ -1,19 +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. */
-
-#addUserInput {
- width: 100%;
-}
-
-.add-user-button {
- padding-top: 25px;
-}
-
-.users {
- -webkit-margin-start: 50px;
-}
-
-paper-input {
- width: 300px;
-}
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 a734ba01bbd..9c9d5b640f8 100644
--- a/chromium/chrome/browser/resources/settings/people_page/users_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/users_page.html
@@ -9,37 +9,52 @@
<link rel="import" href="user_list.html">
<dom-module id="settings-users-page">
- <link rel="import" type="css" href="users_page.css">
<template>
- <style include="settings-shared"></style>
- <div class="settings-box" i18n-content="usersModifiedByOwnerLabel"
+ <style include="settings-shared">
+ #addUserInput {
+ width: 100%;
+ }
+
+ .add-user-button {
+ padding-top: 25px;
+ }
+
+ .users {
+ -webkit-margin-start: 50px;
+ }
+
+ paper-input {
+ width: 300px;
+ }
+ </style>
+ <div class="settings-box"
hidden$="{{computeHideOwnerLabel_(isOwner, isWhitelistManaged)}}">
+ $i18n{usersModifiedByOwnerLabel}
</div>
- <div class="settings-box" i18n-content="settingsManagedLabel"
+ <div class="settings-box"
hidden$="{{computeHideManagedLabel_(isOwner, isWhitelistManaged)}}">
+ $i18n{settingsManagedLabel}
</div>
- <div class="settings-box">
+ <div class="settings-box block">
<settings-checkbox
pref="{{prefs.cros.accounts.allowBWSI}}"
- i18n-values="label:guestBrowsingLabel"
+ label="$i18n{guestBrowsingLabel}"
disabled="{{editingDisabled}}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.cros.accounts.supervisedUsersEnabled}}"
- i18n-values="label:supervisedUsersLabel"
+ label="$i18n{supervisedUsersLabel}"
disabled="{{editingDisabled}}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.cros.accounts.showUserNamesOnSignIn}}"
- i18n-values="label:showOnSigninLabel"
+ label="$i18n{showOnSigninLabel}"
disabled="{{editingDisabled}}">
</settings-checkbox>
- </div>
- <div class="settings-box">
<settings-checkbox
pref="{{prefs.cros.accounts.allowGuest}}"
id="restrictSignIn"
- i18n-values="label:restrictSigninLabel"
+ label="$i18n{restrictSigninLabel}"
disabled="{{editingDisabled}}" inverted>
</settings-checkbox>
<div class="users">
@@ -49,12 +64,13 @@
</settings-user-list>
</div>
<div>
- <paper-input id="addUserInput" i18n-values="label:addUsersLabel"
+ <paper-input id="addUserInput" label="$i18n{addUsersLabel}"
disabled="[[editingUsersDisabled]]">
</paper-input>
<div class="add-user-button layout horizontal end-justified">
- <paper-button i18n-content="add" on-tap="addUser_"
- disabled="[[editingUsersDisabled]]" class="action-button">
+ <paper-button on-tap="addUser_" disabled="[[editingUsersDisabled]]"
+ class="action-button">
+ $i18n{add}
</paper-button>
</div>
</div>
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 8d52d8fff19..c16b06d929b 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,3 @@
-<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/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
@@ -22,58 +21,61 @@
<dom-module id="settings-privacy-page">
<template>
<style include="settings-shared"></style>
+ <template is="dom-if" if="[[showClearBrowsingDataDialog_]]" restamp>
+ <settings-clear-browsing-data-dialog prefs="{{prefs}}"
+ on-iron-overlay-closed="onIronOverlayClosed_">
+ </settings-clear-browsing-data-dialog>
+ </template>
<settings-animated-pages id="pages" current-route="{{currentRoute}}"
section="privacy">
<neon-animatable id="main">
- <settings-clear-browsing-data-dialog prefs="{{prefs}}">
- </settings-clear-browsing-data-dialog>
<div class="settings-box block first">
- <p class="privacy-explanation"
- i18n-values=".innerHTML:improveBrowsingExperience">
+ <p class="privacy-explanation">
+ $i18nRaw{improveBrowsingExperience}
</p>
<settings-checkbox
pref="{{prefs.alternate_error_pages.enabled}}"
- i18n-values="label:linkDoctorPref">
+ label="$i18n{linkDoctorPref}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.search.suggest_enabled}}"
- i18n-values="label:searchSuggestPref">
+ label="$i18n{searchSuggestPref}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.net.network_prediction_options}}"
- i18n-values="label:networkPredictionEnabled">
+ label="$i18n{networkPredictionEnabled}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.safebrowsing.extended_reporting_enabled}}"
- i18n-values="label:safeBrowsingEnableExtendedReporting">
+ label="$i18n{safeBrowsingEnableExtendedReporting}">
</settings-checkbox>
<settings-checkbox pref="{{prefs.safebrowsing.enabled}}"
- i18n-values="label:safeBrowsingEnableProtection">
+ label="$i18n{safeBrowsingEnableProtection}">
</settings-checkbox>
<if expr="_google_chrome">
<settings-checkbox
pref="{{prefs.spellcheck.use_spelling_service}}"
- i18n-values="label:spellingPref">
+ label="$i18n{spellingPref}">
</settings-checkbox>
<if expr="chromeos">
<settings-checkbox
pref="{{prefs.cros.metrics.reportingEnabled}}"
- i18n-values="label:enableLogging">
+ label="$i18n{enableLogging}">
</settings-checkbox>
</if>
<!-- TODO(jlklein): Add non-chromeos metrics box. -->
</if>
<settings-checkbox pref="{{prefs.enable_do_not_track}}"
- i18n-values="label:doNotTrack">
+ label="$i18n{doNotTrack}">
</settings-checkbox>
<if expr="chromeos">
<settings-checkbox
pref="{{prefs.cros.device.attestation_for_content_protection_enabled}}"
- i18n-values="label:enableContentProtectionAttestation">
+ label="$i18n{enableContentProtectionAttestation}">
</settings-checkbox>
<settings-checkbox
pref="{{prefs.settings.internet.wake_on_wifi_darkconnect}}"
- i18n-values="label:wakeOnWifi">
+ label="$i18n{wakeOnWifi}">
</settings-checkbox>
</if>
</div>
@@ -81,7 +83,7 @@
<div id="manageCertificates" class="settings-box two-line"
on-tap="onManageCertificatesTap_">
<div class="start">
- <div i18n-content="manageCertificates"></div>
+ <div>$i18n{manageCertificates}</div>
<div class="secondary">
<!-- TODO(dschuyler): replace this placeholder text -->
Contrary to popular belief, Lorem Ipsum is not simply random text.
@@ -91,7 +93,7 @@
</if>
<div class="settings-box two-line" on-tap="onSiteSettingsTap_">
<div class="start">
- <div i18n-content="siteSettings"></div>
+ <div>$i18n{siteSettings}</div>
<div class="secondary">
<!-- TODO(dschuyler): replace this placeholder text -->
Contrary to popular belief, Lorem Ipsum is not simply random text.
@@ -99,14 +101,14 @@
</div>
</div>
<div class="settings-box">
- <paper-button on-tap="onClearBrowsingDataTap_" class="primary-button"
- i18n-content="clearBrowsingData">
+ <paper-button on-tap="onClearBrowsingDataTap_" class="primary-button">
+ $i18n{clearBrowsingData}
</paper-button>
</div>
</neon-animatable>
<if expr="use_nss_certs">
<template is="dom-if" name="manage-certificates">
- <settings-subpage page-title="[[i18n('manageCertificates')]]">
+ <settings-subpage page-title="$i18n{manageCertificates}">
<settings-certificate-manager-page>
</settings-certificate-manager-page>
</settings-subpage>
@@ -114,7 +116,7 @@
</if>
<template is="dom-if" name="site-settings">
<settings-subpage id="site-settings"
- page-title="[[i18n('siteSettings')]]">
+ page-title="$i18n{siteSettings}">
<settings-site-settings-page current-route="{{currentRoute}}"
category-selected="{{categorySelected}}">
</settings-site-settings-page>
@@ -122,7 +124,7 @@
</template>
<template is="dom-if" name="all-sites">
- <settings-subpage page-title="[[i18n('siteSettingsCategoryAllSites')]]">
+ <settings-subpage page-title="$i18n{siteSettingsCategoryAllSites}">
<all-sites
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}">
@@ -130,7 +132,7 @@
</settings-subpage>
</template>
<template is="dom-if" name="site-settings-category-camera">
- <settings-subpage page-title="[[i18n('siteSettingsCategoryCamera')]]">
+ <settings-subpage page-title="$i18n{siteSettingsCategoryCamera}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -139,7 +141,7 @@
</settings-subpage>
</template>
<template is="dom-if" name="site-settings-category-cookies">
- <settings-subpage page-title="[[i18n('siteSettingsCategoryCookies')]]">
+ <settings-subpage page-title="$i18n{siteSettingsCategoryCookies}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -149,7 +151,7 @@
</template>
<template is="dom-if" name="site-settings-category-fullscreen">
<settings-subpage
- page-title="[[i18n('siteSettingsCategoryFullscreen')]]">
+ page-title="$i18n{siteSettingsCategoryFullscreen}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -158,7 +160,7 @@
</settings-subpage>
</template>
<template is="dom-if" name="site-settings-category-images">
- <settings-subpage page-title="[[i18n('siteSettingsCategoryImages')]]">
+ <settings-subpage page-title="$i18n{siteSettingsCategoryImages}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -167,7 +169,7 @@
</settings-subpage>
</template>
<template is="dom-if" name="site-settings-category-location">
- <settings-subpage page-title="[[i18n('siteSettingsCategoryLocation')]]">
+ <settings-subpage page-title="$i18n{siteSettingsCategoryLocation}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -177,7 +179,7 @@
</template>
<template is="dom-if" name="site-settings-category-javascript">
<settings-subpage
- page-title="[[i18n('siteSettingsCategoryJavascript')]]">
+ page-title="$i18n{siteSettingsCategoryJavascript}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -187,7 +189,7 @@
</template>
<template is="dom-if" name="site-settings-category-microphone">
<settings-subpage
- page-title="[[i18n('siteSettingsCategoryMicrophone')]]">
+ page-title="$i18n{siteSettingsCategoryMicrophone}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -197,7 +199,7 @@
</template>
<template is="dom-if" name="site-settings-category-notifications">
<settings-subpage
- page-title="[[i18n('siteSettingsCategoryNotifications')]]">
+ page-title="$i18n{siteSettingsCategoryNotifications}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -206,7 +208,7 @@
</settings-subpage>
</template>
<template is="dom-if" name="site-settings-category-popups">
- <settings-subpage page-title="[[i18n('siteSettingsCategoryPopups')]]">
+ <settings-subpage page-title="$i18n{siteSettingsCategoryPopups}">
<site-settings-category
selected-site="{{selectedSite}}"
current-route="{{currentRoute}}"
@@ -217,7 +219,7 @@
<template is="dom-if" name="site-details">
<settings-subpage
- page-title="[[i18n('siteSettingsSiteDetailsPageTitle')]]">
+ page-title="$i18n{siteSettingsSiteDetailsPageTitle}">
<site-details site="[[selectedSite]]"></site-details>
</settings-subpage>
</template>
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 f32e8538028..b32e2174b03 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
+++ b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -6,22 +6,10 @@
* @fileoverview
* 'settings-privacy-page' is the settings page containing privacy and
* security settings.
- *
- * Example:
- *
- * <iron-animated-pages>
- * <settings-privacy-page prefs="{{prefs}}">
- * </settings-privacy-page>
- * ... other pages ...
- * </iron-animated-pages>
*/
Polymer({
is: 'settings-privacy-page',
- behaviors: [
- I18nBehavior,
- ],
-
properties: {
/**
* Preferences state.
@@ -38,6 +26,9 @@ Polymer({
type: Object,
notify: true,
},
+
+ /** @private */
+ showClearBrowsingDataDialog_: Boolean,
},
ready: function() {
@@ -62,6 +53,15 @@ Polymer({
/** @private */
onClearBrowsingDataTap_: function() {
- this.$.pages.querySelector('settings-clear-browsing-data-dialog').open();
+ this.showClearBrowsingDataDialog_ = true;
+ },
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ onIronOverlayClosed_: function(event) {
+ if (Polymer.dom(event).rootTarget.tagName == 'SETTINGS-DIALOG')
+ this.showClearBrowsingDataDialog_ = false;
},
});
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 a6942696e2c..5daa87fe9dd 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
+++ b/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.html
@@ -11,18 +11,20 @@
<template>
<style include="settings-shared"></style>
<settings-dialog id="dialog">
- <div class="title" i18n-content="powerwashDialogTitle"></div>
+ <div class="title">$i18n{powerwashDialogTitle}</div>
<div class="body">
- <span i18n-content="powerwashDialogExplanation"></span>
- <a i18n-values="href:powerwashLearnMoreUrl"
- i18n-content="learnMore" target="_blank"></a>
+ <span>
+ $i18n{powerwashDialogExplanation}
+ <a href="$i18nRaw{powerwashLearnMoreUrl}" target="_blank">
+ $i18n{learnMore}
+ </a>
+ </span>
</div>
<div class="button-container">
<paper-button class="cancel-button" on-tap="onCancelTap_"
- id="cancel" i18n-content="cancel"></paper-button>
+ id="cancel">$i18n{cancel}</paper-button>
<paper-button class="action-button" id="powerwash"
- on-tap="onRestartTap_" i18n-content="powerwashDialogButton">
- </paper-button>
+ on-tap="onRestartTap_">$i18n{powerwashDialogButton}</paper-button>
</div>
</settings-dialog>
</template>
diff --git a/chromium/chrome/browser/resources/settings/reset_page/reset_browser_proxy.js b/chromium/chrome/browser/resources/settings/reset_page/reset_browser_proxy.js
index 4390e04a128..6c81d8bb301 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/reset_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/reset_page/reset_browser_proxy.js
@@ -29,6 +29,12 @@ cr.define('settings', function() {
*/
onShowResetProfileDialog: function() {},
+ /**
+ * Shows the settings that are about to be reset and which will be reported
+ * to Google for analysis, in a new tab.
+ */
+ showReportedSettings: function() {},
+
<if expr="chromeos">
/**
* A method to be called when the reset powerwash dialog is shown.
@@ -70,6 +76,20 @@ cr.define('settings', function() {
chrome.send('onShowResetProfileDialog');
},
+ /** @override */
+ showReportedSettings: function() {
+ cr.sendWithPromise('getReportedSettings').then(function(settings) {
+ var output = settings.map(function(entry) {
+ return entry.key + ': ' + entry.value.replace(/\n/g, ', ');
+ });
+ var win = window.open('about:blank');
+ var div = win.document.createElement('div');
+ div.textContent = output.join('\n');
+ div.style.whiteSpace = 'pre';
+ win.document.body.appendChild(div);
+ });
+ },
+
<if expr="chromeos">
/** @override */
onPowerwashDialogShow: function() {
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 be3d27f8e94..9722fc41102 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/reset_page.html
+++ b/chromium/chrome/browser/resources/settings/reset_page/reset_page.html
@@ -13,16 +13,16 @@
<div class="settings-box first two-line" id="resetProfile"
on-tap="onShowResetProfileDialog_">
<div>
- <div i18n-content="resetPageTitle"></div>
- <div class="secondary" i18n-content="resetPageDescription"></div>
+ <div>$i18n{resetPageTitle}</div>
+ <div class="secondary">$i18n{resetPageDescription}</div>
</div>
</div>
<if expr="chromeos">
<div class="settings-box two-line" id="powerwash"
on-tap="onShowPowerwashDialog_" hidden="[[!allowPowerwash_]]">
<div>
- <div i18n-content="powerwashTitle"></div>
- <div class="secondary" i18n-content="powerwashDescription"></div>
+ <div>$i18n{powerwashTitle}</div>
+ <div class="secondary">$i18n{powerwashDescription}</div>
</div>
</div>
</if>
diff --git a/chromium/chrome/browser/resources/settings/reset_page/reset_profile_banner.html b/chromium/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
index 611f7d0b43f..fd81809d25f 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
+++ b/chromium/chrome/browser/resources/settings/reset_page/reset_profile_banner.html
@@ -1,3 +1,4 @@
+<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-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
@@ -9,18 +10,19 @@
<template>
<div id="banner-content">
<div id="top-row">
- <paper-icon-button icon="clear" on-tap="onCloseTap_" id="close">
+ <paper-icon-button icon="cr:clear" on-tap="onCloseTap_" id="close">
</paper-icon-button>
</div>
<div id="main-body">
<span id="description">
- <span i18n-content="resetProfileBannerDescription"></span>
+ $i18n{resetProfileBannerDescription}
<a id="learnMore"
- i18n-values="href:resetProfileBannerLearnMoreUrl"
- i18n-content="learnMore" target="_blank"></a>
+ href="$i18nRaw{resetProfileBannerLearnMoreUrl}"
+ target="_blank">$i18n{learnMore}</a>
</span>
- <paper-button id="reset" on-tap="showDialog_"
- i18n-content="resetProfileBannerButton"></paper-button>
+ <paper-button id="reset" on-tap="showDialog_">
+ $i18n{resetProfileBannerButton}
+ </paper-button>
</div>
</div>
<template is="dom-if" if="[[showResetProfileDialog_]]">
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 36f22602b8c..f7d9c540ba2 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
@@ -1,3 +1,4 @@
+<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/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
@@ -11,31 +12,36 @@
<dom-module id="settings-reset-profile-dialog">
<link rel="import" type="css" href="reset_page_dialog.css">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ .footer a {
+ vertical-align: middle;
+ }
+ </style>
<settings-dialog id="dialog">
- <div class="title" i18n-content="resetPageTitle"></div>
+ <div class="title">$i18n{resetPageTitle}</div>
<div class="body">
- <span i18n-content="resetPageExplanation"></span>
- <a i18n-values="href:resetPageLearnMoreUrl"
- i18n-content="learnMore" target="_blank"></a>
+ <span>
+ $i18n{resetPageExplanation}
+ <a href="$i18nRaw{resetPageLearnMoreUrl}" target="_blank">
+ $i18n{learnMore}
+ </a>
+ </span>
</div>
<div class="button-container">
<paper-spinner id="resetSpinner"></paper-spinner>
<paper-button class="cancel-button" on-tap="onCancelTap_"
- id="cancel" i18n-content="cancel"></paper-button>
+ id="cancel">$i18n{cancel}</paper-button>
<paper-button class="action-button" on-tap="onResetTap_"
- id="reset" i18n-content="resetPageCommit"></paper-button>
+ id="reset">$i18n{resetPageCommit}</paper-button>
</div>
<div class="footer">
- <paper-checkbox id="sendSettings" i18n-content="resetPageFeedback"
- checked on-change="onSendSettingsChange_"></paper-checkbox>
- <div id="settings">
- <template is="dom-repeat" items="[[feedbackInfo_]]">
- <div><span>[[item.key]]</span>: <span>[[item.value]]</span></div>
- </template>
- </div>
+ <paper-checkbox id="sendSettings"
+ checked>$i18n{resetPageFeedback}</paper-checkbox>
+ <a is="action-link"
+ on-tap="onShowReportedSettingsTap_">$i18n{viewReportedSettings}</a>
</div>
</settings-dialog>
</template>
+ <link rel="import" type="css" href="chrome://resources/css/action_link.css">
<script src="reset_profile_dialog.js"></script>
</dom-module>
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 2d57d12fbc2..89eae1fdfe2 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
@@ -12,10 +12,6 @@ Polymer({
behaviors: [WebUIListenerBehavior],
- properties: {
- feedbackInfo_: String,
- },
-
/** @private {!settings.ResetBrowserProxy} */
browserProxy_: null,
@@ -26,10 +22,6 @@ Polymer({
this.addEventListener('iron-overlay-canceled', function() {
this.browserProxy_.onHideResetProfileDialog();
}.bind(this));
-
- this.addWebUIListener('feedback-info-changed', function(feedbackInfo) {
- this.feedbackInfo_ = feedbackInfo;
- }.bind(this));
},
open: function() {
@@ -53,11 +45,11 @@ Polymer({
}.bind(this));
},
- /** @private */
- onSendSettingsChange_: function() {
- // TODO(dpapad): Update how settings info is surfaced when final mocks
- // exist.
- this.$.settings.hidden = !this.$.sendSettings.checked;
- this.$.dialog.center();
+ /**
+ * Displays the settings that will be reported in a new tab.
+ * @private
+ */
+ onShowReportedSettingsTap_: function() {
+ this.browserProxy_.showReportedSettings();
},
});
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 9615ec8f39f..a67ab8d8eb1 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
@@ -1,8 +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/html/icon.html">
<link rel="import" href="chrome://md-settings/search_engines_page/search_engines_browser_proxy.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.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-icons/iron-icons.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-item/paper-item.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
@@ -10,8 +10,7 @@
<dom-module id="settings-omnibox-extension-entry">
<link rel="import" type="css" href="chrome://md-settings/search_engines_page/search_engine_entry.css">
<template>
- <style include="settings-shared"></style>
- <style>
+ <style include="settings-shared">
.name-column {
flex: 3;
}
@@ -22,28 +21,23 @@
</style>
<div id="container" class="list-item">
<div class="name-column">
- <span class="icon-container">
- <template is="dom-if" if="[[engine.iconURL]]">
- <iron-icon src="[[engine.iconURL]]"></iron-icon>
- </template>
- <template is="dom-if" if="[[!engine.iconURL]]">
- <iron-icon icon="icons:find-in-page"></iron-icon>
- </template>
- </span>
+ <span class="favicon-image"
+ style="background-image: [[getIconSet_(engine.iconURL)]]"></span>
<span class="name">[[engine.displayName]]</span>
</div>
<div class="keyword-column">[[engine.keyword]]</div>
- <paper-icon-button icon="more-vert" toggles active="{{editMenuOpened}}">
- </paper-icon-button>
- <iron-dropdown opened="{{editMenuOpened}}" horizontal-align="right"
- vertical-align="top">
- <div class="dropdown-content">
- <paper-item on-tap="onManageTap_" id="manage"
- i18n-content="searchEnginesManageExtension"></paper-item>
- <paper-item on-tap="onDisableTap_" id="disable"
- i18n-content="disable"></paper-item>
- <div>
- </iron-dropdown>
+ <paper-icon-button icon="cr:more-vert" toggles
+ active="{{editMenuOpened}}">
+ </paper-icon-button>
+ <iron-dropdown opened="{{editMenuOpened}}" horizontal-align="right"
+ vertical-align="top">
+ <div class="dropdown-content">
+ <paper-item on-tap="onManageTap_" id="manage">
+ $i18n{searchEnginesManageExtension}</paper-item>
+ <paper-item on-tap="onDisableTap_" id="disable">
+ $i18n{disable}</paper-item>
+ <div>
+ </iron-dropdown>
</div>
</template>
<script src="omnibox_extension_entry.js"></script>
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 162ce84dac5..c1a5ff1910c 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
@@ -38,4 +38,13 @@ Polymer({
closePopupMenu_: function() {
this.$$('iron-dropdown').close();
},
+
+ /**
+ * @param {string} url
+ * @return {string} A set of icon URLs.
+ * @private
+ */
+ getIconSet_: function(url) {
+ return cr.icon.getFaviconImageSet(url);
+ },
});
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 c4d7a505c6c..25b4ed3e8fa 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
@@ -12,23 +12,26 @@
<div class="title">[[dialogTitle_]]</div>
<div class="body">
<paper-input always-float-label id="searchEngine"
- i18n-values="label:searchEnginesSearchEngine;error-message:searchEnginesNotValid"
+ label="$i18n{searchEnginesSearchEngine}"
+ error-message="$i18n{searchEnginesNotValid}"
value="{{searchEngine_}}" on-focus="validate_"
on-input="validate_">
</paper-input>
<paper-input always-float-label id="keyword"
- i18n-values="label:searchEnginesKeyword;error-message:searchEnginesNotValid"
+ label="$i18n{searchEnginesKeyword}"
+ error-message="$i18n{searchEnginesNotValid}"
value="{{keyword_}}" on-focus="validate_" on-input="validate_">
</paper-input>
<paper-input always-float-label id="queryUrl"
- i18n-values="label:searchEnginesQueryURLExplanation;error-message:searchEnginesNotValid"
+ label="$i18n{searchEnginesQueryURLExplanation}"
+ error-message="$i18n{searchEnginesNotValid}"
value="{{queryUrl_}}" on-focus="validate_" on-input="validate_"
disabled$="[[model.urlLocked]]">
</paper-input>
</div>
<div class="button-container">
- <paper-button class="cancel-button" on-tap="cancel_"
- i18n-content="cancel" id="cancel"></paper-button>
+ <paper-button class="cancel-button" on-tap="cancel_" id="cancel">
+ $i18n{cancel}</paper-button>
<paper-button id="actionButton" class="action-button"
on-tap="onActionButtonTap_">
[[actionButtonText_]]
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.css b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.css
index e8a10865dfe..1cb4233966e 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.css
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.css
@@ -2,8 +2,14 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-.icon-container {
+.favicon-image {
-webkit-margin-end: 8px;
+ background-repeat: no-repeat;
+ background-size: contain;
+ display: inline-block;
+ height: 20px;
+ vertical-align: middle;
+ width: 20px;
}
.name {
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 95d61f3c860..f73d24addc7 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
@@ -1,11 +1,11 @@
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://md-settings/search_engines_page/search_engine_dialog.html">
-<link rel="import" href="chrome://md-settings/search_engines_page/search_engines_browser_proxy.html">
+<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.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-icons/iron-icons.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-item/paper-item.html">
+<link rel="import" href="chrome://md-settings/search_engines_page/search_engine_dialog.html">
+<link rel="import" href="chrome://md-settings/search_engines_page/search_engines_browser_proxy.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-search-engine-entry">
@@ -36,34 +36,28 @@
</template>
<div id="container" class="list-item">
<div class="name-column">
- <span class="icon-container">
- <template is="dom-if" if="[[engine.iconURL]]">
- <iron-icon src="[[engine.iconURL]]"></iron-icon>
- </template>
- <template is="dom-if" if="[[!engine.iconURL]]">
- <iron-icon icon="icons:find-in-page"></iron-icon>
- </template>
- </span>
+ <span class="favicon-image"
+ style="background-image: [[getIconSet_(engine.iconURL)]]"></span>
<span class="name">[[engine.displayName]]</span>
</div>
<div class="keyword-column">[[engine.keyword]]</div>
<div class="url-column">[[engine.url]]</div>
- <paper-icon-button icon="more-vert" toggles active="{{editMenuOpened}}">
- </paper-icon-button>
- <iron-dropdown opened="{{editMenuOpened}}" horizontal-align="right"
- vertical-align="top">
- <div class="dropdown-content">
- <paper-item on-tap="onMakeDefaultTap_"
- i18n-content="searchEnginesMakeDefault"
- hidden$="[[!engine.canBeDefault]]" id="makeDefault"></paper-item>
- <paper-item on-tap="onEditTap_"
- i18n-content="searchEnginesEdit"
- hidden$="[[!engine.canBeEdited]]" id="edit"></paper-item>
- <paper-item on-tap="onDeleteTap_"
- i18n-content="searchEnginesRemoveFromList"
- hidden$="[[!engine.canBeRemoved]]" id="delete"></paper-item>
- <div>
- </iron-dropdown>
+ <paper-icon-button icon="cr:more-vert" toggles
+ active="{{editMenuOpened}}">
+ </paper-icon-button>
+ <iron-dropdown opened="{{editMenuOpened}}" horizontal-align="right"
+ vertical-align="top">
+ <div class="dropdown-content">
+ <paper-item on-tap="onMakeDefaultTap_"
+ hidden$="[[!engine.canBeDefault]]" id="makeDefault">
+ $i18n{searchEnginesMakeDefault}
+ </paper-item>
+ <paper-item on-tap="onEditTap_" hidden$="[[!engine.canBeEdited]]"
+ id="edit">$i18n{searchEnginesEdit}</paper-item>
+ <paper-item on-tap="onDeleteTap_" hidden$="[[!engine.canBeRemoved]]"
+ id="delete">$i18n{searchEnginesRemoveFromList}</paper-item>
+ <div>
+ </iron-dropdown>
</div>
</template>
<script src="search_engine_entry.js"></script>
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 fd02264bc12..037dd9e8f13 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
@@ -71,4 +71,14 @@ Polymer({
closePopupMenu_: function() {
this.$$('iron-dropdown').close();
},
+
+ /**
+ * @param {?string} url The icon URL if available.
+ * @return {string} A set of icon URLs.
+ * @private
+ */
+ getIconSet_: function(url) {
+ // Force default icon, if no |engine.iconURL| is available.
+ return cr.icon.getFaviconImageSet(url || '');
+ },
});
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 267e4720515..c7334b754b5 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
@@ -4,7 +4,6 @@
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/html/action_link.html">
<link rel="import" href="chrome://md-settings/search_engines_page/search_engines_browser_proxy.html">
<link rel="import" href="chrome://md-settings/search_engines_page/search_engine_dialog.html">
<link rel="import" href="chrome://md-settings/search_engines_page/search_engines_list.html">
@@ -26,7 +25,7 @@
}
</style>
<div>
- <div class="label" i18n-content="searchEnginesDefault"></div>
+ <div class="label">$i18n{searchEnginesDefault}</div>
<settings-search-engines-list engines="[[defaultEngines]]">
</settings-search-engines-list>
</div>
@@ -34,16 +33,16 @@
<settings-search-engine-dialog></settings-search-engine-dialog>
</template>
<div>
- <div class="label" i18n-content="searchEnginesOther"></div>
+ <div class="label">$i18n{searchEnginesOther}</div>
<!-- TODO(dbeam): why does on-click work with keyboard but on-tap
doesn't? -->
<settings-search-engines-list engines="[[otherEngines]]">
- <a is="action-link" i18n-content="searchEnginesAddSearchEngine"
- on-tap="onAddSearchEngineTap_" id="addSearchEngine"></a>
+ <a is="action-link" on-tap="onAddSearchEngineTap_" id="addSearchEngine">
+ $i18n{searchEnginesAddSearchEngine}</a>
</settings-search-engines-list>
<template is="dom-if" if="[[showExtensionsList_]]">
- <div class="label" i18n-content="searchEnginesExtension"></div>
+ <div class="label">$i18n{searchEnginesExtension}</div>
<div class="extension-engines">
<template is="dom-repeat" items="[[extensions]]">
<settings-omnibox-extension-entry engine="[[item]]">
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 d89382bfa76..8d3f9115834 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.html
@@ -1,4 +1,3 @@
-<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">
@@ -44,7 +43,7 @@
section="search">
<neon-animatable id="main">
<div class="settings-box first">
- <p class="start" i18n-content="searchExplanation"></p>
+ <p class="start">$i18n{searchExplanation}</p>
<paper-dropdown-menu>
<paper-listbox class="dropdown-content"
selected="[[getSelectedSearchEngineIndex_(searchEngines_)]]"
@@ -56,13 +55,14 @@
</paper-dropdown-menu>
</div>
<div class="settings-box">
- <paper-button i18n-content="searchEnginesManage"
- on-tap="onManageSearchEnginesTap_" class="primary-button">
+ <paper-button on-tap="onManageSearchEnginesTap_"
+ class="primary-button">
+ $i18n{searchEnginesManage}
</paper-button>
</div>
</neon-animatable>
<template is="dom-if" name="search-engines">
- <settings-subpage page-title="[[i18n('searchEnginesManage')]]">
+ <settings-subpage page-title="$i18n{searchEnginesManage}">
<settings-search-engines-page></settings-search-engines-page>
</settings-subpage>
</template>
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 5851043091b..51ee6bdb07f 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.js
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.js
@@ -9,10 +9,6 @@
Polymer({
is: 'settings-search-page',
- behaviors: [
- I18nBehavior,
- ],
-
properties: {
/**
* The current active route.
diff --git a/chromium/chrome/browser/resources/settings/settings.html b/chromium/chrome/browser/resources/settings/settings.html
index 2b210fcc197..4b57e772421 100644
--- a/chromium/chrome/browser/resources/settings/settings.html
+++ b/chromium/chrome/browser/resources/settings/settings.html
@@ -1,8 +1,8 @@
<!doctype html>
-<html i18n-values="dir:textdirection;lang:language">
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
- <title i18n-content="settings"></title>
+ <title>$i18n{settings}</title>
<base href="chrome://md-settings">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://md-settings/i18n_setup.html">
@@ -15,6 +15,11 @@
<dom-module id="cr-settings">
<template>
+ <style>
+ :host {
+ color: var(--paper-grey-800);
+ }
+ </style>
<settings-prefs id="prefs" prefs="{{prefs_}}"></settings-prefs>
<settings-ui id="ui" prefs="{{prefs_}}"></settings-ui>
</template>
diff --git a/chromium/chrome/browser/resources/settings/settings_dialog.html b/chromium/chrome/browser/resources/settings/settings_dialog.html
index df72a0df54e..d923118da9f 100644
--- a/chromium/chrome/browser/resources/settings/settings_dialog.html
+++ b/chromium/chrome/browser/resources/settings/settings_dialog.html
@@ -1,5 +1,5 @@
+<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-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-dialog-behavior/paper-dialog-behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-dialog-behavior/paper-dialog-shared-styles.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
@@ -9,8 +9,9 @@
<style include="paper-dialog-shared-styles"></style>
<style>
.body-content {
- font-size: 1em;
- margin: 20px 0;
+ display: flex;
+ flex-direction: column;
+ min-height: 120px;
}
.dialog-content {
@@ -27,30 +28,46 @@
.top-row {
align-items: center;
- border-bottom: 1px solid var(--paper-grey-300);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.14);
display: flex;
- padding-bottom: 5px;
- padding-top: 5px;
+ min-height: 52px;
+ }
+
+ paper-icon-button {
+ height: 20px;
+ margin: 16px;
+ padding: 0;
+ width: 20px;
}
:host {
+ border-radius: 2px;
max-width: 800px;
- min-width: 500px;
+ min-width: 512px;
overflow: auto;
}
+ :host ::content .body,
+ :host ::content .footer,
+ :host ::content paper-button {
+ font-size: 92.86%; /* (13px / 14px) * 100 */
+ }
+
:host ::content .body {
- margin-bottom: 35px;
+ margin: 12px 0 24px 0;
}
:host ::content .button-container {
+ -webkit-padding-end: 16px;
+ -webkit-padding-start: 16px;
display: flex;
justify-content: flex-end;
+ margin-bottom: 12px;
}
:host ::content .button-container .cancel-button {
+ -webkit-margin-end: 8px;
color: var(--paper-grey-600);
- font-weight: 500;
}
:host ::content .footer {
@@ -70,20 +87,20 @@
}
:host ::content .title {
- flex: 1;
- font-size: 1.13em;
+ font-size: 114.28%; /* (16px / 14px) * 100 */
}
- :host ::content .title,
- .body-content {
+ :host ::content .body,
+ :host ::content .title {
-webkit-padding-end: 24px;
-webkit-padding-start: 24px;
+ flex: 1;
}
</style>
<div class="dialog-content">
<div class="top-row">
<content select=".title"></content>
- <paper-icon-button icon="clear" on-tap="cancel" id="close">
+ <paper-icon-button icon="cr:clear" on-tap="cancel" id="close">
</paper-icon-button>
</div>
<div class="body-content">
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 1a1cabc869c..b16250f9c37 100644
--- a/chromium/chrome/browser/resources/settings/settings_main/settings_main.html
+++ b/chromium/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -1,4 +1,5 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://md-settings/about_page/about_page.html">
<link rel="import" href="chrome://md-settings/advanced_page/advanced_page.html">
<link rel="import" href="chrome://md-settings/basic_page/basic_page.html">
@@ -7,7 +8,7 @@
<template>
<content select="paper-icon-button"></content>
<div id="pageContainer">
- <template is="dom-if" if="[[!showAdvancedPage_]]">
+ <template is="dom-if" if="[[showBasicPage_]]">
<settings-basic-page prefs="{{prefs}}" current-route="{{currentRoute}}">
</settings-basic-page>
</template>
@@ -16,6 +17,10 @@
current-route="{{currentRoute}}">
</settings-advanced-page>
</template>
+ <template is="dom-if" if="[[showAboutPage_]]">
+ <settings-about-page current-route="{{currentRoute}}">
+ </settings-about-page>
+ </template>
</div>
</template>
<script src="settings_main.js"></script>
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 766e9dde50e..a7070d055de 100644
--- a/chromium/chrome/browser/resources/settings/settings_main/settings_main.js
+++ b/chromium/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -36,15 +36,23 @@ Polymer({
observer: 'currentRouteChanged_',
},
- // If false the 'basic' page should be shown.
- showAdvancedPage_: {
- type: Boolean,
- value: false
- }
+ /** @private */
+ showAdvancedPage_: Boolean,
+
+ /** @private */
+ showBasicPage_: Boolean,
+
+ /** @private */
+ showAboutPage_: Boolean,
},
- /** @private */
- currentRouteChanged_: function(newRoute, oldRoute) {
+ /**
+ * @param {!SettingsRoute} newRoute
+ * @private
+ */
+ currentRouteChanged_: function(newRoute) {
+ this.showAboutPage_ = newRoute.page == 'about';
this.showAdvancedPage_ = newRoute.page == 'advanced';
+ this.showBasicPage_ = newRoute.page == 'basic';
},
});
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 0e6dcbea743..c8495612e11 100644
--- a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -1,24 +1,21 @@
+<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-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/av-icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/device-icons.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/image-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/iron-icons/social-icons.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-menu/paper-submenu.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
-<if expr="chromeos">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/device-icons.html">
-</if>
-
<dom-module id="settings-menu">
<template>
<style include="settings-shared">
iron-icon {
- -webkit-margin-end: 16px;
+ --iron-icon-fill-color: var(--settings-nav-grey);
+ -webkit-margin-end: 24px;
+ }
+
+ .iron-selected:not(.menu-trigger) > iron-icon {
+ fill: var(--google-blue-500);
}
.menu-trigger span {
@@ -27,15 +24,20 @@
}
paper-menu {
- background-color: var(--settings-background-color);
- color: var(--settings-nav-grey);
- font-size: 13px;
--paper-menu-selected-item: {
font-weight: 500;
};
--paper-menu-focused-item-after: {
background: none;
};
+ background: none; /* Overrides <paper-menu> default. */
+ color: var(--settings-nav-grey);
+ font-size: 13px;
+ padding: 0;
+ }
+
+ paper-submenu > div {
+ margin-top: 8px;
}
paper-submenu {
@@ -49,7 +51,6 @@
color: var(--google-blue-500);
font-weight: 500;
};
- padding: 0;
}
paper-submenu div {
@@ -60,106 +61,115 @@
font-weight: 500;
min-height: 40px;
}
+
+ .separator {
+ /* Per Alan@, this line is different from the other separator lines. */
+ border-bottom: 1px solid rgba(0, 0, 0, 0.08);
+ margin-top: 8px;
+ }
</style>
<paper-menu name="root-menu">
- <paper-submenu opened="{{basicOpened_}}" data-page="basic"
- on-tap="openPage_">
- <div class="menu-trigger">
- <span i18n-content="basicPageTitle"></span>
- <iron-icon icon="{{arrowState_(basicOpened_)}}" item-icon></iron-icon>
+ <paper-submenu data-page="basic" id="basicPage" opened="{{basicOpened_}}">
+ <div class="menu-trigger" data-section="" on-tap="openPage_">
+ <span>$i18n{basicPageTitle}</span>
+ <iron-icon icon="[[arrowState_(basicOpened_)]]"></iron-icon>
</div>
- <paper-menu class="menu-content">
+ <paper-menu attr-for-selected="data-section" class="menu-content"
+ data-page="basic" id="basicMenu">
<if expr="chromeos">
- <div>
- <iron-icon icon="device:network-wifi" item-icon></iron-icon>
- <span i18n-content="internetPageTitle"></span>
+ <div data-section="internet" on-tap="openPage_">
+ <iron-icon icon="settings:network-wifi"></iron-icon>
+ $i18n{internetPageTitle}
</div>
</if>
- <div>
- <iron-icon icon="social:people" item-icon></iron-icon>
- <span i18n-content="peoplePageTitle"></span>
+ <div data-section="people" on-tap="openPage_">
+ <iron-icon icon="settings:people"></iron-icon>
+ $i18n{peoplePageTitle}
</div>
- <div>
- <iron-icon icon="image:palette" item-icon></iron-icon>
- <span i18n-content="appearancePageTitle"></span>
+ <div data-section="appearance" on-tap="openPage_">
+ <iron-icon icon="settings:palette"></iron-icon>
+ $i18n{appearancePageTitle}
</div>
<if expr="chromeos">
- <div>
- <iron-icon icon="hardware:laptop-chromebook" item-icon></iron-icon>
- <span i18n-content="devicePageTitle"></span>
+ <div data-section="device" on-tap="openPage_">
+ <iron-icon icon="settings:laptop-chromebook"></iron-icon>
+ $i18n{devicePageTitle}
</div>
</if>
- <div>
- <iron-icon icon="search" item-icon></iron-icon>
- <span i18n-content="searchPageTitle"></span>
+ <div data-section="search" on-tap="openPage_">
+ <iron-icon icon="cr:search"></iron-icon>
+ $i18n{searchPageTitle}
</div>
<if expr="not chromeos">
- <div>
- <iron-icon icon="av:web" item-icon></iron-icon>
- <span i18n-content="defaultBrowser"></span>
+ <div data-section="defaultBrowser" on-tap="openPage_">
+ <iron-icon icon="settings:web"></iron-icon>
+ $i18n{defaultBrowser}
</div>
</if>
- <div>
- <iron-icon icon="icons:power-settings-new" item-icon></iron-icon>
- <span i18n-content="onStartup"></span>
+ <div data-section="onStartup" on-tap="openPage_">
+ <iron-icon icon="settings:power-settings-new"></iron-icon>
+ $i18n{onStartup}
</div>
</paper-menu>
</paper-submenu>
- <paper-submenu opened="{{advancedOpened_}}" data-page="advanced"
- on-tap="openPage_">
- <div class="menu-trigger">
- <span i18n-content="advancedPageTitle"></span>
- <iron-icon icon="{{arrowState_(advancedOpened_)}}" item-icon>
- </iron-icon>
+ <paper-submenu id="advancedPage" data-page="advanced"
+ opened="{{advancedOpened_}}">
+ <div class="menu-trigger" data-section="" on-tap="openPage_">
+ <span>$i18n{advancedPageTitle}</span>
+ <iron-icon icon="[[arrowState_(advancedOpened_)]]"></iron-icon>
</div>
- <paper-menu class="menu-content">
+ <paper-menu attr-for-selected="data-section" class="menu-content"
+ data-page="advanced" id="advancedMenu">
<if expr="chromeos">
- <div>
- <iron-icon icon="device:access-time" item-icon></iron-icon>
- <span i18n-content="dateTimePageTitle"></span>
+ <div data-section="dateTime" on-tap="openPage_">
+ <iron-icon icon="settings:access-time"></iron-icon>
+ $i18n{dateTimePageTitle}
</div>
</if>
- <div>
- <iron-icon icon="hardware:security" item-icon></iron-icon>
- <span i18n-content="privacyPageTitle"></span>
+ <div data-section="privacy" on-tap="openPage_">
+ <iron-icon icon="settings:security"></iron-icon>
+ $i18n{privacyPageTitle}
</div>
<if expr="chromeos">
- <div>
- <iron-icon icon="device:bluetooth" item-icon></iron-icon>
- <span i18n-content="bluetoothPageTitle"></span>
+ <div data-section="bluetooth" on-tap="openPage_">
+ <iron-icon icon="settings:bluetooth"></iron-icon>
+ $i18n{bluetoothPageTitle}
</div>
</if>
- <div>
- <iron-icon icon="icons:assignment" item-icon></iron-icon>
- <span i18n-content="passwordsAndAutofillPageTitle"></span>
+ <div data-section="passwordsAndForms" on-tap="openPage_">
+ <iron-icon icon="settings:assignment"></iron-icon>
+ $i18n{passwordsAndAutofillPageTitle}
</div>
- <div>
- <iron-icon icon="icons:language" item-icon></iron-icon>
- <span i18n-content="languagesPageTitle"></span>
+ <div data-section="languages" on-tap="openPage_">
+ <iron-icon icon="settings:language"></iron-icon>
+ $i18n{languagesPageTitle}
</div>
- <div>
- <iron-icon icon="icons:file-download" item-icon></iron-icon>
- <span i18n-content="downloadsPageTitle"></span>
+ <div data-section="downloads" on-tap="openPage_">
+ <iron-icon icon="cr:file-download">
+ </iron-icon>
+ $i18n{downloadsPageTitle}
</div>
- <div>
- <iron-icon icon="icons:accessibility" item-icon></iron-icon>
- <span i18n-content="a11yPageTitle"></span>
+ <div data-section="a11y" on-tap="openPage_">
+ <iron-icon icon="settings:accessibility">
+ </iron-icon>
+ $i18n{a11yPageTitle}
</div>
<if expr="not chromeos">
- <div>
- <iron-icon icon="icons:build" item-icon></iron-icon>
- <span i18n-content="systemPageTitle"></span>
+ <div data-section="system" on-tap="openPage_">
+ <iron-icon icon="settings:build"></iron-icon>
+ $i18n{systemPageTitle}
</div>
</if>
- <div>
- <iron-icon icon="icons:restore" item-icon></iron-icon>
- <span i18n-content="resetPageTitle"></span>
+ <div data-section="reset" on-tap="openPage_">
+ <iron-icon icon="settings:restore"></iron-icon>
+ $i18n{resetPageTitle}
</div>
</paper-menu>
</paper-submenu>
- <paper-submenu on-tap="openPage_">
- <div class="menu-trigger">
- <span i18n-content="aboutProgram"></span>
+ <div class="separator"></div>
+ <paper-submenu data-page="about">
+ <div class="menu-trigger" on-tap="openPage_" data-section="">
+ $i18n{aboutPageTitle}
</div>
</paper-submenu>
</paper-menu>
diff --git a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.js b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.js
index d701db5b5a7..7ea80a6d450 100644
--- a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.js
+++ b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.js
@@ -15,12 +15,6 @@ Polymer({
is: 'settings-menu',
properties: {
- /** @private */
- advancedOpened_: Boolean,
-
- /** @private */
- basicOpened_: Boolean,
-
/**
* The current active route.
*/
@@ -33,19 +27,25 @@ Polymer({
/** @private */
currentRouteChanged_: function() {
- var submenu = this.shadowRoot.querySelector(
- 'paper-submenu[data-page="' + this.currentRoute.page + '"]');
- if (submenu)
- submenu.opened = true;
+ // Sync URL changes to the side nav menu.
+
+ this.$.advancedPage.opened = this.currentRoute.page == 'advanced';
+ this.$.basicPage.opened = this.currentRoute.page == 'basic';
+
+ if (this.$.advancedPage.opened)
+ this.$.advancedMenu.selected = this.currentRoute.section;
+
+ if (this.$.basicPage.opened)
+ this.$.basicMenu.selected = this.currentRoute.section;
},
/** @private */
openPage_: function(event) {
- var submenuRoute = event.currentTarget.dataset.page;
+ var submenuRoute = event.currentTarget.parentNode.dataset.page;
if (submenuRoute) {
this.currentRoute = {
page: submenuRoute,
- section: '',
+ section: event.currentTarget.dataset.section,
subpage: [],
};
}
@@ -57,6 +57,6 @@ Polymer({
* @private
* */
arrowState_: function(opened) {
- return opened ? 'arrow-drop-up' : 'arrow-drop-down';
+ return opened ? 'settings:arrow-drop-up' : 'cr:arrow-drop-down';
},
});
diff --git a/chromium/chrome/browser/resources/settings/settings_page.css b/chromium/chrome/browser/resources/settings/settings_page.css
index 78d34a063d4..859ffa5b898 100644
--- a/chromium/chrome/browser/resources/settings/settings_page.css
+++ b/chromium/chrome/browser/resources/settings/settings_page.css
@@ -3,11 +3,13 @@
* found in the LICENSE file. */
:host {
+ box-sizing: border-box;
display: block;
height: 100%;
- margin: 24px auto;
+ margin: 0 auto;
max-width: 960px;
min-width: 622px;
+ padding: 24px 0;
position: relative;
width: 80%;
}
diff --git a/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.html b/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.html
index 3d1c94f2e79..ea024a52326 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/main_page_behavior.html
@@ -7,12 +7,20 @@
<style>
.expanding,
.collapsing {
- z-index: 2;
+ /* Must be lower than the paper-header-panel's z-index.
+ * See settings_ui.html. */
+ z-index: 1;
}
.expanded {
min-height: 100%;
}
+
+ .expanded.frozen {
+ /* Account for padding in settings_page.css. */
+ margin: -24px 0;
+ min-height: calc(100% + 48px);
+ }
</style>
</template>
</dom-module>
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 99dbc67c618..130a2881cdc 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
@@ -264,7 +264,6 @@ var MainPageBehaviorImpl = {
*/
playCollapseSection_: function(section) {
var card = section.$.card;
- var cardStyle = getComputedStyle(card);
this.style.margin = '';
section.$.header.hidden = false;
@@ -293,6 +292,12 @@ var MainPageBehaviorImpl = {
// but account for scroll.
var targetTop = card.getBoundingClientRect().top - this.scroller.scrollTop;
+ // Account for the section header.
+ var headerStyle = getComputedStyle(section.$.header);
+ targetTop += section.$.header.offsetHeight +
+ parseInt(headerStyle.marginBottom, 10) +
+ parseInt(headerStyle.marginTop, 10);
+
var keyframes = [{
top: startingTop + 'px',
minHeight: cardHeightStart + 'px',
@@ -304,17 +309,18 @@ var MainPageBehaviorImpl = {
var options = /** @type {!KeyframeEffectOptions} */({
duration: EXPAND_DURATION
});
- var promise = this.animateElement('section', card, keyframes, options);
- return promise;
+ return this.animateElement('section', card, keyframes, options);
},
};
+
/** @polymerBehavior */
var MainPageBehavior = [
TransitionBehavior,
MainPageBehaviorImpl
];
+
/**
* TODO(michaelpg): integrate slide animations.
* @polymerBehavior RoutableBehavior
@@ -330,12 +336,29 @@ var RoutableBehaviorImpl = {
},
/** @private */
+ scrollToSection_: function() {
+ // TODO(dschuyler): Determine whether this setTimeout can be removed.
+ // See also: https://github.com/Polymer/polymer/issues/3629
+ setTimeout(function pollForScrollHeight() {
+ // If the current section changes while we are waiting for the page to be
+ // ready, scroll to the newest requested section.
+ var element = this.getSection_(this.currentRoute.section);
+ if (!element)
+ return;
+
+ if (element.parentNode.host.scrollHeight == 0) {
+ setTimeout(pollForScrollHeight.bind(this), 100);
+ return;
+ }
+
+ element.scrollIntoView();
+ }.bind(this));
+ },
+
+ /** @private */
currentRouteChanged_: function(newRoute, oldRoute) {
- // route.section is only non-empty when the user is within a subpage.
- // When the user is not in a subpage, but on the Basic page, route.section
- // is an empty string.
- var newRouteIsSubpage = newRoute && newRoute.section;
- var oldRouteIsSubpage = oldRoute && oldRoute.section;
+ var newRouteIsSubpage = newRoute && newRoute.subpage.length;
+ var oldRouteIsSubpage = oldRoute && oldRoute.subpage.length;
if (!oldRoute && newRouteIsSubpage) {
// Allow the page to load before expanding the section. TODO(michaelpg):
@@ -357,6 +380,8 @@ var RoutableBehaviorImpl = {
var section = this.getSection_(newRoute.section);
if (section)
this.expandSection(section);
+ } else if (newRoute && newRoute.section) {
+ this.scrollToSection_();
}
},
@@ -372,6 +397,7 @@ var RoutableBehaviorImpl = {
},
};
+
/** @polymerBehavior */
var RoutableBehavior = [
MainPageBehavior,
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 574350715c0..27869cd1485 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
@@ -88,11 +88,8 @@ Polymer({
return;
}
- // route.section is only non-empty when the user is within a subpage.
- // When the user is not in a subpage, but on the Basic page, route.section
- // is an empty string.
- var newRouteIsSubpage = newRoute && newRoute.section == this.section;
- var oldRouteIsSubpage = oldRoute && oldRoute.section == this.section;
+ var newRouteIsSubpage = newRoute && newRoute.subpage.length;
+ var oldRouteIsSubpage = oldRoute && oldRoute.subpage.length;
if (newRouteIsSubpage)
this.ensureSubpageInstance_();
@@ -114,8 +111,10 @@ Polymer({
}
}
- this.$.animatedPages.selected =
- newRouteIsSubpage ? newRoute.subpage.slice(-1)[0] : 'main';
+ if (newRouteIsSubpage && newRoute.section == this.section)
+ this.$.animatedPages.selected = newRoute.subpage.slice(-1)[0];
+ else
+ this.$.animatedPages.selected = 'main';
},
/**
@@ -127,8 +126,9 @@ Polymer({
var template = Polymer.dom(this).querySelector(
'template[name="' + id + '"]');
- // Do nothing if the subpage is already stamped.
- if (template.if)
+ // Nothing to do if the subpage isn't wrapped in a <template> or the
+ // template is already stamped.
+ if (!template || template.if)
return;
// Set the subpage's id for use by neon-animated-pages.
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_router.js b/chromium/chrome/browser/resources/settings/settings_page/settings_router.js
index 8c32e900c8b..17471c9aaa3 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_router.js
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_router.js
@@ -3,6 +3,16 @@
// found in the LICENSE file.
/**
+ * @typedef {{
+ * url: string,
+ * page: string,
+ * section: string,
+ * subpage: !Array<string>,
+ * }}
+ */
+var SettingsRoute;
+
+/**
* @fileoverview
* 'settings-router' is a simple router for settings. Its responsibilities:
* - Update the URL when the routing state changes.
@@ -31,6 +41,7 @@ Polymer({
* the user is on. The previous elements are the ancestor subpages. This
* enables support for multiple paths to the same subpage. This is used by
* both the Back button and the Breadcrumb to determine ancestor subpages.
+ * @type {SettingsRoute}
*/
currentRoute: {
notify: true,
@@ -43,6 +54,7 @@ Polymer({
var route = this.routes_[i];
if (route.url == window.location.pathname) {
return {
+ url: route.url,
page: route.page,
section: route.section,
subpage: route.subpage,
@@ -72,11 +84,11 @@ Polymer({
},
- /**
- * @private
- * The 'url' property is not accessible to other elements.
- */
- routes_: [
+ /**
+ * @private {!Array<!SettingsRoute>}
+ * The 'url' property is not accessible to other elements.
+ */
+ routes_: [
{
url: '/',
page: 'basic',
@@ -84,6 +96,20 @@ Polymer({
subpage: [],
},
{
+ url: '/help',
+ page: 'about',
+ section: '',
+ subpage: [],
+ },
+<if expr="chromeos">
+ {
+ url: '/help/details',
+ page: 'about',
+ section: 'about',
+ subpage: ['detailed-build-info'],
+ },
+</if>
+ {
url: '/advanced',
page: 'advanced',
section: '',
@@ -91,6 +117,12 @@ Polymer({
},
<if expr="chromeos">
{
+ url: '/internet',
+ page: 'basic',
+ section: 'internet',
+ subpage: [],
+ },
+ {
url: '/networkDetail',
page: 'basic',
section: 'internet',
@@ -104,22 +136,46 @@ Polymer({
},
</if>
{
+ url: '/appearance',
+ page: 'basic',
+ section: 'appearance',
+ subpage: [],
+ },
+ {
url: '/fonts',
page: 'basic',
section: 'appearance',
subpage: ['appearance-fonts'],
},
{
+ url: '/defaultBrowser',
+ page: 'basic',
+ section: 'defaultBrowser',
+ subpage: [],
+ },
+ {
+ url: '/search',
+ page: 'basic',
+ section: 'search',
+ subpage: [],
+ },
+ {
url: '/searchEngines',
page: 'basic',
section: 'search',
subpage: ['search-engines'],
},
{
- url: '/searchEngines/advanced',
+ url: '/onStartup',
page: 'basic',
- section: 'search',
- subpage: ['search-engines', 'search-engines-advanced'],
+ section: 'onStartup',
+ subpage: [],
+ },
+ {
+ url: '/people',
+ page: 'basic',
+ section: 'people',
+ subpage: [],
},
<if expr="chromeos">
{
@@ -152,6 +208,12 @@ Polymer({
},
</if>
{
+ url: '/advanced',
+ page: 'advanced',
+ section: 'privacy',
+ subpage: [],
+ },
+ {
url: '/certificates',
page: 'advanced',
section: 'privacy',
@@ -302,6 +364,18 @@ Polymer({
},
<if expr="chromeos">
{
+ url: '/dateTime',
+ page: 'advanced',
+ section: 'dateTime',
+ subpage: [],
+ },
+ {
+ url: '/bluetooth',
+ page: 'advanced',
+ section: 'bluetooth',
+ subpage: [],
+ },
+ {
url: '/bluetoothAddDevice',
page: 'advanced',
section: 'bluetooth',
@@ -315,15 +389,33 @@ Polymer({
},
</if>
{
+ url: '/autofill',
+ page: 'advanced',
+ section: 'passwordsAndForms',
+ subpage: ['manage-autofill'],
+ },
+ {
url: '/passwords',
page: 'advanced',
section: 'passwordsAndForms',
+ subpage: [],
+ },
+ {
+ url: '/managePasswords',
+ page: 'advanced',
+ section: 'passwordsAndForms',
subpage: ['manage-passwords'],
},
{
url: '/languages',
page: 'advanced',
section: 'languages',
+ subpage: [],
+ },
+ {
+ url: '/manageLanguages',
+ page: 'advanced',
+ section: 'languages',
subpage: ['manage-languages'],
},
{
@@ -332,6 +424,14 @@ Polymer({
section: 'languages',
subpage: ['language-detail'],
},
+<if expr="chromeos">
+ {
+ url: '/inputMethods',
+ page: 'advanced',
+ section: 'languages',
+ subpage: ['manage-input-methods'],
+ },
+</if>
<if expr="not is_macosx">
{
url: '/editDictionary',
@@ -340,8 +440,38 @@ Polymer({
subpage: ['edit-dictionary'],
},
</if>
+ {
+ url: '/downloadsDirectory',
+ page: 'advanced',
+ section: 'downloads',
+ subpage: [],
+ },
+ {
+ url: '/accessibility',
+ page: 'advanced',
+ section: 'a11y',
+ subpage: [],
+ },
+ {
+ url: '/system',
+ page: 'advanced',
+ section: 'system',
+ subpage: [],
+ },
+ {
+ url: '/reset',
+ page: 'advanced',
+ section: 'reset',
+ subpage: [],
+ },
<if expr="chromeos">
{
+ url: '/device',
+ page: 'basic',
+ section: 'device',
+ subpage: [],
+ },
+ {
url: '/pointer-overlay',
page: 'basic',
section: 'device',
@@ -373,10 +503,12 @@ Polymer({
},
/**
- * @private
* Is called when another element modifies the route. This observer validates
* the route change against the pre-defined list of routes, and updates the
* URL appropriately.
+ * @param {!SettingsRoute} newRoute Where we're headed.
+ * @param {!SettingsRoute|undefined} oldRoute Where we've been.
+ * @private
*/
currentRouteChanged_: function(newRoute, oldRoute) {
for (var i = 0; i < this.routes_.length; ++i) {
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_section.css b/chromium/chrome/browser/resources/settings/settings_page/settings_section.css
deleted file mode 100644
index 85d6e9166f0..00000000000
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_section.css
+++ /dev/null
@@ -1,49 +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
- * Common styles for Settings pages.
- */
-:host {
- display: flex;
- flex-direction: column;
- position: relative;
-}
-
-#header {
- margin-bottom: 12px;
-}
-
-#header .title {
- color: rgb(104, 113, 116);
- font-size: 13px;
- font-weight: 500;
-}
-
-#card {
- background-color: white;
- overflow: hidden;
-}
-
-#card {
- flex: 1;
-}
-
-:host(.expanded) {
- margin-bottom: 0;
-}
-
-:host(.expanded) #header {
- display: none;
-}
-
-:host(.frozen) #card {
- position: fixed;
- width: 100%;
-}
-
-:host(.expanded.frozen) #card {
- position: relative;
-}
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_section.html b/chromium/chrome/browser/resources/settings/settings_page/settings_section.html
index ed4e2632c1b..cac8012145a 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_section.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_section.html
@@ -1,16 +1,56 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-material/paper-material.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
<dom-module id="settings-section">
- <link rel="import" type="css" href="settings_section.css">
<template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ }
+
+ #header {
+ margin-bottom: 12px;
+ }
+
+ #header .title {
+ color: rgb(104, 113, 116); /* Custom color from bettes@ */
+ font-size: 13px;
+ font-weight: 500;
+ }
+
+ #card {
+ @apply(--shadow-elevation-2dp);
+ background-color: white;
+ flex: 1;
+ overflow: hidden;
+ }
+
+ :host(.expanded) {
+ margin-bottom: 0;
+ }
+
+ :host(.expanded) #header {
+ display: none;
+ }
+
+ :host(.frozen) #card {
+ position: fixed;
+ width: 100%;
+ }
+
+ :host(.expanded.frozen) #card {
+ position: relative;
+ }
+ </style>
<div id="header">
<div class="title">{{pageTitle}}</div>
</div>
- <paper-material id="card" animated>
+ <div id="card">
<content id="content"></content>
- </paper-material>
+ </div>
</template>
<script src="settings_section.js"></script>
</dom-module>
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 fcef1ebe182..f4cf014ea46 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
@@ -1,8 +1,8 @@
<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/iron-resizable-behavior/iron-resizable-behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<dom-module id="settings-subpage">
@@ -10,14 +10,18 @@
<style include="settings-shared">
:host {
display: block;
- margin: 8px 0 16px 0;
+ }
+
+ .settings-box.first {
+ padding-bottom: 16px;
+ padding-top: 8px;
}
paper-icon-button {
/* The inner icon is 20px in size. paper-icon-button has 8px padding. */
height: 36px;
/* Centers the ripple on the icon with appropriate margin on right. */
- margin: 0 12px 0 -8px;
+ margin: 0 8px 0 -8px;
width: 36px;
}
@@ -27,7 +31,7 @@
}
</style>
<div class="settings-box first">
- <paper-icon-button icon="arrow-back" on-tap="onTapBack_">
+ <paper-icon-button icon="settings:arrow-back" on-tap="onTapBack_">
</paper-icon-button>
<h2>[[pageTitle]]</h2>
</div>
diff --git a/chromium/chrome/browser/resources/settings/settings_resources.grd b/chromium/chrome/browser/resources/settings/settings_resources.grd
index 4efe8913589..068c6fbd742 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources.grd
@@ -21,6 +21,36 @@
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
+ <structure name="IDR_SETTINGS_ABOUT_PAGE_BROWSER_PROXY_HTML"
+ file="about_page/about_page_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ABOUT_PAGE_BROWSER_PROXY_JS"
+ file="about_page/about_page_browser_proxy.js"
+ type="chrome_html"
+ flattenhtml="true" />
+ <structure name="IDR_SETTINGS_ABOUT_PAGE_JS"
+ file="about_page/about_page.js"
+ type="chrome_html"
+ flattenhtml="true" />
+ <structure name="IDR_SETTINGS_ABOUT_PAGE_HTML"
+ file="about_page/about_page.html"
+ type="chrome_html"
+ flattenhtml="true"
+ allowexternalscript="true" />
+ <if expr="chromeos">
+ <structure name="IDR_SETTINGS_DETAILED_BUILD_INFO_JS"
+ file="about_page/detailed_build_info.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_DETAILED_BUILD_INFO_HTML"
+ file="about_page/detailed_build_info.html"
+ type="chrome_html" />
+ </if>
+ <structure name="IDR_SETTINGS_ADD_SITE_DIALOG_HTML"
+ file="site_settings/add_site_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ADD_SITE_DIALOG_JS"
+ file="site_settings/add_site_dialog.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_ADVANCED_PAGE_JS"
file="advanced_page/advanced_page.js"
flattenhtml="true"
@@ -45,6 +75,13 @@
<structure name="IDR_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_JS"
file="settings_page/settings_animated_pages.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_APPEARANCE_BROWSER_PROXY_HTML"
+ file="appearance_page/appearance_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_APPEARANCE_BROWSER_PROXY_JS"
+ file="appearance_page/appearance_browser_proxy.js"
+ type="chrome_html"
+ flattenhtml="true" />
<structure name="IDR_SETTINGS_APPEARANCE_FONTS_PAGE_HTML"
file="appearance_page/appearance_fonts_page.html"
type="chrome_html"
@@ -59,10 +96,8 @@
allowexternalscript="true" />
<structure name="IDR_SETTINGS_APPEARANCE_PAGE_JS"
file="appearance_page/appearance_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_APPEARANCE_SHARED_CSS"
- file="appearance_page/appearance_shared.css"
- type="chrome_html" />
+ type="chrome_html"
+ flattenhtml="true" />
<structure name="IDR_SETTINGS_BASIC_PAGE_JS"
file="basic_page/basic_page.js"
type="chrome_html" />
@@ -98,6 +133,20 @@
<structure name="IDR_SETTINGS_STARTUP_URLS_PAGE_BROWSER_PROXY_HTML"
file="on_startup_page/startup_urls_page_browser_proxy.html"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_STARTUP_URL_DIALOG_JS"
+ file="on_startup_page/startup_url_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_STARTUP_URL_DIALOG_HTML"
+ file="on_startup_page/startup_url_dialog.html"
+ type="chrome_html"
+ allowexternalscript="true" />
+ <structure name="IDR_SETTINGS_STARTUP_URL_ENTRY_JS"
+ file="on_startup_page/startup_url_entry.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_STARTUP_URL_ENTRY_HTML"
+ file="on_startup_page/startup_url_entry.html"
+ type="chrome_html"
+ allowexternalscript="true" />
<structure name="IDR_SETTINGS_CR_SETTINGS_MAIN_CSS"
file="settings_main/settings_main.css"
type="chrome_html" />
@@ -123,9 +172,6 @@
<structure name="IDR_SETTINGS_CR_SETTINGS_PAGE_VISIBILITY_JS"
file="settings_page/settings_page_visibility.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CR_SETTINGS_SECTION_CSS"
- file="settings_page/settings_section.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_CR_SETTINGS_SECTION_HTML"
file="settings_page/settings_section.html"
type="chrome_html" />
@@ -230,6 +276,12 @@
file="certificate_manager_page/certificates_error_dialog.html"
type="chrome_html" />
</if>
+ <structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_BROWSER_PROXY_HTML"
+ file="clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_BROWSER_PROXY_JS"
+ file="clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_HTML"
file="clear_browsing_data_dialog/clear_browsing_data_dialog.html"
type="chrome_html" />
@@ -269,9 +321,6 @@
<structure name="IDR_SETTINGS_CONTROLS_RADIO_GROUP_JS"
file="controls/settings_radio_group.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CONTROLS_RADIO_GROUP_CSS"
- file="controls/settings_radio_group.css"
- type="chrome_html" />
<if expr="not chromeos">
<structure name="IDR_SETTINGS_DEFAULT_BROWSER_PAGE_CSS"
file="default_browser_page/default_browser_page.css"
@@ -286,6 +335,12 @@
type="chrome_html" />
</if>
<if expr="chromeos">
+ <structure name="IDR_SETTINGS_DEVICE_BROWSER_PROXY_HTML"
+ file="device_page/device_page_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_DEVICE_BROWSER_PROXY_JS"
+ file="device_page/device_page_browser_proxy.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_DEVICE_DISPLAY_HTML"
file="device_page/display.html"
type="chrome_html" />
@@ -390,6 +445,14 @@
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
+ <if expr="chromeos">
+ <structure name="IDR_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_PAGE_HTML"
+ file="languages_page/manage_input_methods_page.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_PAGE_JS"
+ file="languages_page/manage_input_methods_page.js"
+ type="chrome_html" />
+ </if>
<structure name="IDR_SETTINGS_LANGUAGES_MANAGE_LANGUAGES_PAGE_HTML"
file="languages_page/manage_languages_page.html"
type="chrome_html" />
@@ -420,6 +483,15 @@
<structure name="IDR_SETTINGS_PASSWORDS_AND_FORMS_PAGE_JS"
file="passwords_and_forms_page/passwords_and_forms_page.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_PASSWORDS_SHARED_CSS_HTML"
+ file="passwords_and_forms_page/passwords_shared_css.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_AUTOFILL_SECTION_HTML"
+ file="passwords_and_forms_page/autofill_section.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_AUTOFILL_SECTION_JS"
+ file="passwords_and_forms_page/autofill_section.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PASSWORDS_SECTION_HTML"
file="passwords_and_forms_page/passwords_section.html"
type="chrome_html" />
@@ -453,13 +525,25 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_MANAGE_PROFILE_BROWSER_PROXY_HTML"
file="people_page/manage_profile_browser_proxy.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_MANAGE_PROFILE_BROWSER_PROXY_JS"
file="people_page/manage_profile_browser_proxy.js"
type="chrome_html" />
</if>
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_PROFILE_INFO_BROWSER_PROXY_HTML"
+ file="people_page/profile_info_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_PROFILE_INFO_BROWSER_PROXY_JS"
+ file="people_page/profile_info_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_BROWSER_PROXY_HTML"
+ file="people_page/sync_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_BROWSER_PROXY_JS"
+ file="people_page/sync_browser_proxy.js"
+ type="chrome_html"
+ flattenhtml="true"
+ allowexternalscript="true" />
<structure name="IDR_SETTINGS_PREF_UTIL_HTML"
file="prefs/pref_util.html"
type="chrome_html" />
@@ -509,9 +593,6 @@
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
- <structure name="IDR_SETTINGS_SITE_LIST_CSS"
- file="site_settings/site_list.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_LIST_HTML"
file="site_settings/site_list.html"
type="chrome_html" />
@@ -644,19 +725,6 @@
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
- <structure name="IDR_SETTINGS_SYNC_PAGE_CSS"
- file="people_page/sync_page.css"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_SYNC_PRIVATE_API_JS"
- file="people_page/sync_private_api.js"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_SYNC_PRIVATE_API_HTML"
- file="people_page/sync_private_api.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
<structure name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY_HTML"
file="system_page/system_page_browser_proxy.html"
type="chrome_html" />
@@ -683,8 +751,11 @@
file="site_settings/website_usage_private_api.js"
type="chrome_html" />
<if expr="chromeos">
- <structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_CSS"
- file="bluetooth_page/bluetooth_device_list_item.css"
+ <structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_DIALOG_HTML"
+ file="bluetooth_page/bluetooth_device_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_DIALOG_JS"
+ file="bluetooth_page/bluetooth_device_dialog.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_HTML"
file="bluetooth_page/bluetooth_device_list_item.html"
@@ -692,48 +763,24 @@
<structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_JS"
file="bluetooth_page/bluetooth_device_list_item.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_DIALOG_CSS"
- file="bluetooth_page/bluetooth_dialog.css"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_PAGE_CSS"
- file="bluetooth_page/bluetooth_page.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_BLUETOOTH_PAGE_HTML"
file="bluetooth_page/bluetooth_page.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_BLUETOOTH_PAGE_JS"
file="bluetooth_page/bluetooth_page.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_ADD_DEVICE_DIALOG_HTML"
- file="bluetooth_page/bluetooth_add_device_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_ADD_DEVICE_DIALOG_JS"
- file="bluetooth_page/bluetooth_add_device_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_PAIR_DEVICE_DIALOG_HTML"
- file="bluetooth_page/bluetooth_pair_device_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_PAIR_DEVICE_DIALOG_JS"
- file="bluetooth_page/bluetooth_pair_device_dialog.js"
- type="chrome_html" />
<structure name="IDR_SETTINGS_DATE_TIME_PAGE_HTML"
file="date_time_page/date_time_page.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_DATE_TIME_PAGE_JS"
file="date_time_page/date_time_page.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_DETAIL_PAGE_CSS"
- file="internet_page/internet_detail_page.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_INTERNET_DETAIL_PAGE_HTML"
file="internet_page/internet_detail_page.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_INTERNET_DETAIL_PAGE_JS"
file="internet_page/internet_detail_page.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_KNOWN_NETWORKS_PAGE_CSS"
- file="internet_page/internet_known_networks_page.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_INTERNET_KNOWN_NETWORKS_PAGE_HTML"
file="internet_page/internet_known_networks_page.html"
type="chrome_html" />
@@ -746,72 +793,48 @@
<structure name="IDR_SETTINGS_INTERNET_PAGE_JS"
file="internet_page/internet_page.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_APNLIST_CSS"
- file="internet_page/network_apnlist.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_APNLIST_HTML"
file="internet_page/network_apnlist.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_APNLIST_JS"
file="internet_page/network_apnlist.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_IP_CONFIG_CSS"
- file="internet_page/network_ip_config.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_IP_CONFIG_HTML"
file="internet_page/network_ip_config.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_IP_CONFIG_JS"
file="internet_page/network_ip_config.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_NAMESERVERS_CSS"
- file="internet_page/network_nameservers.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_NAMESERVERS_HTML"
file="internet_page/network_nameservers.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_NAMESERVERS_JS"
file="internet_page/network_nameservers.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_PROPERTY_LIST_CSS"
- file="internet_page/network_property_list.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROPERTY_LIST_HTML"
file="internet_page/network_property_list.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROPERTY_LIST_JS"
file="internet_page/network_property_list.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_PROXY_CSS"
- file="internet_page/network_proxy.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_HTML"
file="internet_page/network_proxy.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_JS"
file="internet_page/network_proxy.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_PROXY_EXCLUSIONS_CSS"
- file="internet_page/network_proxy_exclusions.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_EXCLUSIONS_HTML"
file="internet_page/network_proxy_exclusions.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_EXCLUSIONS_JS"
file="internet_page/network_proxy_exclusions.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_PROXY_INPUT_CSS"
- file="internet_page/network_proxy_input.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_INPUT_HTML"
file="internet_page/network_proxy_input.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_INPUT_JS"
file="internet_page/network_proxy_input.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_SIMINFO_CSS"
- file="internet_page/network_siminfo.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_SIMINFO_HTML"
file="internet_page/network_siminfo.html"
type="chrome_html" />
@@ -824,9 +847,6 @@
<structure name="IDR_SETTINGS_NETWORK_SUMMARY_JS"
file="internet_page/network_summary.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_CSS"
- file="internet_page/network_summary_item.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_HTML"
file="internet_page/network_summary_item.html"
type="chrome_html" />
@@ -879,6 +899,15 @@
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
+ <structure name="IDR_SETTINGS_PIN_KEYBOARD_HTML"
+ file="people_page/pin_keyboard.html"
+ type="chrome_html"
+ flattenhtml="true"
+ allowexternalscript="true"/>
+ <structure name="IDR_SETTINGS_KEYBOARD_PIN_JS"
+ file="people_page/pin_keyboard.js"
+ type="chrome_html"
+ flattenhtml="true" />
<structure name="IDR_SETTINGS_USERS_PAGE_USER_LIST_JS"
file="people_page/user_list.js"
type="chrome_html" />
@@ -887,9 +916,6 @@
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
- <structure name="IDR_SETTINGS_USERS_PAGE_USER_LIST_CSS"
- file="people_page/user_list.css"
- type="chrome_html" />
<structure name="IDR_SETTINGS_USERS_PAGE_JS"
file="people_page/users_page.js"
type="chrome_html" />
@@ -898,9 +924,6 @@
type="chrome_html"
flattenhtml="true"
allowexternalscript="true" />
- <structure name="IDR_SETTINGS_USERS_PAGE_CSS"
- file="people_page/users_page.css"
- type="chrome_html" />
</if>
</structures>
</release>
diff --git a/chromium/chrome/browser/resources/settings/settings_shared_css.html b/chromium/chrome/browser/resources/settings/settings_shared_css.html
index 33e504aaa0e..001f436da70 100644
--- a/chromium/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_shared_css.html
@@ -8,16 +8,26 @@
--checkbox-spacing: 18px;
--iron-icon-fill-color: var(--paper-grey-600);
--iron-icon-height: 20px;
+ --iron-icon-spacing: 16px;
--iron-icon-width: 20px;
+ --paper-checkbox-label-color: inherit;
+ --paper-dialog-color: inherit;
--paper-icon-button: {
width: 36px;
height: 36px;
};
--paper-input-max-width: 264px;
+ --paper-item: {
+ font-size: inherit;
+ };
+ --paper-radio-button-label-color: inherit;
+ --paper-radio-group-item-padding: 0;
+
--settings-background-color: var(--paper-blue-grey-50);
--settings-secondary: {
color: var(--paper-grey-600);
font-weight: 400;
+ margin-top: 4px;
};
--settings-error-color: var(--paper-red-700);
--settings-hover-color: var(--google-grey-300);
@@ -25,28 +35,31 @@
/* Some colors use non-MD colors. These custom colors are specified by
* UX design (bettes@). */
--settings-nav-grey: rgb(90, 90, 90);
+
+ --settings-row-min-height: 40px;
+ --settings-separator-line: 1px solid rgba(0, 0, 0, 0.06);
+
--settings-title-bar-background-color: rgb(52, 73, 94);
--settings-title-bar-color: rgb(255, 255, 255);
+ --settings-title-search-color: rgb(192, 199, 205);
}
h2 {
@apply(--layout-center);
- color: var(--paper-grey-500);
display: flex;
font-size: 100%;
font-weight: 500;
margin: 0;
- min-height: 40px;
+ min-height: var(--settings-row-min-height);
}
- iron-icon[icon=check],
- iron-icon[icon=done] {
+ iron-icon[icon='cr:check'],
+ iron-icon[icon='settings:done'] {
--iron-icon-fill-color: var(--google-green-500);
}
paper-button {
margin: 0;
- min-width: auto;
}
paper-button[toggles][active] {
@@ -82,7 +95,7 @@
paper-button.secondary-button {
--paper-button: {
- color: var(--paper-grey-700);
+ color: var(--paper-grey-600);
text-decoration: none;
font-weight: 500;
};
@@ -95,11 +108,26 @@
};
}
+ paper-checkbox {
+ --paper-checkbox-checked-color: var(--google-blue-500);
+ --paper-checkbox-label-spacing: var(--checkbox-spacing);
+ --paper-checkbox-size: var(--checkbox-size);
+ --paper-checkbox-unchecked-color: var(--paper-grey-600);
+ -webkit-margin-start: var(--checkbox-margin-start);
+ }
+
paper-radio-button {
+ @apply(--layout-center);
--paper-radio-button-checked-color: var(--google-blue-500);
--paper-radio-button-label-spacing: 18px;
--paper-radio-button-unchecked-color: var(--paper-grey-600);
-webkit-margin-start: 2px;
+ display: flex;
+ min-height: 40px;
+ }
+
+ paper-radio-group {
+ width: 100%;
}
.text-elide {
@@ -120,17 +148,21 @@
.action-button {
background: var(--google-blue-500);
color: white;
- font-weight: 500;
}
.action-button[disabled] {
opacity: .25; /* TODO(dbeam): check this value with bettes. */
}
+ .action-button,
+ .cancel-button {
+ font-weight: 500;
+ }
+
.list-frame {
@apply(--layout-center);
-webkit-padding-end: 20px;
- -webkit-padding-start: 48px;
+ -webkit-padding-start: 56px;
display: block;
padding-bottom: 0;
padding-top: 0;
@@ -144,12 +176,12 @@
.list-item {
@apply(--layout-center);
display: flex;
- min-height: 40px;
+ min-height: var(--settings-row-min-height);
padding: 0;
}
.list-item.underbar {
- border-bottom: 1px solid var(--paper-grey-300);
+ border-bottom: var(--settings-separator-line);
}
.list-item.selected {
@@ -162,7 +194,7 @@
.list-item > .middle {
flex: 1;
- margin: 8px 12px;
+ margin: 8px 16px;
overflow: hidden;
white-space: nowrap;
}
@@ -186,13 +218,14 @@
.settings-box {
@apply(--layout-center);
- border-top: 1px solid var(--paper-grey-300);
+ border-top: var(--settings-separator-line);
display: flex;
- min-height: 40px;
+ min-height: var(--settings-row-min-height);
padding: 0 20px;
}
- .settings-box.first {
+ .settings-box.first,
+ .settings-box.continuation {
border-top: none;
}
@@ -230,7 +263,7 @@
* +-------------------------------------------------------+
*/
.settings-box .secondary-action {
- -webkit-border-start: 1px solid var(--paper-grey-300);
+ -webkit-border-start: var(--settings-separator-line);
-webkit-padding-start: 20px;
}
@@ -239,12 +272,8 @@
padding: 8px;
}
- .vertical-list > div:first-of-type {
- border-top: none;
- }
-
- .vertical-list > div {
- border-top: 1px solid var(--paper-grey-300);
+ .vertical-list > *:not(:first-of-type) {
+ border-top: var(--settings-separator-line);
}
.settings-checkbox-spacer {
@@ -253,6 +282,20 @@
var(--checkbox-size) +
var(--checkbox-spacing));
}
+
+ /* Keep the slider color consistent throughout the range. */
+ paper-slider.always-on {
+ --paper-slider-knob-start-border-color: var(--google-blue-700);
+ --paper-slider-knob-start-color: var(--google-blue-700);
+ --paper-slider-pin-start-color: var(--google-blue-700);
+ }
+
+ .favicon-image {
+ background-repeat: no-repeat;
+ background-size: contain;
+ height: 16px;
+ width: 16px;
+ }
</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 e7fb6486d56..5c58e292599 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html
+++ b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -1,8 +1,9 @@
+<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-drawer-panel/paper-drawer-panel.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-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-styles/typography.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-toolbar/paper-toolbar.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/iron-icon/iron-icon.html">
@@ -24,52 +25,198 @@
background-color: var(--settings-background-color);
}
- iron-icon {
- --iron-icon-fill-color: var(--settings-title-bar-color);
+ paper-drawer-panel {
+ @apply(--layout-center);
+ --paper-drawer-panel-drawer-container: {
+ background: none; /* Remove default background styling. */
+ };
+ position: relative;
}
- paper-toolbar {
- @apply(--shadow-elevation-4dp);
- --paper-toolbar-title: {
- font-size: 123.08%;
+ #drawer {
+ --paper-header-panel-shadow: {
+ /* Polymer's style transformation chokes on :host() and :not() (and
+ * many other things, it seems). Just hide the built-in shadow and
+ * duplicate its style. */
+ display: none;
};
- background-color: var(--settings-title-bar-background-color);
- min-height: 56px;
- position: relative;
- z-index: 10;
+ /* Explicitly set this so that transitions work and look good. */
+ background-color: var(--settings-background-color);
}
- paper-drawer-panel {
+ #drawer .toolbar::after {
+ box-shadow: inset 0px 5px 6px -3px rgba(0, 0, 0, 0.4);
+ content: '';
+ display: block;
+ height: 6px;
+ }
+
+ #drawer,
+ #drawer .toolbar,
+ #drawer .toolbar::after {
+ transition: background-color .3s, color .3s, height .3s;
+ }
+
+ :host(:not(.narrowing)) [narrow] #drawer,
+ :host(:not(.narrowing)) [narrow] #drawer .toolbar,
+ :host(:not(.narrowing)) [narrow] #drawer .toolbar::after {
+ transition: none; /* Transition only when removing [narrow]. */
+ }
+
+ :host(:not(.narrowing)) [narrow] #drawer,
+ :host(:not(.narrowing)) [narrow] #drawer .toolbar {
+ background-color: white;
+ }
+
+ :host(:not(.narrowing)) [narrow] #drawer .toolbar {
+ color: var(--settings-nav-grey);
+ }
+
+ :host(:not(.narrowing)) [narrow] #drawer .toolbar::after {
+ border-bottom: var(--settings-separator-line);
+ height: 0;
+ }
+
+ paper-icon-button {
+ --iron-icon-fill-color: var(--settings-title-bar-color);
+ }
+
+ paper-icon-button[suffix] {
+ --iron-icon-fill-color: var(--settings-title-search-color);
+ height: 32px; /* After padding, the icon size is 16px. */
+ width: 32px;
+ }
+
+ paper-input {
@apply(--layout-center);
- --paper-drawer-panel-left-drawer-container: {
- background-color: var(--settings-background-color);
- margin-top: 8px;
+ --paper-input-container: {
+ padding-top: 0;
};
- --paper-drawer-panel-right-drawer-container: {
- background-color: var(--settings-background-color);
- margin-top: 8px;
+ --paper-input-container-color: var(--settings-title-search-color);
+ --paper-input-container-focus-color: var(--settings-title-search-color);
+ --paper-input-container-input: {
+ font-size: 81.25%; /* go to 13px from 16px */
+ position: relative;
+ top: 3px; /* Special positioning needed for UX design. */
};
- position: relative;
+
+ /*
+ * The button in the input suffix needs special positioning for the UX
+ * design. The hit box extends right and down from the paper-input
+ * underline.
+ */
+ --paper-input-suffix: {
+ left: 8px;
+ line-height: 16px;
+ position: relative;
+ top: 4px;
+ };
+ --paper-input-container-input-color: var(--settings-title-bar-color);
+ --paper-input-container-label: {
+ font-size: 81.25%; /* go to 13px from 16px */
+ top: 3px; /* Special positioning needed for UX design. */
+ };
+ --paper-input-max-width: 200px;
+ }
+
+ /* These header elements must create stacking contexts when a section is
+ * expanding to show a sub-page. (It's simpler for them to always create
+ * these stacking contexts, so we do.) But for the overlay to work, the
+ * paper-header-panel's other descendents (rooted at settings-main) must
+ * never create stacking contexts while a dialog is showing. This means
+ * we cannot animate a section expanding/collapsing while a dialog is
+ * shown (which makes good UX sense anyway.) I have discovered a truly
+ * non-marvellous proof of this, which this comment cannot contain:
+ * https://goo.gl/CCzijE */
+ paper-header-panel[main] paper-toolbar {
+ z-index: 2;
+ }
+
+ paper-header-panel[main] {
+ --paper-header-panel-shadow: {
+ z-index: 2;
+ };
+ }
+
+ /* The paper-drawer-panel implementation gives the drawer a stacking
+ * context, so its z-index should at least equal the main panel's. */
+ paper-drawer-panel[narrow] {
+ --paper-drawer-panel-drawer-container: {
+ z-index: 2;
+ };
+ }
+
+ paper-toolbar {
+ --paper-toolbar-height: 56px;
+ --paper-toolbar-sm-height: 56px;
+ --paper-toolbar-content: {
+ font-size: 123.08%; /* go to 16px from 13px */
+ };
+ --paper-toolbar: {
+ background-color: var(--settings-title-bar-background-color);
+ };
+ }
+
+ /* Prevent paper-toolbar from setting the margin-right to 24px. */
+ paper-icon-button#menu-button {
+ flex-shrink: 0;
+ /* TODO(dschuyler): this margin is on the right regardless of language
+ * direction (e.g. rtl). Make a patch for paper-toolbar in Polymer. */
+ margin-right: 0;
+ }
+
+ .heading {
+ -webkit-margin-start: 8px;
+ }
+
+ paper-drawer-panel:not([narrow]) #main-title {
+ display: none;
+ }
+
+ paper-icon-button[toggles]:not([active]) + #search-input {
+ display: none;
}
- settings-main paper-icon-button {
- z-index: 10;
+ .last {
+ display: flex;
+ justify-content: flex-end;
+ width: 100%;
}
</style>
<settings-router current-route="{{currentRoute}}"
current-route-titles="{{currentRouteTitles}}">
</settings-router>
- <paper-toolbar>
- <div class="title" i18n-content="settings"></div>
- <!-- TODO(dschuyler): implement internal search. -->
- <iron-icon icon="md-settings-icons:search"></iron-icon>
- </paper-toolbar>
- <paper-drawer-panel drawer-width="256px" id="panel">
- <settings-menu drawer class="flex" current-route="{{currentRoute}}">
- </settings-menu>
- <settings-main main prefs="{{prefs}}" current-route="{{currentRoute}}">
- <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
- </settings-main>
+ <paper-drawer-panel drawer-width="256px" id="panel" narrow="{{isNarrow_}}"
+ responsive-width="900px">
+ <paper-header-panel drawer id="drawer">
+ <paper-toolbar class="toolbar">
+ <div class="heading flex">$i18n{settings}</div>
+ </paper-toolbar>
+ <settings-menu current-route="{{currentRoute}}">
+ </settings-menu>
+ </paper-header-panel>
+ <paper-header-panel main>
+ <paper-toolbar class="toolbar">
+ <paper-icon-button icon="settings:menu" id="menu-button"
+ paper-drawer-toggle>
+ </paper-icon-button>
+ <div class="heading" id="main-title">
+ $i18n{settings}
+ </div>
+ <div class="last">
+ <paper-icon-button icon="cr:search" toggles>
+ </paper-icon-button>
+ <paper-input id="search-input" label="$i18n{internalSearch}"
+ no-label-float>
+ <!-- TODO(dschuyler): implement internal search. -->
+ <paper-icon-button suffix icon="cr:cancel">
+ </paper-icon-button>
+ </paper-input>
+ </div>
+ </paper-toolbar>
+ <settings-main prefs="{{prefs}}" current-route="{{currentRoute}}">
+ </settings-main>
+ </paper-header-panel>
</paper-drawer-panel>
</template>
<script src="settings_ui.js"></script>
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 9e5a531d3d0..ebd72d3c929 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -27,6 +27,29 @@ Polymer({
},
},
+ listeners: {
+ 'iron-select': 'onIronSelect_',
+ 'paper-responsive-change': 'onPaperResponsiveChange_',
+ },
+
+ /**
+ * @param {!CustomEvent} e
+ * @private
+ */
+ onIronSelect_: function(e) {
+ if (Polymer.dom(e).path.indexOf(this.$.panel) >= 0)
+ this.classList.remove('narrowing');
+ },
+
+ /**
+ * @param {!CustomEvent} e
+ * @private
+ */
+ onPaperResponsiveChange_: function(e) {
+ if (Polymer.dom(e).rootTarget == this.$.panel)
+ this.classList.toggle('narrowing', e.detail.narrow);
+ },
+
/** @private */
directionDelegateChanged_: function() {
this.$.panel.rightDrawer = this.directionDelegate.isRtl();
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
new file mode 100644
index 00000000000..51314e28932
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.html
@@ -0,0 +1,30 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://md-settings/i18n_setup.html">
+<link rel="import" href="chrome://md-settings/settings_dialog.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+
+<dom-module id="add-site-dialog">
+ <template>
+ <style include="settings-shared"></style>
+ <settings-dialog id="dialog">
+ <div class="title">$i18n{addSiteHeader}</div>
+ <div class="body">
+ <span class="start">$i18n{addSite}</span>
+ <paper-input type="text" id="site" autofocus
+ value="{{site_}}" on-input="validate_"></paper-input>
+ </div>
+ <div class="button-container">
+ <paper-button class="cancel-button" dialog-dismiss>
+ $i18n{cancel}
+ </paper-button>
+ <paper-button class="action-button" id="add"
+ on-tap="onAddTap_" disabled>
+ $i18n{add}
+ </paper-button>
+ </div>
+ </settings-dialog>
+ </template>
+ <script src="add_site_dialog.js"></script>
+</dom-module>
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
new file mode 100644
index 00000000000..8abb0a7b658
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/site_settings/add_site_dialog.js
@@ -0,0 +1,65 @@
+// 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
+ * 'add-site-dialog' provides a dialog to add exceptions for a given Content
+ * Settings category.
+ */
+Polymer({
+ is: 'add-site-dialog',
+
+ behaviors: [SiteSettingsBehavior],
+
+ properties: {
+ /**
+ * The site to add an exception for.
+ * @private
+ */
+ site_: String,
+ },
+
+ /** Opens the dialog. */
+ open: function() {
+ this.$.dialog.open();
+ },
+
+ /**
+ * Validates that the pattern entered is valid.
+ * @private
+ */
+ validate_: function() {
+ var pattern = this.addPatternWildcard_(this.site_);
+ this.browserProxy.isPatternValid(pattern).then(function(isValid) {
+ this.$.add.disabled = !isValid;
+ }.bind(this));
+ },
+
+ /**
+ * Adds the wildcard prefix to a pattern string.
+ * @param {string} pattern The pattern to add the wildcard to.
+ * @return {string} The resulting pattern.
+ * @private
+ */
+ addPatternWildcard_: function(pattern) {
+ if (pattern.startsWith('http://'))
+ return pattern.replace('http://', 'http://[*.]');
+ else if (pattern.startsWith('https://'))
+ return pattern.replace('https://', 'https://[*.]');
+ else
+ return '[*.]' + pattern;
+ },
+
+ /**
+ * The tap handler for the Add [Site] button (adds the pattern and closes
+ * the dialog).
+ * @private
+ */
+ onAddTap_: function() {
+ var pattern = this.addPatternWildcard_(this.site_);
+ this.setCategoryPermissionForOrigin(
+ pattern, pattern, this.category, settings.PermissionValues.ALLOW);
+ this.$.dialog.close();
+ },
+});
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 6bd41c03590..e3ff72059bf 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
@@ -69,6 +69,7 @@
'target_name': 'site_settings_behavior',
'dependencies': [
'<(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',
'<(EXTERNS_GYP):settings_private',
'constants',
diff --git a/chromium/chrome/browser/resources/settings/site_settings/constants.js b/chromium/chrome/browser/resources/settings/site_settings/constants.js
index 55f871efa94..33d469f7cee 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/constants.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/constants.js
@@ -4,11 +4,11 @@
cr.define('settings', function() {
/**
- * The possible contentSettingsTypes (the ones we currently support
- * configuring in the UI). This is a subset of the constants found under
- * content_setttings_types.h and the values should be kept in sync.
- * TODO(finnur): When all categories have been implemented we can just
- * generate these constants from content_setttings_types.h.
+ * All possible contentSettingsTypes that we currently support configuring in
+ * the UI. Both top-level categories and content settings that represent
+ * individual permissions under Site Details should appear here. This is a
+ * subset of the constants found under content_setttings_types.h and the
+ * values should be kept in sync.
* @enum {number}
*/
var ContentSettingsTypes = {
@@ -24,22 +24,14 @@ cr.define('settings', function() {
};
/**
- * Contains the possible values for a given contentSettingsType.
- * @enum {number}
- */
- var PermissionValues = {
- ALLOW: 1,
- BLOCK: 2,
- ASK: 3,
- };
-
- /**
* Contains the possible string values for a given contentSettingsType.
* @enum {string}
*/
- var PermissionStringValues = {
+ var PermissionValues = {
+ DEFAULT: 'default',
ALLOW: 'allow',
BLOCK: 'block',
+ ASK: 'ask',
};
/**
@@ -50,14 +42,13 @@ cr.define('settings', function() {
/**
* An invalid subtype value.
- * @const {number}
+ * @const {string}
*/
- var INVALID_CATEGORY_SUBTYPE = -1;
+ var INVALID_CATEGORY_SUBTYPE = '';
return {
ContentSettingsTypes: ContentSettingsTypes,
PermissionValues: PermissionValues,
- PermissionStringValues: PermissionStringValues,
ALL_SITES: ALL_SITES,
INVALID_CATEGORY_SUBTYPE: INVALID_CATEGORY_SUBTYPE,
};
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details.css b/chromium/chrome/browser/resources/settings/site_settings/site_details.css
index 5bc14097827..f82b7a260a2 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.css
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.css
@@ -3,14 +3,19 @@
* found in the LICENSE file. */
:host {
+ -webkit-margin-start: 4px;
display: block;
}
+.origin-box {
+ margin-bottom: 20px;
+ margin-top: 35px;
+}
+
.origin {
+ -webkit-margin-start: 10px;
font-size: 110%;
font-weight: 500;
- margin-bottom: 20px;
- margin-top: 35px;
}
.reset-button {
@@ -19,4 +24,11 @@
#storage {
-webkit-padding-end: 0;
-} \ No newline at end of file
+}
+
+.website-icon {
+ background-repeat: no-repeat;
+ background-size: contain;
+ height: 16px;
+ width: 16px;
+}
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 c029fb86f63..b1008c8e101 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.html
@@ -2,6 +2,7 @@
<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-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://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<link rel="import" href="chrome://md-settings/site_settings/constants.html">
<link rel="import" href="chrome://md-settings/site_settings/site_details_permission.html">
@@ -13,16 +14,18 @@
<template>
<style include="settings-shared"></style>
<div class="settings-box block">
- <div class="origin">[[site.origin]]</div>
- <h2 i18n-content="siteSettingsUsage" id="usage"
- hidden$="[[!storedData_]]"></h2>
+ <div class="horizontal layout origin-box">
+ <div class="website-icon" style$="[[computeSiteIcon(site)]]"></div>
+ <div class="origin flex">[[site.originForDisplay]]</div>
+ </div>
+ <h2 id="usage" hidden$="[[!storedData_]]">$i18n{siteSettingsUsage}</h2>
<paper-item id="storage" hidden$="[[!storedData_]]">
<div class="flex">[[storedData_]]</div>
- <paper-icon-button icon="delete"
+ <paper-icon-button icon="settings:delete"
on-tap="onClearStorage_"
- i18n-values="alt:siteSettingsDelete"></paper-icon-button>
+ alt="$i18n{siteSettingsDelete}"></paper-icon-button>
</paper-item>
- <h2 i18n-content="siteSettingsPermissions"></h2>
+ <h2>$i18n{siteSettingsPermissions}</h2>
<site-details-permission site="[[site]]" id="cookies"
category="{{ContentSettingsTypes.COOKIES}}">
</site-details-permission>
@@ -47,10 +50,9 @@
<site-details-permission site="[[site]]" id="mic"
category="{{ContentSettingsTypes.MIC}}">
</site-details-permission>
- <paper-button
- on-tap="onClearAndReset_"
- raised i18n-content="siteSettingsClearAndReset"
- class="reset-button"></paper-button>
+ <paper-button on-tap="onClearAndReset_" raised class="reset-button">
+ $i18n{siteSettingsClearAndReset}
+ </paper-button>
</div>
<website-usage-private-api id="usageApi"
website-data-usage="{{storedData_}}"
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details.js b/chromium/chrome/browser/resources/settings/site_settings/site_details.js
index 5fa776485ed..980dc6e3b24 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.js
@@ -48,7 +48,8 @@ Polymer({
* Handler for when the origin changes.
*/
onSiteChanged_: function() {
- var url = new URL(this.site.origin);
+ // Using originForDisplay avoids the [*.] prefix that some exceptions use.
+ var url = new URL(this.ensureUrlHasScheme(this.site.originForDisplay));
this.$.usageApi.fetchUsageTotal(url.hostname);
},
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 728fe930537..4e3258f7d8b 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
@@ -1,15 +1,13 @@
<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/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/av-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-icons/social-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu.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-listbox/paper-listbox.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://md-settings/i18n_setup.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+<link rel="import" href="chrome://md-settings/site_settings/constants.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_behavior.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_prefs_browser_proxy.html">
@@ -28,11 +26,18 @@
</div>
<div class="permission-list">
<paper-dropdown-menu>
- <paper-menu id="permission" class="dropdown-content"
- on-iron-activate="onPermissionMenuIronActivate_">
- <paper-item id="allow">[[i18n_.allowAction]]</paper-item>
- <paper-item id="block">[[i18n_.blockAction]]</paper-item>
- </paper-menu>
+ <paper-listbox id="permission" class="dropdown-content"
+ on-iron-activate="onPermissionMenuIronActivate_"
+ attr-for-selected="data-permission-value">
+ <paper-item id="allow"
+ data-permission-value$="[[PermissionValues.ALLOW]]">
+ [[i18n_.allowAction]]
+ </paper-item>
+ <paper-item id="block"
+ data-permission-value$="[[PermissionValues.BLOCK]]">
+ [[i18n_.blockAction]]
+ </paper-item>
+ </paper-listbox>
</paper-dropdown-menu>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js
index 5a3fa05f9b5..7ac2f6f5928 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js
@@ -35,6 +35,7 @@ Polymer({
/** @override */
attached: function() {
+ this.PermissionValues = settings.PermissionValues;
this.addWebUIListener('contentSettingSitePermissionChanged',
this.sitePermissionChanged_.bind(this));
},
@@ -47,13 +48,11 @@ Polymer({
siteChanged_: function(site) {
this.$.details.hidden = true;
- var prefsProxy = settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
- prefsProxy.getExceptionList(this.category).then(function(exceptionList) {
+ this.browserProxy.getExceptionList(this.category).then(
+ function(exceptionList) {
for (var i = 0; i < exceptionList.length; ++i) {
if (exceptionList[i].origin == site.origin) {
- // TODO(finnur): Convert to use attrForSelected.
- this.$.permission.selected = exceptionList[i].setting ==
- settings.PermissionStringValues.ALLOW ? 0 : 1;
+ this.$.permission.selected = exceptionList[i].setting;
this.$.details.hidden = false;
}
}
@@ -71,6 +70,7 @@ Polymer({
// TODO(finnur): Send down the full SiteException, not just a string.
this.siteChanged_({
origin: site,
+ originForDisplay: '',
embeddingOrigin: '',
setting: '',
source: '',
@@ -88,16 +88,11 @@ Polymer({
/**
* Handles the category permission changing for this origin.
- * @param {!{detail: !{item: !{innerText: string}}}} event
+ * @param {!{detail: !{item: !{dataset: !{permissionValue: string}}}}} event
*/
onPermissionMenuIronActivate_: function(event) {
- // TODO(finnur): Compare with event.detail.item.dataset.permission directly
- // once attrForSelected is in use.
- var action = event.detail.item.innerText;
- var value = (action == this.i18n_.allowAction) ?
- settings.PermissionValues.ALLOW :
- settings.PermissionValues.BLOCK;
+ var value = event.detail.item.dataset.permissionValue;
this.setCategoryPermissionForOrigin(
- this.site.origin, '', value, this.category);
+ this.site.origin, '', this.category, value);
},
});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_list.css b/chromium/chrome/browser/resources/settings/site_settings/site_list.css
deleted file mode 100644
index f0b3678cf36..00000000000
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.css
+++ /dev/null
@@ -1,20 +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. */
-
-:host {
- display: block;
-}
-
-.site-header {
- width: 100%;
-}
-
-.site-list {
- -webkit-margin-end: -16px;
-}
-
-.origin {
- --paper-item-body-two-line-min-height: 0;
- -webkit-margin-start: 12px;
-}
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 643f85f8546..9a5286f30ca 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list.html
@@ -1,64 +1,66 @@
+<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/classes/iron-flex-layout.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-icons/communication-icons.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-item/paper-item.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item-body.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-menu/paper-submenu.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu-button/paper-menu-button.html">
-<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<link rel="import" href="chrome://md-settings/site_settings/constants.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_behavior.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_prefs_browser_proxy.html">
<dom-module id="settings-site-list">
- <link rel="import" type="css" href="site_list.css">
<template>
- <style include="settings-shared"></style>
- <paper-submenu id="category" hidden on-paper-submenu-open="onToggle_"
- on-paper-submenu-close="onToggle_">
- <paper-item class="menu-trigger" hidden$="[[allSites]]">
- <div class="site-header horizontal layout">
- <div class="flex" id="header"
- >[[computeSiteListHeader_(sites, categoryEnabled)]]</div>
- <iron-icon id="icon" icon="icons:expand-more"></iron-icon>
+ <style include="settings-shared">
+ paper-menu-button {
+ left: 8px;
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+ <paper-submenu id="category" hidden
+ on-paper-submenu-open="onToggle_" on-paper-submenu-close="onToggle_">
+ <div class="menu-trigger settings-box" hidden$="[[allSites]]">
+ <div class="flex" id="header">
+ [[computeSiteListHeader_(sites, categoryEnabled)]]
</div>
- </paper-item>
+ <iron-icon id="icon" icon="cr:expand-more"></iron-icon>
+ </div>
- <paper-menu class="menu-content" id="listContainer">
+ <div class="list-frame menu-content vertical-list" id="listContainer">
<template is="dom-repeat" items="[[sites]]">
- <div class="site-list horizontal layout center">
- <paper-item class="flex">
- <iron-icon icon="[[computeSiteIcon_(item)]]" item-icon>
- </iron-icon>
- <paper-item-body two-line on-tap="onOriginTap_" class="origin">
- <div>[[item.origin]]</div>
- <div secondary>[[item.embeddingOriginForDisplay]]</div>
- </paper-item-body>
-
- <paper-menu-button hidden$="[[allSites]]">
- <paper-icon-button icon="menu"
- class="dropdown-trigger"></paper-icon-button>
- <paper-menu id="actionMenu" class="dropdown-content"
- on-iron-activate="onActionMenuIronActivate_">
- <paper-item value="[[actions_.ALLOW]]"
- hidden="[[!showAllowAction_]]"
- >[[i18n_.allowAction]]</paper-item>
- <paper-item value="[[actions_.BLOCK]]"
- hidden="[[!showBlockAction_]]"
- >[[i18n_.blockAction]]</paper-item>
- <paper-item value="[[actions_.RESET]]"
- >[[i18n_.resetAction]]</paper-item>
- </paper-menu>
- </paper-menu-button>
- </paper-item>
+ <div class="list-item underscore">
+ <div class="favicon-image" style$="[[computeSiteIcon(item)]]"
+ on-tap="onOriginTap_"></div>
+ <div class="middle" on-tap="onOriginTap_">
+ <div>[[item.originForDisplay]]</div>
+ <div class="secondary">[[item.embeddingOriginForDisplay]]</div>
+ </div>
+ <paper-menu-button hidden$="[[allSites]]">
+ <paper-icon-button icon="settings:more-vert"
+ class="dropdown-trigger">
+ </paper-icon-button>
+ <paper-menu id="actionMenu" class="dropdown-content"
+ on-iron-activate="onActionMenuIronActivate_">
+ <paper-item value="[[actions_.ALLOW]]"
+ hidden="[[!showAllowAction_]]">
+ [[i18n_.allowAction]]
+ </paper-item>
+ <paper-item value="[[actions_.BLOCK]]"
+ hidden="[[!showBlockAction_]]">
+ [[i18n_.blockAction]]
+ </paper-item>
+ <paper-item value="[[actions_.RESET]]">
+ [[i18n_.resetAction]]
+ </paper-item>
+ </paper-menu>
+ </paper-menu-button>
</div>
</template>
-
- </paper-menu>
+ </div>
</paper-submenu>
</template>
<script src="site_list.js"></script>
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 e724ab81998..d05439a28cf 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list.js
@@ -50,11 +50,11 @@ Polymer({
/**
* The type of category this widget is displaying data for. Normally
- * either ALLOW or BLOCK, representing which sites are allowed or blocked
- * respectively.
+ * either 'allow' or 'block', representing which sites are allowed or
+ * blocked respectively.
*/
categorySubtype: {
- type: Number,
+ type: String,
value: settings.INVALID_CATEGORY_SUBTYPE,
},
@@ -160,7 +160,7 @@ Polymer({
this.browserProxy_.getExceptionList(this.category).then(
function(exceptionList) {
var allowExists = exceptionList.some(function(exception) {
- return exception.setting == settings.PermissionStringValues.ALLOW;
+ return exception.setting == settings.PermissionValues.ALLOW;
});
if (allowExists)
return;
@@ -187,9 +187,9 @@ Polymer({
*/
onToggle_: function(e) {
if (this.$.category.opened)
- this.$.icon.icon = 'icons:expand-less';
+ this.$.icon.icon = 'cr:expand-less';
else
- this.$.icon.icon = 'icons:expand-more';
+ this.$.icon.icon = 'cr:expand-more';
},
/**
@@ -250,13 +250,16 @@ Polymer({
appendSiteList_: function(sites, exceptionList) {
for (var i = 0; i < exceptionList.length; ++i) {
if (this.category != settings.ALL_SITES) {
+ if (exceptionList[i].setting == settings.PermissionValues.DEFAULT)
+ continue;
+
// Filter out 'Block' values if this list is handling 'Allow' items.
- if (exceptionList[i].setting == settings.PermissionStringValues.BLOCK &&
+ if (exceptionList[i].setting == settings.PermissionValues.BLOCK &&
this.categorySubtype != settings.PermissionValues.BLOCK) {
continue;
}
// Filter out 'Allow' values if this list is handling 'Block' items.
- if (exceptionList[i].setting == settings.PermissionStringValues.ALLOW &&
+ if (exceptionList[i].setting == settings.PermissionValues.ALLOW &&
this.categorySubtype != settings.PermissionValues.ALLOW) {
continue;
}
@@ -268,41 +271,45 @@ Polymer({
},
/**
- * Ensures the URL has a scheme (assumes http if omitted).
+ * Converts a string origin/pattern to a URL.
+ * @param {string} originOrPattern The origin/pattern to convert to URL.
+ * @return {URL} The URL to return (or null if origin is not a valid URL).
+ * @private
*/
- ensureUrlHasScheme_: function(url) {
- if (url.length == 0) return url;
- return url.indexOf('://') != -1 ? url : 'http://' + url;
+ toUrl_: function(originOrPattern) {
+ if (originOrPattern.length == 0)
+ return null;
+ // TODO(finnur): Hmm, it would probably be better to ensure scheme on the
+ // JS/C++ boundary.
+ return new URL(
+ this.ensureUrlHasScheme(originOrPattern.replace('[*.]', '')));
},
/**
* Converts an unordered site list to an ordered array, sorted by site name
* then protocol and de-duped (by origin).
* @param {!Array<SiteException>} sites A list of sites to sort and de-dup.
+ * @return {!Array<SiteException>} Sorted and de-duped list.
* @private
*/
toSiteArray_: function(sites) {
var self = this;
sites.sort(function(a, b) {
- // TODO(finnur): Hmm, it would probably be better to ensure scheme on the
- // JS/C++ boundary.
- var originA = self.ensureUrlHasScheme_(a.origin);
- var originB = self.ensureUrlHasScheme_(b.origin);
- var embeddingOriginA = self.ensureUrlHasScheme_(a.embeddingOrigin);
- var embeddingOriginB = self.ensureUrlHasScheme_(b.embeddingOrigin);
- var url1 = new URL(originA);
- var url2 = new URL(originB);
- var embeddingUrl1 = embeddingOriginA.length == 0 ? '' :
- new URL(embeddingOriginA);
- var embeddingUrl2 = embeddingOriginB.length == 0 ? '' :
- new URL(embeddingOriginB);
+ var url1 = self.toUrl_(a.origin);
+ var url2 = self.toUrl_(b.origin);
var comparison = url1.host.localeCompare(url2.host);
if (comparison == 0) {
comparison = url1.protocol.localeCompare(url2.protocol);
if (comparison == 0) {
comparison = url1.port.localeCompare(url2.port);
- if (comparison == 0)
- return embeddingUrl1.host.localeCompare(embeddingUrl2.host);
+ if (comparison == 0) {
+ // Compare hosts for the embedding origins.
+ var host1 = self.toUrl_(a.embeddingOrigin);
+ var host2 = self.toUrl_(b.embeddingOrigin);
+ host1 = (host1 == null) ? '' : host1.host;
+ host2 = (host2 == null) ? '' : host2.host;
+ return host1.localeCompare(host2);
+ }
}
}
return comparison;
@@ -312,24 +319,34 @@ Polymer({
var lastEmbeddingOrigin = '';
for (var i = 0; i < sites.length; ++i) {
var origin = sites[i].origin;
+ var originForDisplay = this.sanitizePort(origin.replace('[*.]', ''));
+
var embeddingOrigin = sites[i].embeddingOrigin;
+ if (this.category == settings.ContentSettingsTypes.GEOLOCATION) {
+ if (embeddingOrigin == '')
+ embeddingOrigin = '*';
+ }
+ var embeddingOriginForDisplay = '';
+ if (embeddingOrigin != '' && origin != embeddingOrigin) {
+ embeddingOriginForDisplay = loadTimeData.getStringF(
+ 'embeddedOnHost', this.sanitizePort(embeddingOrigin));
+ }
// The All Sites category can contain duplicates (from other categories).
- if (origin == lastOrigin && embeddingOrigin == lastEmbeddingOrigin)
+ if (originForDisplay == lastOrigin &&
+ embeddingOriginForDisplay == lastEmbeddingOrigin) {
continue;
-
- var embeddingOriginForDisplay = '';
- if (embeddingOrigin != '*' && origin != embeddingOrigin)
- embeddingOriginForDisplay = embeddingOrigin;
+ }
results.push({
origin: origin,
+ originForDisplay: originForDisplay,
embeddingOrigin: embeddingOrigin,
embeddingOriginForDisplay: embeddingOriginForDisplay,
});
- lastOrigin = origin;
- lastEmbeddingOrigin = embeddingOrigin;
+ lastOrigin = originForDisplay;
+ lastEmbeddingOrigin = embeddingOriginForDisplay;
}
return results;
},
@@ -342,8 +359,7 @@ Polymer({
this.showAllowAction_ =
this.categorySubtype == settings.PermissionValues.BLOCK;
this.showBlockAction_ =
- this.categorySubtype == settings.PermissionValues.ALLOW &&
- this.category != settings.ContentSettingsTypes.FULLSCREEN;
+ this.categorySubtype == settings.PermissionValues.ALLOW;
},
/**
@@ -381,7 +397,7 @@ Polymer({
settings.PermissionValues.ALLOW :
settings.PermissionValues.BLOCK;
this.setCategoryPermissionForOrigin(
- origin, embeddingOrigin, value, this.category);
+ origin, embeddingOrigin, this.category, value);
}
},
@@ -435,15 +451,4 @@ Polymer({
return toggleState;
},
-
- /**
- * Returns the icon to use for a given site.
- * @param {string} url The url of the site to fetch the icon for.
- * @private
- */
- computeSiteIcon_: function(url) {
- // TODO(finnur): For now, we're returning a placeholder image for each site
- // but the actual favicon for each site will need to be returned.
- return 'communication:message';
- },
});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.html b/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.html
index ec5addf3d33..045a673f4e3 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_settings_behavior.html
@@ -1,5 +1,7 @@
<link rel="import" href="chrome://md-settings/icons.html">
<link rel="import" href="chrome://md-settings/site_settings/constants.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_prefs_browser_proxy.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/assert.html">
-<script src="site_settings_behavior.js"></script> \ No newline at end of file
+<link rel="import" href="chrome://resources/html/icon.html">
+<script src="site_settings_behavior.js"></script>
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 31310a6701e..c541b8db9f1 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
@@ -49,12 +49,12 @@ var SiteSettingsBehaviorImpl = {
* for.
* @param {string} secondaryPattern The secondary pattern to change the
* permission for.
- * @param {number} value What value to set the permission to.
* @param {number} category The category permission to change.
+ * @param {string} value What value to set the permission to.
* @protected
*/
setCategoryPermissionForOrigin: function(
- primaryPattern, secondaryPattern, value, category) {
+ primaryPattern, secondaryPattern, category, value) {
this.browserProxy.setCategoryPermissionForOrigin(
primaryPattern, secondaryPattern, category, value);
},
@@ -71,8 +71,6 @@ var SiteSettingsBehaviorImpl = {
return 'camera';
case settings.ContentSettingsTypes.COOKIES:
return 'cookies';
- case settings.ContentSettingsTypes.FULLSCREEN:
- return 'fullscreen';
case settings.ContentSettingsTypes.GEOLOCATION:
return 'location';
case settings.ContentSettingsTypes.IMAGES:
@@ -91,7 +89,9 @@ var SiteSettingsBehaviorImpl = {
},
/**
- * A utility function to compute the icon to use for the category.
+ * A utility function to compute the icon to use for the category, both for
+ * the overall category as well as the individual permission in the details
+ * for a site.
* @param {number} category The category to show the icon for.
* @return {string} The id of the icon for the given category.
* @protected
@@ -99,23 +99,23 @@ var SiteSettingsBehaviorImpl = {
computeIconForContentCategory: function(category) {
switch (category) {
case settings.ContentSettingsTypes.CAMERA:
- return 'av:videocam';
+ return 'settings:videocam';
case settings.ContentSettingsTypes.COOKIES:
- return 'md-settings-icons:cookie';
+ return 'settings:cookie';
case settings.ContentSettingsTypes.FULLSCREEN:
- return 'icons:fullscreen';
+ return 'cr:fullscreen';
case settings.ContentSettingsTypes.GEOLOCATION:
- return 'communication:location-on';
+ return 'settings:location-on';
case settings.ContentSettingsTypes.IMAGES:
- return 'image:photo';
+ return 'settings:photo';
case settings.ContentSettingsTypes.JAVASCRIPT:
- return 'icons:input';
+ return 'settings:input';
case settings.ContentSettingsTypes.MIC:
- return 'av:mic';
+ return 'settings:mic';
case settings.ContentSettingsTypes.NOTIFICATIONS:
- return 'social:notifications';
+ return 'settings:notifications';
case settings.ContentSettingsTypes.POPUPS:
- return 'icons:open-in-new';
+ return 'settings:open-in-new';
default:
assertNotReached('Invalid category: ' + category);
return '';
@@ -123,7 +123,9 @@ var SiteSettingsBehaviorImpl = {
},
/**
- * A utility function to compute the title of the category.
+ * A utility function to compute the title of the category, both for
+ * the overall category as well as the individual permission in the details
+ * for a site.
* @param {number} category The category to show the title for.
* @return {string} The title for the given category.
* @protected
@@ -155,62 +157,6 @@ var SiteSettingsBehaviorImpl = {
},
/**
- * A utility function to compute the name of the pref for the category.
- * @param {number} category The category to find the pref name for.
- * @return {string} The pref name for the given category.
- * @protected
- */
- computeCategoryPrefName: function(category) {
- return 'profile.default_content_setting_values.' +
- this.computeCategorySuffix(category);
- },
-
- /**
- * A utility function to compute the name of the pref for the exceptions
- * for a given category.
- * @param {number} category The category to find the pref name for.
- * @return {string} The pref name for the given category exceptions.
- * @protected
- */
- computeCategoryExceptionsPrefName: function(category) {
- return 'profile.content_settings.exceptions.' +
- this.computeCategorySuffix(category);
- },
-
- /**
- * A utility function to convert the category enum into its text
- * representation, for use with prefs.
- * @param {number} category The category to find the pref name for.
- * @return {string} The pref name (suffix) for the given category.
- * @protected
- */
- computeCategorySuffix: function(category) {
- switch (category) {
- case settings.ContentSettingsTypes.CAMERA:
- return 'media_stream_camera';
- case settings.ContentSettingsTypes.COOKIES:
- return 'cookies';
- case settings.ContentSettingsTypes.FULLSCREEN:
- return 'fullscreen';
- case settings.ContentSettingsTypes.GEOLOCATION:
- return 'geolocation';
- case settings.ContentSettingsTypes.IMAGES:
- return 'images';
- case settings.ContentSettingsTypes.JAVASCRIPT:
- return 'javascript';
- case settings.ContentSettingsTypes.MIC:
- return 'media_stream_mic';
- case settings.ContentSettingsTypes.NOTIFICATIONS:
- return 'notifications';
- case settings.ContentSettingsTypes.POPUPS:
- return 'popups';
- default:
- assertNotReached();
- return '';
- }
- },
-
- /**
* A utility function to compute the description for the category.
* @param {number} category The category to show the description for.
* @param {boolean} categoryEnabled The state of the global toggle.
@@ -256,14 +202,6 @@ var SiteSettingsBehaviorImpl = {
loadTimeData.getString(
'siteSettingsAskBeforeAccessingRecommended') :
loadTimeData.getString('siteSettingsAskBeforeAccessing');
- case settings.ContentSettingsTypes.FULLSCREEN:
- // "Allowed" vs. "Ask first (recommended)".
- if (categoryEnabled) {
- return loadTimeData.getString('siteSettingsAllowed');
- }
- return showRecommendation ?
- loadTimeData.getString('siteSettingsAskFirstRecommended') :
- loadTimeData.getString('siteSettingsAskFirst');
case settings.ContentSettingsTypes.COOKIES:
// "Allow sites to save and read cookie data" vs "Blocked".
if (!categoryEnabled) {
@@ -284,6 +222,45 @@ var SiteSettingsBehaviorImpl = {
return '';
}
},
+
+ /**
+ * Ensures the URL has a scheme (assumes http if omitted).
+ * @param {string} url The URL with or without a scheme.
+ * @return {string} The URL with a scheme, or an empty string.
+ */
+ ensureUrlHasScheme: function(url) {
+ if (url.length == 0) return url;
+ return url.includes('://') ? url : 'http://' + url;
+ },
+
+ /**
+ * Removes redundant ports, such as port 80 for http and 443 for https.
+ * @param {string} url The URL to sanitize.
+ * @return {string} The URL without redundant ports, if any.
+ */
+ sanitizePort: function(url) {
+ var urlWithScheme = this.ensureUrlHasScheme(url);
+ if (urlWithScheme.startsWith('https://') &&
+ urlWithScheme.endsWith(':443')) {
+ return url.slice(0, -4);
+ }
+ if (urlWithScheme.startsWith('http://') &&
+ urlWithScheme.endsWith(':80')) {
+ return url.slice(0, -3);
+ }
+ return url;
+ },
+
+ /**
+ * Returns the icon to use for a given site.
+ * @param {SiteException} site The url of the site to fetch the icon for.
+ * @return {string} The background-image style with the favicon.
+ * @private
+ */
+ computeSiteIcon: function(site) {
+ var url = this.ensureUrlHasScheme(site.originForDisplay);
+ return 'background-image: ' + cr.icon.getFaviconImageSet(url);
+ },
};
/** @polymerBehavior */
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.css b/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.css
index b5339ee99fc..43bf6e34353 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.css
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.css
@@ -6,6 +6,14 @@
display: block;
}
+.toggle-icon {
+ -webkit-margin-start: 4px;
+}
+
+.toggle-text {
+ -webkit-margin-start: -11px;
+}
+
settings-site-list {
border-bottom: 1px solid var(--paper-grey-300);
}
@@ -13,3 +21,7 @@ settings-site-list {
settings-site-list:last-of-type {
border-bottom: none;
}
+
+.button-container {
+ -webkit-margin-start: 18px;
+}
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.html b/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.html
index 8454782d0fe..4a08892c1da 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.html
@@ -1,12 +1,11 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/av-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-icons/social-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-item/paper-icon-item.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item-body.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://md-settings/settings_shared_css.html">
+<link rel="import" href="chrome://md-settings/site_settings/add_site_dialog.html">
<link rel="import" href="chrome://md-settings/site_settings/constants.html">
<link rel="import" href="chrome://md-settings/site_settings/site_details.html">
<link rel="import" href="chrome://md-settings/site_settings/site_list.html">
@@ -16,19 +15,18 @@
<dom-module id="site-settings-category">
<link rel="import" type="css" href="site_settings_category.css">
<template>
- <style include="settings-shared"></style>
- <paper-icon-item>
- <iron-icon icon="[[computeIconForContentCategory(category)]]"
- item-icon></iron-icon>
- <paper-item-body two-line class="flex">
- <div>[[computeTitleForContentCategory(category)]]</div>
- <div secondary>
- [[computeCategoryDesc(category, categoryEnabled, showRecommendation)]]
- </div>
- </paper-item-body>
+ <style include="settings-shared">
+ paper-toggle-button {
+ --paper-toggle-button-label-spacing: 0;
+ }
+ </style>
+ <div class="settings-box first two-line">
+ <div class="start secondary">
+ [[computeCategoryDesc(category, categoryEnabled, showRecommendation)]]
+ </div>
<paper-toggle-button id="toggle" checked="{{categoryEnabled}}"
on-change="onToggleChange_"></paper-toggle-button>
- </paper-icon-item>
+ </div>
<settings-site-list id="blockList"
category="[[category]]"
current-route="{{currentRoute}}"
@@ -41,6 +39,10 @@
category-enabled="[[categoryEnabled]]"
selected-site="{{selectedSite}}">
</settings-site-list>
+ <div class="button-container">
+ <paper-button on-tap="onAddSiteTap_" class="primary-button"
+ hidden$="[[categoryEnabled]]">$i18n{addSiteLink}</paper-button>
+ </div>
</template>
<script src="site_settings_category.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.js b/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.js
index 7016b2490a9..6bf06cfceae 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_settings_category.js
@@ -54,7 +54,6 @@ Polymer({
this.$.blockList.categorySubtype = settings.PermissionValues.BLOCK;
this.$.allowList.categorySubtype = settings.PermissionValues.ALLOW;
- this.prefsProxy_ = settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
this.addWebUIListener('contentSettingCategoryChanged',
this.defaultValueForCategoryChanged_.bind(this));
},
@@ -80,7 +79,7 @@ Polymer({
case settings.ContentSettingsTypes.JAVASCRIPT:
case settings.ContentSettingsTypes.POPUPS:
// "Allowed" vs "Blocked".
- this.prefsProxy_.setDefaultValueForContentType(
+ this.browserProxy.setDefaultValueForContentType(
this.category,
this.categoryEnabled ?
settings.PermissionValues.ALLOW :
@@ -91,20 +90,12 @@ Polymer({
case settings.ContentSettingsTypes.CAMERA:
case settings.ContentSettingsTypes.MIC:
// "Ask" vs "Blocked".
- this.prefsProxy_.setDefaultValueForContentType(
+ this.browserProxy.setDefaultValueForContentType(
this.category,
this.categoryEnabled ?
settings.PermissionValues.ASK :
settings.PermissionValues.BLOCK);
break;
- case settings.ContentSettingsTypes.FULLSCREEN:
- // "Allowed" vs. "Ask first".
- this.prefsProxy_.setDefaultValueForContentType(
- this.category,
- this.categoryEnabled ?
- settings.PermissionValues.ALLOW :
- settings.PermissionValues.ASK);
- break;
default:
assertNotReached('Invalid category: ' + this.category);
}
@@ -121,4 +112,20 @@ Polymer({
this.categoryEnabled = enabled;
}.bind(this));
},
+
+ /**
+ * A handler for the Add Site button.
+ * @private
+ */
+ onAddSiteTap_: function() {
+ var dialog = document.createElement('add-site-dialog');
+ dialog.category = this.category;
+ this.shadowRoot.appendChild(dialog);
+
+ dialog.open();
+
+ dialog.addEventListener('iron-overlay-closed', function() {
+ dialog.remove();
+ });
+ },
});
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 b27395f0b17..e70d087a3a6 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
@@ -10,6 +10,7 @@
/**
* @typedef {{embeddingOrigin: string,
* origin: string,
+ * originForDisplay: string,
* setting: string,
* source: string}}
*/
@@ -62,10 +63,10 @@ cr.define('settings', function() {
/**
* Resets the category permission for a given origin (expressed as primary
* and secondary patterns).
- * @param {!string} primaryPattern The origin to change (primary pattern).
- * @param {!string} secondaryPattern The embedding origin to change
+ * @param {string} primaryPattern The origin to change (primary pattern).
+ * @param {string} secondaryPattern The embedding origin to change
* (secondary pattern).
- * @param {!number} contentType The category to change.
+ * @param {number} contentType The category to change.
*/
resetCategoryPermissionForOrigin: function(
primaryPattern, secondaryPattern, contentType) {},
@@ -73,14 +74,21 @@ cr.define('settings', function() {
/**
* Sets the category permission for a given origin (expressed as primary
* and secondary patterns).
- * @param {!string} primaryPattern The origin to change (primary pattern).
- * @param {!string} secondaryPattern The embedding origin to change
+ * @param {string} primaryPattern The origin to change (primary pattern).
+ * @param {string} secondaryPattern The embedding origin to change
* (secondary pattern).
- * @param {!number} contentType The category to change.
- * @param {!number} value The value to change the permission to.
+ * @param {number} contentType The category to change.
+ * @param {string} value The value to change the permission to.
*/
setCategoryPermissionForOrigin: function(
primaryPattern, secondaryPattern, contentType, value) {},
+
+ /**
+ * Checks whether a pattern is valid.
+ * @param {string} pattern The pattern to check
+ * @return {!Promise<boolean>} True if the pattern is valid.
+ */
+ isPatternValid: function(pattern) {},
};
/**
@@ -122,6 +130,12 @@ cr.define('settings', function() {
chrome.send('setCategoryPermissionForOrigin',
[primaryPattern, secondaryPattern, contentType, value]);
},
+
+ /** @override */
+ isPatternValid: function(pattern) {
+ return cr.sendWithPromise('isPatternValid', pattern);
+ },
+
};
return {
diff --git a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.css b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.css
index 6f590de24cd..809ed2850b1 100644
--- a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.css
+++ b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.css
@@ -5,16 +5,3 @@
:host {
display: block;
}
-
-.settings-list > paper-icon-item {
- border-bottom: 1px solid var(--paper-grey-300);
-}
-
-.settings-list > paper-icon-item:last-of-type {
- border-bottom: none;
-}
-
-.option-value {
- color: gray;
- font-size: 80%;
-}
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 0ae0e0678c5..6357e183b1f 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
@@ -1,17 +1,95 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/image-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-icons/social-icons.html">
+<link rel="import" href="chrome://md-settings/icons.html">
+<link rel="import" href="chrome://md-settings/settings_shared_css.html">
<link rel="import" href="chrome://md-settings/site_settings/constants.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_behavior.html">
<link rel="import" href="chrome://md-settings/site_settings/site_settings_prefs_browser_proxy.html">
<dom-module id="settings-site-settings-page">
- <link rel="import" type="css" href="site_settings_page.css">
<template>
- <div class="settings-box">
- <div id="list" class="settings-list"></div>
+ <style include="settings-shared">
+ </style>
+ <div class="settings-box first" category$="[[ALL_SITES]]"
+ on-tap="onTapCategory">
+ <iron-icon icon="settings:list"></iron-icon>
+ <div class="middle">$i18n{siteSettingsCategoryAllSites}</div>
+ </div>
+ <div class="settings-box two-line"
+ category$="[[ContentSettingsTypes.COOKIES]]" on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.COOKIES)]]"></iron-icon>
+ <div class="middle">
+ <div>
+ [[computeTitleForContentCategory(ContentSettingsTypes.COOKIES)]]
+ </div>
+ <div id="cookies" class="secondary"></div>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ category$="[[ContentSettingsTypes.GEOLOCATION]]" on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.GEOLOCATION)]]" item-icon=""></iron-icon>
+ <div class="middle">
+ [[computeTitleForContentCategory(ContentSettingsTypes.GEOLOCATION)]]
+ <div id="geolocation" class="secondary"></div>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ category$="[[ContentSettingsTypes.CAMERA]]" on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.CAMERA)]]" item-icon=""></iron-icon>
+ <div class="middle">
+ [[computeTitleForContentCategory(ContentSettingsTypes.CAMERA)]]
+ <div id="camera" class="secondary"></div>
+ </div>
+ </div>
+ <div class="settings-box two-line" category$="[[ContentSettingsTypes.MIC]]"
+ on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.MIC)]]" item-icon=""></iron-icon>
+ <div class="middle">
+ [[computeTitleForContentCategory(ContentSettingsTypes.MIC)]]
+ <div id="mic" class="secondary"></div>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ category$="[[ContentSettingsTypes.JAVASCRIPT]]"
+ on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.JAVASCRIPT)]]" item-icon=""></iron-icon>
+ <div class="middle">
+ [[computeTitleForContentCategory(ContentSettingsTypes.JAVASCRIPT)]]
+ <div id="javascript" class="secondary"></div>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ category$="[[ContentSettingsTypes.POPUPS]]" on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.POPUPS)]]" item-icon=""></iron-icon>
+ <div class="middle">
+ [[computeTitleForContentCategory(ContentSettingsTypes.POPUPS)]]
+ <div id="popups" class="secondary"></div>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ category$="[[ContentSettingsTypes.NOTIFICATIONS]]"
+ on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.NOTIFICATIONS)]]" item-icon=""></iron-icon>
+ <div class="middle">
+ [[computeTitleForContentCategory(ContentSettingsTypes.NOTIFICATIONS)]]
+ <div id="notifications" class="secondary"></div>
+ </div>
+ </div>
+ <div class="settings-box two-line"
+ category$="[[ContentSettingsTypes.IMAGES]]" on-tap="onTapCategory">
+ <iron-icon icon="[[computeIconForContentCategory(
+ ContentSettingsTypes.IMAGES)]]" item-icon=""></iron-icon>
+ <div class="middle">
+ [[computeTitleForContentCategory(ContentSettingsTypes.IMAGES)]]
+ <div id="images" class="secondary"></div>
+ </div>
</div>
</template>
<script src="site_settings_page.js"></script>
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 6734247e374..a16c45dcb40 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
@@ -31,82 +31,39 @@ Polymer({
},
ready: function() {
- this.addAllSitesCategory_();
- this.addCategory_(settings.ContentSettingsTypes.COOKIES);
- this.addCategory_(settings.ContentSettingsTypes.GEOLOCATION);
- this.addCategory_(settings.ContentSettingsTypes.CAMERA);
- this.addCategory_(settings.ContentSettingsTypes.MIC);
- this.addCategory_(settings.ContentSettingsTypes.JAVASCRIPT);
- this.addCategory_(settings.ContentSettingsTypes.POPUPS);
- this.addCategory_(settings.ContentSettingsTypes.FULLSCREEN);
- this.addCategory_(settings.ContentSettingsTypes.NOTIFICATIONS);
- this.addCategory_(settings.ContentSettingsTypes.IMAGES);
- },
+ this.ContentSettingsTypes = settings.ContentSettingsTypes;
+ this.ALL_SITES = settings.ALL_SITES;
+
+ // Look up the default value for each category and show it.
+ this.setDefaultValue_(this.ContentSettingsTypes.COOKIES, '#cookies');
+ this.setDefaultValue_(this.ContentSettingsTypes.GEOLOCATION,
+ '#geolocation');
+ this.setDefaultValue_(this.ContentSettingsTypes.CAMERA, '#camera');
+ this.setDefaultValue_(this.ContentSettingsTypes.MIC, '#mic');
+ this.setDefaultValue_(this.ContentSettingsTypes.JAVASCRIPT,
+ '#javascript');
+ this.setDefaultValue_(this.ContentSettingsTypes.POPUPS, '#popups');
+ this.setDefaultValue_(this.ContentSettingsTypes.NOTIFICATIONS,
+ '#notifications');
+ this.setDefaultValue_(this.ContentSettingsTypes.IMAGES, '#images');
- /**
- * Adds the All Sites category to the page.
- * @private
- */
- addAllSitesCategory_: function() {
- var description = loadTimeData.getString('siteSettingsCategoryAllSites');
- this.addCategoryImpl_(-1, 'list', description, '');
},
- /**
- * Adds a single category to the page.
- * @param {number} category The category to add.
- * @private
- */
- addCategory_: function(category) {
- var icon = this.computeIconForContentCategory(category);
- var title = this.computeTitleForContentCategory(category);
- var prefsProxy = settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
- prefsProxy.getDefaultValueForContentType(
+ setDefaultValue_: function(category, id) {
+ this.browserProxy.getDefaultValueForContentType(
category).then(function(enabled) {
var description = this.computeCategoryDesc(category, enabled, false);
- this.addCategoryImpl_(category, icon, title, description);
+ this.$$(id).innerText = description;
}.bind(this));
},
/**
- * Constructs the actual HTML elements for the category.
- * @param {number} category The category to add.
- * @param {string} icon The icon to show with it.
- * @param {string} title The title to show for the category.
- * @param {string} defaultValue The default value (permission) for the
- * category.
- * @private
- */
- addCategoryImpl_: function(category, icon, title, defaultValue) {
- var root = this.$.list;
- var paperIcon = document.createElement('paper-icon-item');
- paperIcon.addEventListener('tap', this.onTapCategory.bind(this, category));
-
- var ironIcon = document.createElement('iron-icon');
- ironIcon.setAttribute('icon', icon);
- ironIcon.setAttribute('item-icon', '');
-
- var description = document.createElement('div');
- description.setAttribute('class', 'flex');
- description.appendChild(document.createTextNode(title));
- var setting = document.createElement('div');
- setting.setAttribute('class', 'option-value');
-
- setting.appendChild(document.createTextNode(defaultValue));
-
- paperIcon.appendChild(ironIcon);
- paperIcon.appendChild(description);
- paperIcon.appendChild(setting);
- root.appendChild(paperIcon);
- },
-
- /**
* Handles selection of a single category and navigates to the details for
* that category.
- * @param {number} category The category selected by the user.
* @param {!Event} event The tap event.
*/
- onTapCategory: function(category, event) {
+ onTapCategory: function(event) {
+ var category = parseInt(event.currentTarget.getAttribute('category'), 10);
if (category == -1) {
this.currentRoute = {
page: this.currentRoute.page,
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 1ce9f830706..ca2d87ab7ed 100644
--- a/chromium/chrome/browser/resources/settings/system_page/system_page.html
+++ b/chromium/chrome/browser/resources/settings/system_page/system_page.html
@@ -21,15 +21,16 @@
</style>
<div class="settings-box block first">
<if expr="not is_macosx">
- <settings-checkbox i18n-values="label:backgroundAppsLabel"
+ <settings-checkbox label="$i18n{backgroundAppsLabel}"
pref="{{prefs.background_mode.enabled}}">
</settings-checkbox>
</if>
<div id="hardware-acceleration">
- <settings-checkbox i18n-values="label:hardwareAccelerationLabel"
+ <settings-checkbox label="$i18n{hardwareAccelerationLabel}"
pref="{{prefs.hardware_acceleration_mode.enabled}}">
</settings-checkbox>
- <template is="dom-if" if="[[shouldShowRestart_(prefs.hardware_acceleration_mode.enabled.value)]]">
+ <template is="dom-if" if="[[shouldShowRestart_(
+ prefs.hardware_acceleration_mode.enabled.value)]]">
<paper-button on-tap="onRestartTap_">$i18n{restart}</paper-button>
</template>
</div>
diff --git a/chromium/chrome/browser/resources/snippets_internals.css b/chromium/chrome/browser/resources/snippets_internals.css
new file mode 100644
index 00000000000..0dd1f5a3826
--- /dev/null
+++ b/chromium/chrome/browser/resources/snippets_internals.css
@@ -0,0 +1,84 @@
+/* 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 {
+ font-size: 20px;
+}
+
+textarea {
+ width: 100%;
+}
+
+#info > div {
+ width: 100%;
+}
+
+#info h2 {
+ color: rgb(74, 142, 230);
+ font-size: 100%;
+ margin-bottom: 0.3em;
+ margin-top: 1em;
+}
+
+.section-details {
+ width: 100%;
+}
+
+.section-details > tbody > tr:nth-child(odd) {
+ background: rgb(239, 243, 255);
+}
+
+.section-details .detail,
+.section-details .value {
+ width: 50%;
+}
+
+td.title-link {
+ padding-bottom: 0.5em;
+ padding-top: 0.5em;
+}
+
+.expiry {
+ color: gray;
+ font-size: 80%;
+}
+
+.date {
+ white-space: nowrap;
+}
+
+.url {
+ display: inline-block;
+ font-size: 80%;
+ word-break: break-all;
+}
+
+.snippet-detail {
+ font-size: 90%;
+}
+
+.hidden {
+ display: none;
+}
+
+.detail {
+ color: gray;
+ font-weight: normal;
+}
+
+.forms {
+ margin-top: 0.3em;
+}
+
+#submit-clear {
+ margin-bottom: 0.5em;
+}
+
+#last-json-text {
+ border: 1px solid black;
+ color: gray;
+ font-size: 90%;
+ padding: 4px;
+ word-break: break-all;
+} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/snippets_internals.html b/chromium/chrome/browser/resources/snippets_internals.html
new file mode 100644
index 00000000000..4a166b25c6a
--- /dev/null
+++ b/chromium/chrome/browser/resources/snippets_internals.html
@@ -0,0 +1,149 @@
+<!--
+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>
+<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">
+</if>
+<title>Snippets Internals</title>
+<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+<link rel="stylesheet" href="snippets_internals.css">
+<script src="chrome://resources/js/cr.js"></script>
+<script src="chrome://resources/js/jstemplate_compiled.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script src="snippets_internals.js"></script>
+
+<div id="info">
+ <div>
+ <h2>Properties</h2>
+ <table class="section-details">
+ <tr>
+ <td class="name">Snippets enabled
+ <td id="flag-snippets" class="value">
+ <tr>
+ <td class="name">Snippets restricted to hosts
+ <td id="switch-restrict-to-hosts" class="value">
+ <tr>
+ <td class="name">Snippets type
+ <td id="switch-personalized" class="value">
+ </table>
+ </div>
+
+ <div id="snippets">
+ <h2>Snippets <span class="detail">(click for details)</span></h2>
+ <table class="section-details">
+ <tr jsselect="list" style="display:none">
+ <td class="title-link">
+ <span class="snippet-title" jsvalues="snippet-id:id">
+ <span jscontent="title"></span>&gt;&gt;</span>
+ <div jsvalues="id:id" class="snippet-detail hidden">
+ <table>
+ <tr>
+ <td>ID
+ <td jscontent="snippetId">
+ <tr>
+ <td>Validity
+ <td class="expiry">
+ <span class="date" jscontent="published"></span> &ndash;
+ <span class="date" jscontent="expires"></span>
+ <tr>
+ <td>Site title
+ <td jscontent="siteTitle">
+ <tr>
+ <td>Text
+ <td jscontent="snippet">
+ <tr>
+ <td>URL
+ <td><a class="url" jsvalues="href:url" jscontent="url"></a>
+ <tr>
+ <td>Favicon
+ <td><a class="url" jsvalues="href:faviconUrl"
+ jscontent="faviconUrl"></a>
+ <tr>
+ <td>Salient image
+ <td><a class="url" jsvalues="href:salientImageUrl"
+ jscontent="salientImageUrl"></a>
+ <tr>
+ <td>Score
+ <td jscontent="score">
+ </table>
+ </div>
+ </table>
+ <div class="detail" id="snippets-empty"></div>
+ <div class="forms">
+ <input id="submit-clear" type="submit" value="Clear the list">
+ <input id="submit-dump" type="submit" value="Dump the list">
+ </div>
+ <div class="forms">
+ <input id="submit-download" type="submit" value="Add snippets">
+ <span id="hosts-restrict">from hosts <span class="detail">(specify at
+ least one host)</span>:
+ <textarea id="hosts-input" placeholder="www.wired.com www.bbc.co.uk"
+ rows="5" autocapitalize="none"></textarea>
+ </span>
+ <span id="hosts-status" class="detail"></span>
+ </div>
+ </div>
+
+ <div id="last-json" class="hidden">
+ <h2>Last JSON</h2>
+ <a id="last-json-button">Show the last JSON &gt;&gt;</a>
+ <div id="last-json-container" class="hidden">
+ <div id="last-json-text"></div>
+ <input id="last-json-dump" type="submit" value="Dump the last JSON">
+ </div>
+ </div>
+
+ <div id="discarded-snippets">
+ <h2>Discarded snippets <span class="detail">(click for details)</span></h2>
+ <table class="section-details">
+ <tr jsselect="list" style="display:none">
+ <td class="title-link">
+ <span class="discarded-snippet-title" jsvalues="snippet-id:id">
+ <span jscontent="title"></span> &gt;&gt;</span>
+ <div jsvalues="id:id" class="snippet-detail hidden">
+ <table>
+ <tr>
+ <td>Validity
+ <td class="expiry">
+ <span class="date" jscontent="published"></span> &ndash;
+ <span class="date" jscontent="expires"></span>
+ <tr>
+ <td>Site title
+ <td jscontent="siteTitle">
+ <tr>
+ <td>Text
+ <td jscontent="snippet">
+ <tr>
+ <td>URL
+ <td><a class="url" jsvalues="href:url" jscontent="url"></a>
+ <tr>
+ <td>Favicon
+ <td><a class="url" jsvalues="href:faviconUrl"
+ jscontent="faviconUrl"></a>
+ <tr>
+ <td>Salient image
+ <td><a class="url" jsvalues="href:salientImageUrl"
+ jscontent="salientImageUrl"></a>
+ </table>
+ </div>
+ </table>
+ <div class="detail" id="discarded-snippets-empty"></div>
+ <div class="forms">
+ <input id="discarded-snippets-clear" type="submit" value="Clear list">
+ </div>
+ </div>
+
+ <div id="hosts">
+ <h2>Suggestion hosts</h2>
+ <table class="section-details">
+ <tr jsselect="list">
+ <td jscontent="url">
+ </table>
+ <div class="detail" id="hosts-empty"></div>
+ </div>
+</div> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/snippets_internals.js b/chromium/chrome/browser/resources/snippets_internals.js
new file mode 100644
index 00000000000..a9f7b57141c
--- /dev/null
+++ b/chromium/chrome/browser/resources/snippets_internals.js
@@ -0,0 +1,130 @@
+// 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('chrome.SnippetsInternals', function() {
+ 'use strict';
+
+ function initialize() {
+ $('submit-download').addEventListener('click', function(event) {
+ chrome.send('download', [$('hosts-input').value]);
+ event.preventDefault();
+ });
+
+ $('submit-clear').addEventListener('click', function(event) {
+ chrome.send('clear');
+ event.preventDefault();
+ });
+
+ $('submit-dump').addEventListener('click', function(event) {
+ chrome.send('dump');
+ event.preventDefault();
+ });
+
+ $('last-json-button').addEventListener('click', function(event) {
+ $('last-json-container').classList.toggle('hidden');
+ });
+
+ $('last-json-dump').addEventListener('click', function(event) {
+ receiveJsonToDownload($('last-json-text').innerText);
+ event.preventDefault();
+ });
+
+ $('discarded-snippets-clear').addEventListener('click', function(event) {
+ chrome.send('clearDiscarded');
+ event.preventDefault();
+ });
+
+ chrome.send('loaded');
+ }
+
+ function setHostRestricted(restricted) {
+ receiveProperty('switch-restrict-to-hosts', restricted ? 'True' : 'False');
+ if (!restricted) {
+ $('hosts-restrict').classList.add('hidden');
+ }
+ }
+
+ function receiveProperty(propertyId, value) {
+ $(propertyId).textContent = value;
+ }
+
+ function receiveHosts(hosts) {
+ displayList(hosts, 'hosts');
+
+ $('hosts-input').value = hosts.list.map(
+ function(host) { return host.url;}).join(' ');
+ }
+
+ function receiveSnippets(snippets) {
+ displayList(snippets, 'snippets', 'snippet-title');
+ }
+
+ function receiveDiscardedSnippets(discardedSnippets) {
+ displayList(discardedSnippets, 'discarded-snippets',
+ 'discarded-snippet-title');
+ }
+
+ function receiveJson(json) {
+ var trimmed = json.trim();
+ var hasContent = (trimmed && trimmed != '{}');
+
+ if (hasContent) {
+ receiveProperty('last-json-text', trimmed);
+ $('last-json').classList.remove('hidden');
+ } else {
+ $('last-json').classList.add('hidden');
+ }
+ }
+
+ function receiveJsonToDownload(json) {
+ // Redirect the browser to download data in |json| as a file "snippets.json"
+ // (Setting Content-Disposition: attachment via a data: URL is not possible;
+ // 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.click();
+ }
+
+ function displayList(object, domId, titleClass) {
+ jstProcess(new JsEvalContext(object), $(domId));
+
+ var text;
+ var display;
+
+ if (object.list.length > 0) {
+ text = '';
+ display = 'inline';
+ } else {
+ text = 'The list is empty.';
+ display = 'none';
+ }
+
+ if ($(domId + '-empty')) $(domId + '-empty').textContent = text;
+ if ($(domId + '-clear')) $(domId + '-clear').style.display = display;
+
+ var links = document.getElementsByClassName(titleClass);
+ for (var link of links) {
+ link.addEventListener('click', function(event) {
+ var id = event.currentTarget.getAttribute('snippet-id');
+ $(id).classList.toggle('hidden');
+ });
+ }
+ }
+
+ // Return an object with all of the exports.
+ return {
+ initialize: initialize,
+ setHostRestricted: setHostRestricted,
+ receiveProperty: receiveProperty,
+ receiveHosts: receiveHosts,
+ receiveSnippets: receiveSnippets,
+ receiveDiscardedSnippets: receiveDiscardedSnippets,
+ receiveJson: receiveJson,
+ receiveJsonToDownload: receiveJsonToDownload,
+ };
+});
+
+document.addEventListener('DOMContentLoaded',
+ chrome.SnippetsInternals.initialize);
diff --git a/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.css b/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.css
index 459849af447..12a11214833 100644
--- a/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.css
+++ b/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.css
@@ -105,7 +105,6 @@ body {
#confirmButton,
#undoButton {
- font-weight: 500;
line-height: 16px;
margin: 0;
padding: 8px 16px;
diff --git a/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.html b/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.html
index 34ddf7e68fc..1958a01a5ed 100644
--- a/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.html
+++ b/chromium/chrome/browser/resources/sync_confirmation/sync_confirmation.html
@@ -17,20 +17,20 @@
--paper-button: {
background: var(--google-blue-500);
color: white;
+ font-weight: 500;
};
--paper-button-flat-keyboard-focus: {
background: rgb(58, 117, 215);
- font-weight: 500;
};
}
#undoButton {
--paper-button: {
color: var(--paper-grey-600);
+ font-weight: 500;
};
--paper-button-flat-keyboard-focus: {
background: rgba(0, 0, 0, .12);
- font-weight: 500;
};
}
diff --git a/chromium/chrome/browser/resources/translate_internals/OWNERS b/chromium/chrome/browser/resources/translate_internals/OWNERS
index 9b648a10380..bb5c3afcabc 100644
--- a/chromium/chrome/browser/resources/translate_internals/OWNERS
+++ b/chromium/chrome/browser/resources/translate_internals/OWNERS
@@ -1,2 +1 @@
-hajimehoshi@chromium.org
-toyoshim@chromium.org
+file://components/translate/OWNERS
diff --git a/chromium/chrome/browser/resources/translate_internals/prefs.html b/chromium/chrome/browser/resources/translate_internals/prefs.html
index 4a3aa70f873..53522377571 100644
--- a/chromium/chrome/browser/resources/translate_internals/prefs.html
+++ b/chromium/chrome/browser/resources/translate_internals/prefs.html
@@ -45,4 +45,8 @@ found in the LICENSE file.
<h2>Dump</h2>
<p class="dump"><p>
</section>
+ <section>
+ <h2 id="override-variations-country">Override Variations Country</h2>
+ <p id="country-override"></p>
+ </section>
</div>
diff --git a/chromium/chrome/browser/resources/translate_internals/translate_internals.js b/chromium/chrome/browser/resources/translate_internals/translate_internals.js
index e6ecc1b8b98..a18d468d408 100644
--- a/chromium/chrome/browser/resources/translate_internals/translate_internals.js
+++ b/chromium/chrome/browser/resources/translate_internals/translate_internals.js
@@ -253,7 +253,56 @@
}
/**
- * Addes '0's to |number| as a string. |width| is length of the string
+ * Handles the message of 'countryUpdated' from the browser.
+ *
+ * @param {Object} details the object containing the country
+ * information.
+ */
+ function onCountryUpdated(details) {
+ var p;
+ p = $('country-override');
+
+ p.innerHTML = '';
+
+ if ('country' in details) {
+ var country = details['country'];
+
+ var h2 = $('override-variations-country');
+ h2.title = (
+ 'Changing this value will override the permanent country stored ' +
+ 'by variations. Normally, this value gets automatically updated ' +
+ 'with a new value received from the variations server when ' +
+ 'Chrome is updated.');
+
+ var input = document.createElement('input');
+ input.type = 'text';
+ input.value = country;
+
+ var button = document.createElement('button');
+ button.textContent = 'update';
+ button.addEventListener('click', function() {
+ chrome.send('overrideCountry', [input.value]);
+ }, false);
+ p.appendChild(input);
+ p.appendChild(document.createElement('br'));
+ p.appendChild(button);
+
+ if ('update' in details && details['update']) {
+ var div1 = document.createElement('div');
+ div1.textContent = 'Permanent stored country updated.';
+ var div2 = document.createElement('div');
+ div2.textContent = ('You will need to restart your browser ' +
+ 'for the changes to take effect.');
+ p.appendChild(div1);
+ p.appendChild(div2);
+ }
+ } else {
+ p.textContent = 'Could not load country info from Variations.';
+ }
+ }
+
+ /**
+ * Adds '0's to |number| as a string. |width| is length of the string
* including '0's.
*
* @param {string} number The number to be converted into a string.
@@ -405,6 +454,9 @@
case 'supportedLanguagesUpdated':
onSupportedLanguagesUpdated(details);
break;
+ case 'countryUpdated':
+ onCountryUpdated(details);
+ break;
case 'translateErrorDetailsAdded':
onTranslateErrorDetailsAdded(details);
break;
diff --git a/chromium/chrome/browser/resources/user_manager/user_manager.css b/chromium/chrome/browser/resources/user_manager/user_manager.css
index eb3801f228c..70e27dd1053 100644
--- a/chromium/chrome/browser/resources/user_manager/user_manager.css
+++ b/chromium/chrome/browser/resources/user_manager/user_manager.css
@@ -197,12 +197,16 @@ html[dir=rtl] .main-pane {
}
.action-box-remove-user-warning .remove-warning-button {
- height: 30px;
-}
-
-.action-box-remove-user-warning .remove-warning-button:focus {
- /* Override the default blue border inherited from
- button.custom-appearance:focus. */
- border: 1px solid transparent !important;
- box-shadow: inset 0 0 0 1px #fff;
+ background: rgb(197, 57, 41);
+ border-radius: 2px;
+ color: white;
+ font-weight: 500;
+ line-height: 32px;
+ padding: 0 16px;
+ width: 100%;
+}
+
+.action-box-remove-user-warning .remove-warning-button[focused] {
+ background: rgb(173, 50, 36);
+ font-weight: 500;
}
diff --git a/chromium/chrome/browser/resources/user_manager/user_manager.js b/chromium/chrome/browser/resources/user_manager/user_manager.js
index 96ddf6588a4..86c7ac8a2e4 100644
--- a/chromium/chrome/browser/resources/user_manager/user_manager.js
+++ b/chromium/chrome/browser/resources/user_manager/user_manager.js
@@ -6,6 +6,7 @@
<include src="../../../../ui/login/login_ui_tools.js">
<include src="../../../../ui/login/display_manager.js">
<include src="control_bar.js">
+<include src="../../../../ui/login/account_picker/user_pod_template.js">
<include src="../../../../ui/login/account_picker/screen_account_picker.js">
<include src="../../../../ui/login/account_picker/user_pod_row.js">
<include src="../../../../ui/login/resource_loader.js">