summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/resources
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 15:06:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:48:58 +0000
commitdaa093eea7c773db06799a13bd7e4e2e2a9f8f14 (patch)
tree96cc5e7b9194c1b29eab927730bfa419e7111c25 /chromium/chrome/browser/resources
parentbe59a35641616a4cf23c4a13fa0632624b021c1b (diff)
downloadqtwebengine-chromium-daa093eea7c773db06799a13bd7e4e2e2a9f8f14.tar.gz
BASELINE: Update Chromium to 63.0.3239.58
Change-Id: Ia93b322a00ba4dd4004f3bcf1254063ba90e1605 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources')
-rw-r--r--chromium/chrome/browser/resources/BUILD.gn30
-rw-r--r--chromium/chrome/browser/resources/PRESUBMIT.py8
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/adapter_broker.js59
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/adapter_page.js2
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.html11
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js20
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js8
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js6
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/device_broker.js4
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/device_collection.js4
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/device_details_page.js20
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/device_table.js10
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/devices_page.js2
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/interfaces.js45
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/service_list.js10
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/value_control.js16
-rw-r--r--chromium/chrome/browser/resources/bookmark_manager/css/bmm.css2
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn1
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json28
-rw-r--r--chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd57
-rw-r--r--chromium/chrome/browser/resources/chromeos/compiled_resources2.gyp14
-rw-r--r--chromium/chrome/browser/resources/chromeos/sys_internals/compiled_resources2.gyp36
-rw-r--r--chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/compiled_resources2.gyp63
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ar/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/bg/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ca/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/cs/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/da/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/de/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/el/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en_GB/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es_419/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/et/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fa/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fi/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fil/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fr/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/he/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hi/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hr/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hu/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/id/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/it/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ja/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ko/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lt/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lv/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ms/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/nl/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/no/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pl/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_BR/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_PT/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ro/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ru/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sk/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sl/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sr/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sv/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/th/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/tr/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/uk/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/vi/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_CN/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_TW/messages.json46
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/manifest.json22
-rw-r--r--chromium/chrome/browser/resources/component_extension_resources.grd1
-rw-r--r--chromium/chrome/browser/resources/cryptotoken/compiled_resources2.gyp47
-rw-r--r--chromium/chrome/browser/resources/download_internals/compiled_resources2.gyp (renamed from chromium/chrome/browser/resources/uber/compiled_resources2.gyp)20
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals.css41
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals.html110
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals.js135
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js131
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals_visuals.js55
-rw-r--r--chromium/chrome/browser/resources/extensions/compiled_resources2.gyp22
-rw-r--r--chromium/chrome/browser/resources/extensions/drag_and_drop_handler.html2
-rw-r--r--chromium/chrome/browser/resources/extensions/extension_command_list.js6
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions.html4
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions.js2
-rw-r--r--chromium/chrome/browser/resources/feedback/html/default.html4
-rw-r--r--chromium/chrome/browser/resources/feedback/js/feedback.js4
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/authenticator.js36
-rw-r--r--chromium/chrome/browser/resources/instant/instant.css31
-rw-r--r--chromium/chrome/browser/resources/instant/instant.html5
-rw-r--r--chromium/chrome/browser/resources/instant/instant.js36
-rw-r--r--chromium/chrome/browser/resources/interventions_internals/index.css58
-rw-r--r--chromium/chrome/browser/resources/interventions_internals/index.html43
-rw-r--r--chromium/chrome/browser/resources/interventions_internals/index.js160
-rw-r--r--chromium/chrome/browser/resources/interventions_internals/unsupported_page.html21
-rw-r--r--chromium/chrome/browser/resources/local_ntp/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/local_ntp.css130
-rw-r--r--chromium/chrome/browser/resources/local_ntp/local_ntp.html27
-rw-r--r--chromium/chrome/browser/resources/local_ntp/local_ntp.js328
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_single.js81
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_util.js8
-rw-r--r--chromium/chrome/browser/resources/local_ntp/voice.css39
-rw-r--r--chromium/chrome/browser/resources/local_ntp/voice.js475
-rw-r--r--chromium/chrome/browser/resources/local_omnibox_popup/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/.eslintrc.js13
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/actions.js20
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/api_listener.html1
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/api_listener.js20
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/app.html4
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/app.js12
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/command_manager.js104
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp22
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/constants.js20
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/debouncer.html (renamed from chromium/chrome/browser/resources/md_bookmarks/timer_proxy.html)2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/debouncer.js86
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js4
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/dnd_chip.js2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js246
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js8
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/folder_node.html4
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/folder_node.js41
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/item.html1
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/item.js18
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/list.html8
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/list.js40
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/mouse_focus_behavior.js4
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/reducers.js50
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/router.js4
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/store.js2
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/store_client.js6
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/timer_proxy.js89
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/toast_manager.html32
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/toast_manager.js42
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/toolbar.js14
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/types.js20
-rw-r--r--chromium/chrome/browser/resources/md_bookmarks/util.js26
-rw-r--r--chromium/chrome/browser/resources/md_downloads/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs45
-rw-r--r--chromium/chrome/browser/resources/md_downloads/compiled_resources2.gyp22
-rw-r--r--chromium/chrome/browser/resources/md_downloads/manager.html20
-rw-r--r--chromium/chrome/browser/resources/md_downloads/manager.js46
-rw-r--r--chromium/chrome/browser/resources/md_downloads/search_service.html (renamed from chromium/chrome/browser/resources/md_downloads/action_service.html)2
-rw-r--r--chromium/chrome/browser/resources/md_downloads/search_service.js (renamed from chromium/chrome/browser/resources/md_downloads/action_service.js)9
-rw-r--r--chromium/chrome/browser/resources/md_downloads/search_service_unittest.gtestjs45
-rw-r--r--chromium/chrome/browser/resources/md_downloads/toolbar.html2
-rw-r--r--chromium/chrome/browser/resources/md_downloads/toolbar.js6
-rw-r--r--chromium/chrome/browser/resources/md_extensions/BUILD.gn43
-rw-r--r--chromium/chrome/browser/resources/md_extensions/code_section.html37
-rw-r--r--chromium/chrome/browser/resources/md_extensions/code_section.js13
-rw-r--r--chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp50
-rw-r--r--chromium/chrome/browser/resources/md_extensions/detail_view.html335
-rw-r--r--chromium/chrome/browser/resources/md_extensions/detail_view.js17
-rw-r--r--chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.html2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.js (renamed from chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js)8
-rw-r--r--chromium/chrome/browser/resources/md_extensions/drop_overlay.html5
-rw-r--r--chromium/chrome/browser/resources/md_extensions/error_page.html205
-rw-r--r--chromium/chrome/browser/resources/md_extensions/error_page.js188
-rw-r--r--chromium/chrome/browser/resources/md_extensions/extensions.html13
-rw-r--r--chromium/chrome/browser/resources/md_extensions/extensions_resources.grd179
-rw-r--r--chromium/chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd19
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item.html41
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item.js33
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_list.html76
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_list.js37
-rw-r--r--chromium/chrome/browser/resources/md_extensions/item_util.html4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html51
-rw-r--r--chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js108
-rw-r--r--chromium/chrome/browser/resources/md_extensions/kiosk_dialog.html144
-rw-r--r--chromium/chrome/browser/resources/md_extensions/kiosk_dialog.js185
-rw-r--r--chromium/chrome/browser/resources/md_extensions/load_error.html4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/load_error.js8
-rw-r--r--chromium/chrome/browser/resources/md_extensions/manager.html132
-rw-r--r--chromium/chrome/browser/resources/md_extensions/manager.js82
-rw-r--r--chromium/chrome/browser/resources/md_extensions/navigation_helper.html3
-rw-r--r--chromium/chrome/browser/resources/md_extensions/navigation_helper.js60
-rw-r--r--chromium/chrome/browser/resources/md_extensions/options_dialog.html4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/pack_dialog.html8
-rw-r--r--chromium/chrome/browser/resources/md_extensions/pack_dialog.js15
-rw-r--r--chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/service.html9
-rw-r--r--chromium/chrome/browser/resources/md_extensions/service.js13
-rw-r--r--chromium/chrome/browser/resources/md_extensions/shortcut_input.html22
-rw-r--r--chromium/chrome/browser/resources/md_extensions/shortcut_input.js6
-rw-r--r--chromium/chrome/browser/resources/md_extensions/shortcut_util.html (renamed from chromium/chrome/browser/resources/extensions/shortcut_util.html)2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/shortcut_util.js (renamed from chromium/chrome/browser/resources/extensions/shortcut_util.js)82
-rw-r--r--chromium/chrome/browser/resources/md_extensions/sidebar.html4
-rw-r--r--chromium/chrome/browser/resources/md_extensions/sidebar.js36
-rw-r--r--chromium/chrome/browser/resources/md_extensions/strings.html2
-rw-r--r--chromium/chrome/browser/resources/md_extensions/toolbar.html45
-rw-r--r--chromium/chrome/browser/resources/md_extensions/toolbar.js29
-rw-r--r--chromium/chrome/browser/resources/md_extensions/view_manager.html4
-rw-r--r--chromium/chrome/browser/resources/md_feedback/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/md_feedback/compiled_resources2.gyp22
-rw-r--r--chromium/chrome/browser/resources/md_feedback/feedback.html17
-rw-r--r--chromium/chrome/browser/resources/md_feedback/feedback.js42
-rw-r--r--chromium/chrome/browser/resources/md_feedback/feedback_container.html73
-rw-r--r--chromium/chrome/browser/resources/md_feedback/feedback_container.js36
-rw-r--r--chromium/chrome/browser/resources/md_history/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/md_history/app.html18
-rw-r--r--chromium/chrome/browser/resources/md_history/app.js13
-rw-r--r--chromium/chrome/browser/resources/md_history/externs.js1
-rw-r--r--chromium/chrome/browser/resources/md_history/history.js5
-rw-r--r--chromium/chrome/browser/resources/md_history/history_toolbar.html50
-rw-r--r--chromium/chrome/browser/resources/md_history/history_toolbar.js77
-rw-r--r--chromium/chrome/browser/resources/md_history/icons.html1
-rw-r--r--chromium/chrome/browser/resources/md_history/shared_style.html2
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js4
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.css27
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.html21
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.js33
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls_interface.js7
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_details/route_details.html3
-rw-r--r--chromium/chrome/browser/resources/media_router/elements/route_details/route_details.js2
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_browser_api.js14
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_data.js8
-rw-r--r--chromium/chrome/browser/resources/memory_internals.js14
-rw-r--r--chromium/chrome/browser/resources/net_internals/bandwidth_view.html32
-rw-r--r--chromium/chrome/browser/resources/net_internals/browser_bridge.js12
-rw-r--r--chromium/chrome/browser/resources/net_internals/events_view.css8
-rw-r--r--chromium/chrome/browser/resources/net_internals/index.html1
-rw-r--r--chromium/chrome/browser/resources/net_internals/index.js1
-rw-r--r--chromium/chrome/browser/resources/net_internals/log_view_painter.js6
-rw-r--r--chromium/chrome/browser/resources/net_internals/main.js15
-rw-r--r--chromium/chrome/browser/resources/net_internals/quic_view.html3
-rw-r--r--chromium/chrome/browser/resources/net_internals/sdch_view.html69
-rw-r--r--chromium/chrome/browser/resources/net_internals/sdch_view.js64
-rw-r--r--chromium/chrome/browser/resources/net_internals/source_entry.js10
-rw-r--r--chromium/chrome/browser/resources/ntp4/md_incognito_tab.css1
-rw-r--r--chromium/chrome/browser/resources/ntp4/new_tab.js31
-rw-r--r--chromium/chrome/browser/resources/ntp4/page_list_view.js29
-rw-r--r--chromium/chrome/browser/resources/offline_pages/offline_internals.html4
-rw-r--r--chromium/chrome/browser/resources/offline_pages/offline_internals.js27
-rw-r--r--chromium/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js21
-rw-r--r--chromium/chrome/browser/resources/optimize_webui.gni (renamed from chromium/chrome/browser/resources/vulcanize.gni)8
-rwxr-xr-xchromium/chrome/browser/resources/optimize_webui.py (renamed from chromium/chrome/browser/resources/vulcanize_gn.py)6
-rwxr-xr-xchromium/chrome/browser/resources/optimize_webui_test.py (renamed from chromium/chrome/browser/resources/vulcanize_gn_test.py)20
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js41
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html31
-rw-r--r--chromium/chrome/browser/resources/pdf/pdf.js27
-rw-r--r--chromium/chrome/browser/resources/pdf/viewport.js30
-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/policy.html6
-rw-r--r--chromium/chrome/browser/resources/policy_android.css6
-rw-r--r--chromium/chrome/browser/resources/policy_base.js50
-rw-r--r--chromium/chrome/browser/resources/policy_common.css6
-rw-r--r--chromium/chrome/browser/resources/policy_tool.css41
-rw-r--r--chromium/chrome/browser/resources/policy_tool.html100
-rw-r--r--chromium/chrome/browser/resources/policy_tool.js273
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/app_state.js202
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/capabilities_holder.js30
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/coordinate2d.js55
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination.js476
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination_match.js85
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination_store.js1400
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/invitation.js91
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/local_parsers.js50
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/margins.js93
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/measurement_system.js17
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/measurement_system_unittest.gtestjs68
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/page_number_set.js45
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js527
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/printable_area.js49
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/size.js45
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/collate.js52
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/color.js83
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/copies.js51
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/css_background.js48
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js117
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/dpi.js49
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/duplex.js52
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js51
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js129
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/landscape.js96
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/margins_type.js66
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/media_size.js87
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/page_range.js96
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/rasterize.js44
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/scaling.js63
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/selection_only.js44
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/ticket_item.js214
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js80
-rw-r--r--chromium/chrome/browser/resources/print_preview/images/1x/printer.png (renamed from chromium/chrome/browser/resources/print_preview/images/printer.png)bin363 -> 363 bytes
-rw-r--r--chromium/chrome/browser/resources/print_preview/images/1x/printer_shared.png (renamed from chromium/chrome/browser/resources/print_preview/images/printer_shared.png)bin685 -> 685 bytes
-rw-r--r--chromium/chrome/browser/resources/print_preview/images/2x/printer.pngbin0 -> 1935 bytes
-rw-r--r--chromium/chrome/browser/resources/print_preview/images/2x/printer_shared.pngbin0 -> 2603 bytes
-rw-r--r--chromium/chrome/browser/resources/print_preview/native_layer.js306
-rw-r--r--chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_header.js25
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.css19
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.html2
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.js65
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview_utils.js2
-rw-r--r--chromium/chrome/browser/resources/print_preview/search/destination_list_item.js1
-rw-r--r--chromium/chrome/browser/resources/print_preview/settings/copies_settings.css12
-rw-r--r--chromium/chrome/browser/resources/print_preview/settings/destination_settings.js1
-rw-r--r--chromium/chrome/browser/resources/print_preview/settings/page_settings.js28
-rw-r--r--chromium/chrome/browser/resources/print_preview/settings/scaling_settings.css7
-rw-r--r--chromium/chrome/browser/resources/print_preview/settings/settings_box.css11
-rw-r--r--chromium/chrome/browser/resources/print_preview/settings/settings_section_select.js12
-rw-r--r--chromium/chrome/browser/resources/profiler/OWNERS4
-rw-r--r--chromium/chrome/browser/resources/profiler/profiler.html164
-rw-r--r--chromium/chrome/browser/resources/profiler/profiler.js2371
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb32
-rw-r--r--chromium/chrome/browser/resources/settings/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.html26
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.js32
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page_browser_proxy.js17
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html77
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js10
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.html9
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.js23
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js8
-rw-r--r--chromium/chrome/browser/resources/settings/change_password_page/change_password_browser_proxy.js11
-rw-r--r--chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html1
-rw-r--r--chromium/chrome/browser/resources/settings/change_password_page/change_password_page.js22
-rw-r--r--chromium/chrome/browser/resources/settings/change_password_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html4
-rw-r--r--chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js388
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js6
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html323
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.js151
-rw-r--r--chromium/chrome/browser/resources/settings/compiled_resources2.gyp8
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_checkbox.html2
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html5
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_toggle_button.js27
-rw-r--r--chromium/chrome/browser/resources/settings/date_time_page/date_time_page.html2
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display.html112
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/night_light_slider.html9
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/night_light_slider.js58
-rw-r--r--chromium/chrome/browser/resources/settings/direction_delegate.html4
-rw-r--r--chromium/chrome/browser/resources/settings/direction_delegate.js29
-rw-r--r--chromium/chrome/browser/resources/settings/icons.html2
-rw-r--r--chromium/chrome/browser/resources/settings/images/settings_icon_visibility.svg1
-rw-r--r--chromium/chrome/browser/resources/settings/images/settings_icon_visibility_off.svg1
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp14
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_config.html78
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_config.js494
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html21
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js30
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.html6
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.js19
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html5
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js6
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_config_input.html20
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_config_input.js21
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_config_select.html24
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_config_select.js62
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html7
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.js14
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js18
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html10
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js16
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages.js14
-rw-r--r--chromium/chrome/browser/resources/settings/lifetime_browser_proxy.js13
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html22
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js17
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html1
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html2
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html19
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js3
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html44
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js149
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/change_picture.html7
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/change_picture.js11
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp1
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_screen.js14
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_state_behavior.js8
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.html1
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.js22
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/settings_icon_flip.svg1
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/user_list.js3
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js18
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_printers.html12
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_printers.js40
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js27
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html48
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.js12
-rw-r--r--chromium/chrome/browser/resources/settings/route.js9
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js7
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.html31
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.js37
-rw-r--r--chromium/chrome/browser/resources/settings/search_settings.js11
-rw-r--r--chromium/chrome/browser/resources/settings/settings.html4
-rw-r--r--chromium/chrome/browser/resources/settings/settings_icons_css.html6
-rw-r--r--chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html13
-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_subpage.html4
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js25
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources.grd54
-rw-r--r--chromium/chrome/browser/resources/settings/settings_shared_css.html31
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/compiled_resources2.gyp2
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html34
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js37
-rw-r--r--chromium/chrome/browser/resources/settings/settings_vars_css.html29
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/all_sites.js4
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js6
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html2
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js5
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp38
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/constants.js13
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.html3
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.js100
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/cookie_tree_node.js234
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html1
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js140
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data.html54
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data.js125
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html3
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js26
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.html18
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.js22
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html13
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js49
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.html8
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js62
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js7
-rw-r--r--chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.html51
-rw-r--r--chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.js21
-rw-r--r--chromium/chrome/browser/resources/snippets_internals.html11
-rw-r--r--chromium/chrome/browser/resources/snippets_internals.js33
-rw-r--r--chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb123
-rw-r--r--chromium/chrome/browser/resources/sync_file_system_internals/main.css2
-rw-r--r--chromium/chrome/browser/resources/translate_internals/prefs.html2
-rw-r--r--chromium/chrome/browser/resources/uber/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/uber/uber.css63
-rw-r--r--chromium/chrome/browser/resources/uber/uber.html39
-rw-r--r--chromium/chrome/browser/resources/uber/uber.js476
-rw-r--r--chromium/chrome/browser/resources/uber/uber_frame.css70
-rw-r--r--chromium/chrome/browser/resources/uber/uber_frame.html39
-rw-r--r--chromium/chrome/browser/resources/uber/uber_frame.js155
-rw-r--r--chromium/chrome/browser/resources/uber/uber_page_manager_observer.js59
-rw-r--r--chromium/chrome/browser/resources/uber/uber_utils.js226
-rw-r--r--chromium/chrome/browser/resources/uber_shared.css (renamed from chromium/chrome/browser/resources/uber/uber_shared.css)2
-rwxr-xr-xchromium/chrome/browser/resources/unpack_pak.py8
439 files changed, 9669 insertions, 13072 deletions
diff --git a/chromium/chrome/browser/resources/BUILD.gn b/chromium/chrome/browser/resources/BUILD.gn
index 39e356bfb69..b2d10f2a0ba 100644
--- a/chromium/chrome/browser/resources/BUILD.gn
+++ b/chromium/chrome/browser/resources/BUILD.gn
@@ -95,7 +95,7 @@ if (!is_android) {
}
grit("settings_resources") {
- if (use_vulcanize) {
+ if (optimize_webui) {
source = "settings/settings_resources_vulcanized.grd"
# The .grd contains references to generated files.
@@ -124,6 +124,34 @@ if (!is_android) {
}
if (enable_extensions) {
+ grit("extensions_resources") {
+ if (optimize_webui) {
+ source = "md_extensions/extensions_resources_vulcanized.grd"
+
+ # The .grd contains references to generated files.
+ source_is_generated = true
+
+ deps = [
+ "//chrome/browser/resources/md_extensions:build",
+ ]
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+ } else {
+ source = "md_extensions/extensions_resources.grd"
+ }
+
+ defines = chrome_grit_defines
+ outputs = [
+ "grit/extensions_resources.h",
+ "grit/extensions_resources_map.cc",
+ "grit/extensions_resources_map.h",
+ "extensions_resources.pak",
+ ]
+ output_dir = "$root_gen_dir/chrome"
+ }
+
grit("sync_file_system_internals_resources") {
source = "sync_file_system_internals_resources.grd"
defines = chrome_grit_defines
diff --git a/chromium/chrome/browser/resources/PRESUBMIT.py b/chromium/chrome/browser/resources/PRESUBMIT.py
index b8a8396d241..e7a3e430986 100644
--- a/chromium/chrome/browser/resources/PRESUBMIT.py
+++ b/chromium/chrome/browser/resources/PRESUBMIT.py
@@ -96,9 +96,9 @@ def CheckHtml(input_api, output_api):
input_api, output_api, 80, lambda x: x.LocalPath().endswith('.html'))
-def RunVulcanizeTests(input_api, output_api):
+def RunOptimizeWebUiTests(input_api, output_api):
presubmit_path = input_api.PresubmitLocalPath()
- tests = [input_api.os_path.join(presubmit_path, 'vulcanize_gn_test.py')]
+ tests = [input_api.os_path.join(presubmit_path, 'optimize_webui_test.py')]
return input_api.canned_checks.RunUnitTests(input_api, output_api, tests)
@@ -123,8 +123,8 @@ def _CheckChangeOnUploadOrCommit(input_api, output_api):
affected = input_api.AffectedFiles()
if any(f for f in affected if f.LocalPath().endswith('.html')):
results += CheckHtml(input_api, output_api)
- if any(f for f in affected if f.LocalPath().endswith('vulcanize_gn.py')):
- results += RunVulcanizeTests(input_api, output_api)
+ if any(f for f in affected if f.LocalPath().endswith('optimize_webui.py')):
+ results += RunOptimizeWebUiTests(input_api, output_api)
results += _CheckWebDevStyle(input_api, output_api)
results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
check_js=True)
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/adapter_broker.js b/chromium/chrome/browser/resources/bluetooth_internals/adapter_broker.js
index 37c8fb829a4..df04fc91b8f 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/adapter_broker.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/adapter_broker.js
@@ -7,11 +7,11 @@
* chrome://bluetooth-internals/.
*/
cr.define('adapter_broker', function() {
- /** @typedef {interfaces.BluetoothAdapter.Adapter.ptrClass} */
+ /** @typedef {bluetooth.mojom.Adapter.ptrClass} */
var AdapterPtr;
- /** @typedef {interfaces.BluetoothDevice.Device.ptrClass} */
+ /** @typedef {bluetooth.mojom.Device.ptrClass} */
var DevicePtr;
- /** @typedef {interfaces.BluetoothAdapter.DiscoverySession.ptrClass} */
+ /** @typedef {bluetooth.mojom.DiscoverySession.ptrClass} */
var DiscoverySessionPtr;
/**
@@ -51,11 +51,10 @@ cr.define('adapter_broker', function() {
*/
connectToDevice: function(address) {
return this.adapter_.connectToDevice(address).then(function(response) {
- if (response.result !=
- interfaces.BluetoothAdapter.ConnectResult.SUCCESS) {
+ if (response.result != bluetooth.mojom.ConnectResult.SUCCESS) {
// TODO(crbug.com/663394): Replace with more descriptive error
// messages.
- var ConnectResult = interfaces.BluetoothAdapter.ConnectResult;
+ var ConnectResult = bluetooth.mojom.ConnectResult;
var errorString = Object.keys(ConnectResult).find(function(key) {
return ConnectResult[key] === response.result;
});
@@ -69,7 +68,7 @@ cr.define('adapter_broker', function() {
/**
* Gets an array of currently detectable devices from the Adapter service.
- * @return {!Array<!interfaces.BluetoothDevice.DeviceInfo>}
+ * @return {!Array<!bluetooth.mojom.DeviceInfo>}
*/
getDevices: function() {
return this.adapter_.getDevices();
@@ -77,7 +76,7 @@ cr.define('adapter_broker', function() {
/**
* Gets the current state of the Adapter.
- * @return {!interfaces.BluetoothAdapter.AdapterInfo}
+ * @return {!bluetooth.mojom.AdapterInfo}
*/
getInfo: function() {
return this.adapter_.getInfo();
@@ -85,11 +84,11 @@ cr.define('adapter_broker', function() {
/**
* Sets client of Adapter service.
- * @param {!interfaces.BluetoothAdapter.AdapterClient} adapterClient
+ * @param {!bluetooth.mojom.AdapterClient} adapterClient
*/
setClient: function(adapterClient) {
- adapterClient.binding = new interfaces.Bindings.Binding(
- interfaces.BluetoothAdapter.AdapterClient, adapterClient);
+ adapterClient.binding =
+ new mojo.Binding(bluetooth.mojom.AdapterClient, adapterClient);
this.adapter_.setClient(
adapterClient.binding.createInterfacePtrAndBind());
@@ -181,7 +180,7 @@ cr.define('adapter_broker', function() {
/**
* Fires deviceadded event.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
deviceAdded: function(deviceInfo) {
var event =
@@ -191,7 +190,7 @@ cr.define('adapter_broker', function() {
/**
* Fires devicechanged event.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
deviceChanged: function(deviceInfo) {
var event =
@@ -201,7 +200,7 @@ cr.define('adapter_broker', function() {
/**
* Fires deviceremoved event.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
deviceRemoved: function(deviceInfo) {
var event =
@@ -221,24 +220,20 @@ cr.define('adapter_broker', function() {
if (adapterBroker)
return Promise.resolve(adapterBroker);
- return interfaces.setupInterfaces()
- .then(function(adapter) {
- var adapterFactory =
- new interfaces.BluetoothAdapter.AdapterFactoryPtr(
- interfaces.FrameInterfaces.getInterface(
- interfaces.BluetoothAdapter.AdapterFactory.name));
-
- // Get an Adapter service.
- return adapterFactory.getAdapter();
- })
- .then(function(response) {
- if (!response.adapter.ptr.isBound()) {
- throw new Error('Bluetooth Not Supported on this platform.');
- }
-
- adapterBroker = new AdapterBroker(response.adapter);
- return adapterBroker;
- });
+ var adapterFactory = new bluetooth.mojom.AdapterFactoryPtr;
+ Mojo.bindInterface(
+ bluetooth.mojom.AdapterFactory.name,
+ mojo.makeRequest(adapterFactory).handle);
+
+ // Get an Adapter service.
+ return adapterFactory.getAdapter().then(function(response) {
+ if (!response.adapter.ptr.isBound()) {
+ throw new Error('Bluetooth Not Supported on this platform.');
+ }
+
+ adapterBroker = new AdapterBroker(response.adapter);
+ return adapterBroker;
+ });
}
return {
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/adapter_page.js b/chromium/chrome/browser/resources/bluetooth_internals/adapter_page.js
index 98d296a192f..b032be08852 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/adapter_page.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/adapter_page.js
@@ -43,7 +43,7 @@ cr.define('adapter_page', function() {
/**
* Sets the information to display in fieldset.
- * @param {!interfaces.BluetoothAdapter.AdapterInfo} info
+ * @param {!bluetooth.mojom.AdapterInfo} info
*/
setAdapterInfo: function(info) {
this.adapterFieldSet.setObject(info);
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.html b/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.html
index 8ad7e7c7bed..40f1bce873c 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.html
+++ b/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.html
@@ -24,8 +24,11 @@
<link rel="import" href="chrome://resources/html/cr/ui/page_manager/page.html">
<link rel="import" href="chrome://resources/html/util.html">
+ <script src="chrome://resources/js/mojo_bindings.js"></script>
+ <script src="uuid.mojom.js"></script>
+ <script src="device.mojom.js"></script>
+ <script src="adapter.mojom.js"></script>
<script src="snackbar.js"></script>
- <script src="interfaces.js"></script>
<script src="adapter_broker.js"></script>
<script src="device_broker.js"></script>
<script src="object_fieldset.js"></script>
@@ -85,11 +88,11 @@
<table>
<thead>
<tr>
- <th data-field="name_for_display">Name</th>
+ <th data-field="nameForDisplay">Name</th>
<th data-field="address">Address</th>
<th data-field="rssi.value">Latest RSSI</th>
<th data-field="services.length">Services</th>
- <th data-field="is_gatt_connected">GATT Connection State</th>
+ <th data-field="isGattConnected">GATT Connection State</th>
<th></th>
</tr>
</thead>
@@ -111,4 +114,4 @@
</div>
</template>
-</html> \ No newline at end of file
+</html>
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js b/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
index 6eedc5a88cc..ff82b194ed6 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
@@ -30,7 +30,7 @@ cr.define('bluetooth_internals', function() {
/** @type {devices_page.DevicesPage} */
var devicesPage = null;
- /** @type {interfaces.BluetoothAdapter.DiscoverySession.ptrClass} */
+ /** @type {bluetooth.mojom.DiscoverySession.ptrClass} */
var discoverySession = null;
/** @type {boolean} */
@@ -87,7 +87,7 @@ cr.define('bluetooth_internals', function() {
* '#page-container', and adds a sidebar item to show the new page. If a
* page exists that matches |deviceInfo.address|, nothing is created and the
* existing page is returned.
- * @param {!interfaces.BluetoothDevice.Device} deviceInfo
+ * @param {!bluetooth.mojom.Device} deviceInfo
* @return {!device_details_page.DeviceDetailsPage}
*/
function makeDeviceDetailsPage(deviceInfo) {
@@ -125,7 +125,7 @@ cr.define('bluetooth_internals', function() {
sidebarObj.addItem({
pageName: deviceDetailsPageId,
- text: deviceInfo.name_for_display,
+ text: deviceInfo.nameForDisplay,
});
deviceDetailsPage.connect();
@@ -275,9 +275,13 @@ cr.define('bluetooth_internals', function() {
}
function initializeViews() {
- setupPages();
-
- adapter_broker.getAdapterBroker()
+ // window.setupFn() provides a hook for the test suite to perform setup
+ // actions after the page is loaded but before any script is run.
+ window.setupFn()
+ .then(function() {
+ setupPages();
+ return adapter_broker.getAdapterBroker();
+ })
.then(function(broker) {
adapterBroker = broker;
})
@@ -300,5 +304,9 @@ cr.define('bluetooth_internals', function() {
};
});
+window.setupFn = window.setupFn || function() {
+ return Promise.resolve();
+};
+
document.addEventListener(
'DOMContentLoaded', bluetooth_internals.initializeViews);
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js b/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js
index 71d93b8c69c..ecee19eb0fe 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js
@@ -44,7 +44,7 @@ cr.define('characteristic_list', function() {
* properties, 'id' and 'uuid', and one for the 'properties' bitfield in the
* CharacteristicInfo object.
* @constructor
- * @param {!interfaces.BluetoothDevice.CharacteristicInfo} characteristicInfo
+ * @param {!bluetooth.mojom.CharacteristicInfo} characteristicInfo
* @param {string} deviceAddress
* @param {string} serviceId
*/
@@ -53,7 +53,7 @@ cr.define('characteristic_list', function() {
var listItem = new ExpandableListItem();
listItem.__proto__ = CharacteristicListItem.prototype;
- /** @type {!interfaces.BluetoothDevice.CharacteristicInfo} */
+ /** @type {!bluetooth.mojom.CharacteristicInfo} */
listItem.info = characteristicInfo;
/** @private {string} */
listItem.deviceAddress_ = deviceAddress;
@@ -87,7 +87,7 @@ cr.define('characteristic_list', function() {
this.propertiesFieldSet_ = new object_fieldset.ObjectFieldSet();
this.propertiesFieldSet_.setPropertyDisplayNames(
PROPERTIES_PROPERTY_NAMES);
- var Property = interfaces.BluetoothDevice.Property;
+ var Property = bluetooth.mojom.Property;
this.propertiesFieldSet_.setObject({
broadcast: (this.info.properties & Property.BROADCAST) > 0,
read: (this.info.properties & Property.READ) > 0,
@@ -120,7 +120,7 @@ cr.define('characteristic_list', function() {
characteristicId: this.info.id,
properties: this.info.properties,
});
- this.valueControl_.setValue(this.info.last_known_value);
+ this.valueControl_.setValue(this.info.lastKnownValue);
/** @private {!descriptor_list.DescriptorList} */
this.descriptorList_ = new descriptor_list.DescriptorList();
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js b/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js
index 13d646b1147..f68e29069bf 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js
@@ -25,7 +25,7 @@ cr.define('descriptor_list', function() {
* A fieldset is created within the element for the primitive
* properties, 'id' and 'uuid' within the DescriptorInfo object.
* @constructor
- * @param {!interfaces.BluetoothDevice.DescriptorInfo} descriptorInfo
+ * @param {!bluetooth.mojom.DescriptorInfo} descriptorInfo
* @param {string} deviceAddress
* @param {string} serviceId
* @param {string} characteristicId
@@ -35,7 +35,7 @@ cr.define('descriptor_list', function() {
var listItem = new ExpandableListItem();
listItem.__proto__ = DescriptorListItem.prototype;
- /** @type {!interfaces.BluetoothDevice.DescriptorInfo} */
+ /** @type {!bluetooth.mojom.DescriptorInfo} */
listItem.info = descriptorInfo;
/** @private {string} */
listItem.deviceAddress_ = deviceAddress;
@@ -184,4 +184,4 @@ cr.define('descriptor_list', function() {
DescriptorList: DescriptorList,
DescriptorListItem: DescriptorListItem,
};
-}); \ No newline at end of file
+});
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/device_broker.js b/chromium/chrome/browser/resources/bluetooth_internals/device_broker.js
index 5704e5a1a7e..acb551c0662 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/device_broker.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/device_broker.js
@@ -10,7 +10,7 @@
*/
// Expose for testing.
-/** @type {!Map<string, !interfaces.BluetoothDevice.DevicePtr|!Promise} */
+/** @type {!Map<string, !bluetooth.mojom.DevicePtr|!Promise} */
var connectedDevices = null;
cr.define('device_broker', function() {
@@ -22,7 +22,7 @@ cr.define('device_broker', function() {
* DevicePtr. If a connection is in progress, the promise resolves when
* the existing connection request promise is fulfilled.
* @param {string} address
- * @return {!Promise<!interfaces.BluetoothDevice.DevicePtr>}
+ * @return {!Promise<!bluetooth.mojom.DevicePtr>}
*/
function connectToDevice(address) {
var deviceOrPromise = connectedDevices.get(address) || null;
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js b/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js
index 7245f26c2ef..ffec1c491fa 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js
@@ -50,7 +50,7 @@ cr.define('device_collection', function() {
/**
* Adds or updates a Device with new DeviceInfo.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
addOrUpdate: function(deviceInfo) {
deviceInfo.removed = false;
@@ -75,7 +75,7 @@ cr.define('device_collection', function() {
/**
* Marks the Device as removed.
- * @param {!interfaces.bluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
remove: function(deviceInfo) {
var device = this.getByAddress(deviceInfo.address);
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/device_details_page.js b/chromium/chrome/browser/resources/bluetooth_internals/device_details_page.js
index 7a573910768..626b18a5bda 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/device_details_page.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/device_details_page.js
@@ -20,7 +20,7 @@ cr.define('device_details_page', function() {
var PROPERTY_NAMES = {
name: 'Name',
address: 'Address',
- is_gatt_connected: 'GATT Connected',
+ isGattConnected: 'GATT Connected',
'rssi.value': 'Latest RSSI',
'services.length': 'Services',
};
@@ -33,16 +33,16 @@ cr.define('device_details_page', function() {
* compononent that lists all of the active services on the device.
* @constructor
* @param {string} id
- * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
* @extends {cr.ui.pageManager.Page}
*/
function DeviceDetailsPage(id, deviceInfo) {
- Page.call(this, id, deviceInfo.name_for_display, id);
+ Page.call(this, id, deviceInfo.nameForDisplay, id);
- /** @type {interfaces.BluetoothDevice.DeviceInfo} */
+ /** @type !bluetooth.mojom.DeviceInfo} */
this.deviceInfo = deviceInfo;
- /** @private {?interfaces.BluetoothDevice.Device.ptrClass} */
+ /** @private {!bluetooth.mojom.Device.ptrClass} */
this.devicePtr_ = null;
/** @private {!object_fieldset.ObjectFieldSet} */
@@ -118,7 +118,7 @@ cr.define('device_details_page', function() {
}
Snackbar.show(
- this.deviceInfo.name_for_display + ': ' + error.message,
+ this.deviceInfo.nameForDisplay + ': ' + error.message,
SnackbarType.ERROR, 'Retry', this.connect.bind(this));
this.updateConnectionStatus_(
@@ -139,7 +139,7 @@ cr.define('device_details_page', function() {
/** Redraws the contents of the page with the current |deviceInfo|. */
redraw: function() {
- var isConnected = this.deviceInfo.is_gatt_connected;
+ var isConnected = this.deviceInfo.isGattConnected;
// Update status if connection has changed.
if (isConnected)
@@ -161,9 +161,9 @@ cr.define('device_details_page', function() {
serviceCount = services.length;
var deviceViewObj = {
- name: this.deviceInfo.name_for_display,
+ name: this.deviceInfo.nameForDisplay,
address: this.deviceInfo.address,
- is_gatt_connected: connectedText,
+ isGattConnected: connectedText,
'rssi.value': rssiValue,
'services.length': serviceCount,
};
@@ -174,7 +174,7 @@ cr.define('device_details_page', function() {
/**
* Sets the page's device info and forces a redraw.
- * @param {!interfaces.BluetoothDevice.DeviceInfo}
+ * @param {!bluetooth.mojom.DeviceInfo}
*/
setDeviceInfo: function(info) {
this.deviceInfo = info;
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/device_table.js b/chromium/chrome/browser/resources/bluetooth_internals/device_table.js
index 0068e27d123..6fdc7b686f4 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/device_table.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/device_table.js
@@ -43,7 +43,7 @@ cr.define('device_table', function() {
this.body_ = this.tBodies[0];
/** @private */
this.headers_ = this.tHead.rows[0].cells;
- /** @private {!Map<!interfaces.BluetoothDevice.DeviceInfo, boolean>} */
+ /** @private {!Map<!bluetooth.mojom.DeviceInfo, boolean>} */
this.inspectionMap_ = new Map();
},
@@ -66,7 +66,7 @@ cr.define('device_table', function() {
* Updates the inspect status of the row matching the given |deviceInfo|.
* If |isInspecting| is true, the forget link is enabled otherwise it's
* disabled.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
* @param {boolean} isInspecting
*/
setInspecting: function(deviceInfo, isInspecting) {
@@ -130,7 +130,7 @@ cr.define('device_table', function() {
/**
* Inserts a new row at |index| and updates it with info from |device|.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} device
+ * @param {!bluetooth.mojom.DeviceInfo} device
* @param {?number} index
* @private
*/
@@ -182,7 +182,7 @@ cr.define('device_table', function() {
/**
* Updates the row at |index| with the info from |device|.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} device
+ * @param {!bluetooth.mojom.DeviceInfo} device
* @param {number} index
* @private
*/
@@ -215,7 +215,7 @@ cr.define('device_table', function() {
obj = obj[part];
}
- if (propName == 'is_gatt_connected') {
+ if (propName == 'isGattConnected') {
obj = obj ? 'Connected' : 'Not Connected';
}
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/devices_page.js b/chromium/chrome/browser/resources/bluetooth_internals/devices_page.js
index 39c72a778a8..3c62fd70e5a 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/devices_page.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/devices_page.js
@@ -51,7 +51,7 @@ cr.define('devices_page', function() {
/**
* Updates the inspect status of the given |deviceInfo| in the device table.
- * @param {!interfaces.BluetoothDevice.DeviceInfo} deviceInfo
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
* @param {boolean} isInspecting
*/
setInspecting: function(deviceInfo, isInspecting) {
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/interfaces.js b/chromium/chrome/browser/resources/bluetooth_internals/interfaces.js
deleted file mode 100644
index 5bec864ca04..00000000000
--- a/chromium/chrome/browser/resources/bluetooth_internals/interfaces.js
+++ /dev/null
@@ -1,45 +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.
-
-/**
- * Javascript for Mojo interface helpers, served from
- * chrome://bluetooth-internals/.
- */
-
-cr.define('interfaces', function() {
- /**
- * Overriden by tests to give them a chance to setup a fake Mojo browser proxy
- * before any other code executes.
- * @return {!Promise} A promise firing once necessary setup has been completed.
- */
- var setupFn = window.setupFn || function() {
- return Promise.resolve();
- };
-
- /**
- * Sets up Mojo interfaces and adds them to window.interfaces.
- * @return {Promise}
- */
- function setupInterfaces() {
- return setupFn().then(function() {
- return importModules([
- 'content/public/renderer/frame_interfaces',
- 'device/bluetooth/public/interfaces/adapter.mojom',
- 'device/bluetooth/public/interfaces/device.mojom',
- 'mojo/public/js/bindings',
- ])
- .then(function(
- [frameInterfaces, bluetoothAdapter, bluetoothDevice, bindings]) {
- interfaces.BluetoothAdapter = bluetoothAdapter;
- interfaces.BluetoothDevice = bluetoothDevice;
- interfaces.Bindings = bindings;
- interfaces.FrameInterfaces = frameInterfaces;
- });
- });
- }
-
- return {
- setupInterfaces: setupInterfaces,
- };
-});
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/service_list.js b/chromium/chrome/browser/resources/bluetooth_internals/service_list.js
index 60df11061dc..b58ec6d4cb6 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/service_list.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/service_list.js
@@ -21,7 +21,7 @@ cr.define('service_list', function() {
var PROPERTY_NAMES = {
id: 'ID',
'uuid.uuid': 'UUID',
- is_primary: 'Type',
+ isPrimary: 'Type',
};
/**
@@ -30,7 +30,7 @@ cr.define('service_list', function() {
* contains an ObjectFieldSet that displays all of the properties in the
* given |serviceInfo|. Data is not loaded until the ServiceListItem is
* expanded for the first time.
- * @param {!interfaces.BluetoothDevice.ServiceInfo} serviceInfo
+ * @param {!bluetooth.mojom.ServiceInfo} serviceInfo
* @param {string} deviceAddress
* @constructor
*/
@@ -38,7 +38,7 @@ cr.define('service_list', function() {
var listItem = new ExpandableListItem();
listItem.__proto__ = ServiceListItem.prototype;
- /** @type {!interfaces.BluetoothDevice.ServiceInfo} */
+ /** @type {!bluetooth.mojom.ServiceInfo} */
listItem.info = serviceInfo;
/** @private {string} */
listItem.deviceAddress_ = deviceAddress;
@@ -64,7 +64,7 @@ cr.define('service_list', function() {
this.serviceFieldSet_.setObject({
id: this.info.id,
'uuid.uuid': this.info.uuid.uuid,
- is_primary: this.info.is_primary ? 'Primary' : 'Secondary',
+ isPrimary: this.info.isPrimary ? 'Primary' : 'Secondary',
});
// Create content for display in brief content container.
@@ -171,4 +171,4 @@ cr.define('service_list', function() {
ServiceList: ServiceList,
ServiceListItem: ServiceListItem,
};
-}); \ No newline at end of file
+});
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/value_control.js b/chromium/chrome/browser/resources/bluetooth_internals/value_control.js
index 04b5a4aabed..69dfc188cf8 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/value_control.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/value_control.js
@@ -293,9 +293,9 @@ cr.define('value_control', function() {
*/
redraw: function() {
this.readBtn_.hidden =
- (this.properties_ & interfaces.BluetoothDevice.Property.READ) === 0;
+ (this.properties_ & bluetooth.mojom.Property.READ) === 0;
this.writeBtn_.hidden =
- (this.properties_ & interfaces.BluetoothDevice.Property.WRITE) === 0;
+ (this.properties_ & bluetooth.mojom.Property.WRITE) === 0;
var isAvailable = !this.readBtn_.hidden || !this.writeBtn_.hidden;
this.unavailableMessage_.hidden = isAvailable;
@@ -319,13 +319,13 @@ cr.define('value_control', function() {
/**
* Gets an error string describing the given |result| code.
- * @param {!interfaces.BluetoothDevice.GattResult} result
+ * @param {!bluetooth.mojom.GattResult} result
* @private
*/
getErrorString_: function(result) {
// TODO(crbug.com/663394): Replace with more descriptive error
// messages.
- var GattResult = interfaces.BluetoothDevice.GattResult;
+ var GattResult = bluetooth.mojom.GattResult;
return Object.keys(GattResult).find(function(key) {
return GattResult[key] === result;
});
@@ -354,8 +354,7 @@ cr.define('value_control', function() {
.then(function(response) {
this.readBtn_.disabled = false;
- if (response.result ===
- interfaces.BluetoothDevice.GattResult.SUCCESS) {
+ if (response.result === bluetooth.mojom.GattResult.SUCCESS) {
this.setValue(response.value);
Snackbar.show(
this.deviceAddress_ + ': Read succeeded',
@@ -395,8 +394,7 @@ cr.define('value_control', function() {
.then(function(response) {
this.writeBtn_.disabled = false;
- if (response.result ===
- interfaces.BluetoothDevice.GattResult.SUCCESS) {
+ if (response.result === bluetooth.mojom.GattResult.SUCCESS) {
Snackbar.show(
this.deviceAddress_ + ': Write succeeded',
SnackbarType.SUCCESS);
@@ -415,4 +413,4 @@ cr.define('value_control', function() {
ValueControl: ValueControl,
ValueDataType: ValueDataType,
};
-}); \ No newline at end of file
+});
diff --git a/chromium/chrome/browser/resources/bookmark_manager/css/bmm.css b/chromium/chrome/browser/resources/bookmark_manager/css/bmm.css
index adef2e44e21..a550ec56d1f 100644
--- a/chromium/chrome/browser/resources/bookmark_manager/css/bmm.css
+++ b/chromium/chrome/browser/resources/bookmark_manager/css/bmm.css
@@ -59,7 +59,7 @@ list .label-img-wrapper {
z-index: -1;
}
-<if expr="not is_macosx and not is_ios">
+<if expr="not is_macosx">
html[dir=rtl] list > .folder .label-img-wrapper > * {
transform: scaleX(-1);
}
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn
index 5f75f2aaf29..6e5018a8af0 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/config/features.gni")
import("//chrome/common/features.gni")
+import("//components/nacl/features.gni")
import("//testing/test.gni")
import("//chrome/test/base/js2gtest.gni")
import("run_jsbundler.gni")
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 c08ebdc2bf8..76b4836f627 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
@@ -449,16 +449,6 @@
}
},
{
- "command": "toggleChromeVoxVersion",
- "sequence": {
- "cvoxModifier": true,
- "keys": {
- "keyCode": [81],
- "shitKey": [true]
- }
- }
- },
- {
"command": "toggleStickyMode",
"sequence": {
"doubleTap": true,
@@ -932,6 +922,24 @@
"keyCode": [119]
}
}
+ },
+ {
+ "command": "enableChromeVoxArcSupportForCurrentApp",
+ "sequence": {
+ "cvoxModifier": true,
+ "keys": {
+ "keyCode": [65, 219]
+ }
+ }
+ },
+ {
+ "command": "disableChromeVoxArcSupportForCurrentApp",
+ "sequence": {
+ "cvoxModifier": true,
+ "keys": {
+ "keyCode": [65, 221]
+ }
+ }
}
]
}
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
index 7a76f8bdf2d..dbbb3c6f00a 100644
--- a/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
+++ b/chromium/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -2533,22 +2533,12 @@
<message desc="Title of a notification that ChromeVox has been updated." name="IDS_CHROMEVOX_UPDATE_TITLE">
ChromeVox Updated
</message>
- <message desc="Message text for a notification that ChromeVox has been updated for a new experience." name="IDS_CHROMEVOX_UPDATE_MESSAGE_NEXT">
- Press ChromeVox o, n to learn more about ChromeVox Next.
+ <message desc="Message text for a notification that ChromeVox has been updated for a new release." name="IDS_CHROMEVOX_UPDATE_MESSAGE_NEW">
+ Press ChromeVox o, n to find out what's new
</message>
<message desc="Options page description for the command to show ChromeVox's update page." name="IDS_CHROMEVOX_SHOW_NEXT_UPDATE_DESCRIPTION">
Show update notes
</message>
- <message desc="Checkbox label for toggling on/off ChromeVox's new beta experience." name="IDS_CHROMEVOX_OPTIONS_USE_NEXT_LABEL">
- Use ChromeVox Next (beta)
- </message>
- <message desc="Spoken when switching to the classic ChromeVox experience." name="IDS_CHROMEVOX_SWITCH_TO_CLASSIC">
- Switched to Classic ChromeVox
- </message>
- <message desc="Spoken when switching to the new beta experience." name="IDS_CHROMEVOX_SWITCH_TO_NEXT">
- Switched to ChromeVox Next
- </message>
-
<message desc="Description of button that closes the ChromeVox Tutorial" name="IDS_CHROMEVOX_CLOSE_TUTORIAL">
Close ChromeVox Tutorial
</message>
@@ -2558,11 +2548,11 @@
<message desc="Button that goes to the next page in the ChromeVox Tutorial" name="IDS_CHROMEVOX_TUTORIAL_NEXT">
Next
</message>
- <message desc="Heading that welcomes users to the ChromeVox Next tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_HEADING">
- Welcome to ChromeVox Next!
+ <message desc="Heading that welcomes users to the ChromeVox tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_HEADING">
+ Welcome to ChromeVox!
</message>
- <message desc="Introductory text for the 'ChromeVox Next' tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_TEXT">
- Are you using ChromeVox Next spoken feedback for the first time? This quick tutorial explains the essentials for getting started with ChromeVox Next.
+ <message desc="Introductory text for the 'ChromeVox' tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_TEXT">
+ Are you using ChromeVox spoken feedback for the first time? This quick tutorial explains the essentials for getting started with ChromeVox.
</message>
<message desc="Text that tells users to press the enter key to move to the next page or backspace to move to the previous page in the tutorial" name="IDS_CHROMEVOX_TUTORIAL_ENTER_TO_ADVANCE">
To advance, press enter; to go back, press backspace.
@@ -2580,7 +2570,7 @@
The ChromeVox modifier key
</message>
<message desc="Text explaining that the Search key on the keyboard will be held down for most ChromeVox shortcuts" name="IDS_CHROMEVOX_TUTORIAL_MODIFIER">
- In ChromeVox Next, the Search key is the modifier key. Most ChromeVox shortcuts start with the Search key. You’ll also use the arrow keys for navigation.
+ In ChromeVox, the Search key is the modifier key. Most ChromeVox shortcuts start with the Search key. You’ll also use the arrow keys for navigation.
</message>
<message desc="Text explaining where to find the Search key on a Chromebook keyboard" name="IDS_CHROMEVOX_TUTORIAL_CHROMEBOOK_SEARCH">
On the Chromebook, the Search key is immediately above the left Shift key.
@@ -2634,29 +2624,29 @@ To open the Chrome browser menu, press Alt+F.
Learn More
</message>
<message desc="Part of the ChromeVox tutorial, explaining that this is the end of the tutorial and that there are links to more information." name="IDS_CHROMEVOX_TUTORIAL_LEARN_MORE">
- Congratulations! You’ve learned the essentials to use ChromeVox Next (beta) successfully. Remember that you can open the ChromeVox command menu at any time by pressing Search+Period. To learn even more about ChromeVox and Chrome OS, visit the following articles.
+ Congratulations! You’ve learned the essentials to use ChromeVox successfully. Remember that you can open the ChromeVox command menu at any time by pressing Search+Period. To learn even more about ChromeVox and Chrome OS, visit the following articles.
If you're done with the tutorial, use ChromeVox to navigate to the Close button and click it.
</message>
- <message desc="Part of the ChromeVox update notes for m56, title." name="IDS_CHROMEVOX_UPDATE_56_TITLE">
- You've been updated to a major new release of ChromeVox!
+ <message desc="Part of the ChromeVox update notes for m63, title." name="IDS_CHROMEVOX_UPDATE_63_TITLE">
+ You've been updated to ChromeVox 63!
</message>
- <message desc="Part of the ChromeVox update notes for m56, introductory text." name="IDS_CHROMEVOX_UPDATE_56_INTRO">
- We've been hard at work on a new and improved ChromeVox experience; here's what's new
+ <message desc="Part of the ChromeVox update notes for m63, introductory text." name="IDS_CHROMEVOX_UPDATE_63_INTRO">
+ We have some exciting changes in this new release; here's what's new:
</message>
- <message desc="Part of the ChromeVox update notes for m56, new items 1." name="IDS_CHROMEVOX_UPDATE_56_ITEM_1">
- New key bindings. We've made Search the ChromeVox modifier and dramatically simplified the key combinations.
+ <message desc="Part of the ChromeVox update notes for 63, new items 1." name="IDS_CHROMEVOX_UPDATE_63_ITEM_1">
+ Classic removed. The keyboard toggle to switch back into ChromeVox Classic has been removed.
</message>
- <message desc="Part of the ChromeVox update notes for m56, new items 2." name="IDS_CHROMEVOX_UPDATE_56_ITEM_2">
- New earcons. We've refreshed the set of audio icons you hear to make browsing more responsive.
+ <message desc="Part of the ChromeVox update notes for m63, new items 2." name="IDS_CHROMEVOX_UPDATE_63_ITEM_2">
+ Rich text support. ChromeVox now supports rich text fields including jump commands, braille cursor routing, selection, and more.
</message>
- <message desc="Part of the ChromeVox update notes for m56, new items 3." name="IDS_CHROMEVOX_UPDATE_56_ITEM_3">
- Under the hood upgrades. We've revamped how ChromeVox works from the bottom up. Expect better performance, stability, and web support/compliance.
+ <message desc="Part of the ChromeVox update notes for m63, new items 3." name="IDS_CHROMEVOX_UPDATE_63_ITEM_3">
+ Android apps for Chrome. If you have Play Store on your device, get a sneak peek at ChromeVox with Android apps. Try the experimental support by downloading Google Chrome Canary from the Play Store.
</message>
- <message desc="Part of the ChromeVox update notes for m56, closing paragraph." name="IDS_CHROMEVOX_UPDATE_56_OUTTRO">
- We're excited to hear from you on this new experience. Send us feedback directly by pressing Search+a, then i. Press the next button to continue onto the tutorial to learn everything you need to get started.
+ <message desc="Part of the ChromeVox update notes for m63, closing paragraph." name="IDS_CHROMEVOX_UPDATE_63_OUTTRO">
+ As always, you can send us feedback directly by pressing Search+a then i. We're eager to hear from you.
</message>
- <message desc="Title of an article on the command reference for 'ChromeVox Next'" name="IDS_CHROMEVOX_NEXT_COMMAND_REFERENCE">
- ChromeVox Next Command Reference
+ <message desc="Title of an article on the command reference for 'ChromeVox'" name="IDS_CHROMEVOX_NEXT_COMMAND_REFERENCE">
+ ChromeVox Command Reference
</message>
<message desc="Title of an article on keyboard shortcuts for Chromebooks" name="IDS_CHROMEVOX_CHROME_KEYBOARD_SHORTCUTS">
Chromebook keyboard shortcuts
@@ -2790,6 +2780,9 @@ If you're done with the tutorial, use ChromeVox to navigate to the Close button
<message desc="Shown to a user when they press a braille keyboard command that requires on screen keyboard to be enabled." name="IDS_CHROMEVOX_ENABLE_VIRTUAL_KEYBOARD">
Please enable the on screen keyboard under status tray, accessibility to use extended braille commands.
</message>
+ <message desc="Shown to a user when they invoke the read current title command in a context without a title." name="IDS_CHROMEVOX_NO_TITLE">
+ No title
+ </message>
</messages>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/chromeos/compiled_resources2.gyp b/chromium/chrome/browser/resources/chromeos/compiled_resources2.gyp
index e166fcf476d..20fea0a35fc 100644
--- a/chromium/chrome/browser/resources/chromeos/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/chromeos/compiled_resources2.gyp
@@ -16,6 +16,20 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'internet_config_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp:network_config',
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_network_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(EXTERNS_GYP):chrome_send',
+ '<(EXTERNS_GYP):networking_private',
+ '<(INTERFACES_GYP):networking_private_interface',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'internet_detail_dialog',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
diff --git a/chromium/chrome/browser/resources/chromeos/sys_internals/compiled_resources2.gyp b/chromium/chrome/browser/resources/chromeos/sys_internals/compiled_resources2.gyp
new file mode 100644
index 00000000000..64b7192275a
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/sys_internals/compiled_resources2.gyp
@@ -0,0 +1,36 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'index',
+ 'dependencies': [
+ 'constants',
+ 'externs',
+ 'types',
+ 'line_chart/compiled_resources2.gyp:*',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'constants',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'externs',
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'types',
+ 'dependencies': [
+ 'line_chart/compiled_resources2.gyp:data_series',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/compiled_resources2.gyp b/chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/compiled_resources2.gyp
new file mode 100644
index 00000000000..a968ea8f1b0
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/compiled_resources2.gyp
@@ -0,0 +1,63 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'line_chart',
+ 'dependencies': [
+ 'sub_chart',
+ 'data_series',
+ 'scrollbar',
+ 'menu',
+ 'constants',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'sub_chart',
+ 'dependencies': [
+ 'unit_label',
+ 'data_series',
+ 'constants',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'scrollbar',
+ 'dependencies': [
+ 'constants',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'unit_label',
+ 'dependencies': [
+ 'constants',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'menu',
+ 'dependencies': [
+ 'constants',
+ 'data_series',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'data_series',
+ 'dependencies': [
+ 'constants',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'constants',
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn b/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
index 68fc2b9ee76..94edb33f30c 100644
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
@@ -27,7 +27,6 @@ copy("zip_archiver_css") {
copy("zip_archiver_html") {
sources = [
- "html/compressor.html",
"html/passphrase-dialog.html",
"html/passphrase.html",
]
@@ -56,9 +55,10 @@ copy("zip_archiver_js") {
"js/app.js",
"js/background.js",
"js/build-config.js",
- "js/compressor-foreground.js",
"js/compressor.js",
"js/decompressor.js",
+ "js/file_operation_utils.js",
+ "js/main.js",
"js/passphrase-dialog.js",
"js/passphrase-manager.js",
"js/request.js",
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ar/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ar/messages.json
deleted file mode 100644
index 78454c10907..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ar/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "أداة فتح ملفات ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "فتح ملفات ZIP في تطبيق \"الملفات\".",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "أخفق فتح الأرشيف.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "تم تحميل الأرشيف فعلاً.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "تنسيق الأرشيف غير متوافق، أو الملف تالف.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "الرجاء الانتظار، جارٍ فحص الأرشيف...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "هذا الملف محمي بكلمة المرور",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "كلمة المرور",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "قبول",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "إلغاء",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "تذكر",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/bg/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/bg/messages.json
deleted file mode 100644
index fbebba08e62..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/bg/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Разширение за разпакетиране на ZIP файлове",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Отваряне на ZIP файлове в приложението Файлове.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Отварянето на архив не бе успешно.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Архивът вече е свързан.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Форматът на архива не се поддържа или файлът е невалиден.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Моля, изчакайте. Архивът се сканира...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Този файл е защитен с парола",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Парола",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Приемам",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Отказ",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Запомняне",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ca/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ca/messages.json
deleted file mode 100644
index 672e463f249..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ca/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Descompressor ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Obriu els fitxers ZIP a l'aplicació Fitxers.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "S'ha produït un error en obrir un arxiu.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "L'arxiu ja està activat.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "El format de l'arxiu no s'admet, o bé el fitxer està malmès.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Espereu, s'està analitzant l'arxiu...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "El fitxer està protegit amb contrasenya",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Contrasenya",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Accepta",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Cancel·la",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Recorda",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/cs/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/cs/messages.json
deleted file mode 100644
index b3de9697653..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/cs/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Rozbalování souborů ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Otevírejte soubory ZIP v aplikaci Soubory.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Archiv se nepodařilo otevřít.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Archiv je již připojen.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Formát archivu není podporován nebo je soubor poškozen.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Čekejte prosím, probíhá prohledávání archivu...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Soubor je chráněn heslem",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Heslo",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Přijmout",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Zrušit",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Zapamatovat",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/da/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/da/messages.json
deleted file mode 100644
index 0a067817c28..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/da/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP-åbning",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Åbn ZIP-filer i appen Filer.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Et arkiv kunne ikke åbnes.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arkivet er allerede tilsluttet.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Arkivformatet understøttes ikke, eller filen er beskadiget.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Et øjeblik, arkivet scannes…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Denne fil er beskyttet med adgangskode",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Adgangskode",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Acceptér",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Annuller",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Husk",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/de/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/de/messages.json
deleted file mode 100644
index fbd1100b8e6..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/de/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP-Datei-Entpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "ZIP-Dateien in App \"Dateien\" öffnen",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Ein Archiv konnte nicht geöffnet werden.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Das Archiv ist schon bereitgestellt.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Das Archivformat wird nicht unterstützt oder die Datei ist fehlerhaft.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Das Archiv wird geprüft. Bitte warten...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Diese Datei ist passwortgeschützt.",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Passwort",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Akzeptieren",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Abbrechen",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Merken",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/el/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/el/messages.json
deleted file mode 100644
index 6d0a376b013..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/el/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Αποσυμπιεστής ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Άνοιγμα αρχείων ZIP στην εφαρμογή \"Αρχεία\".",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Απέτυχε το άνοιγμα ενός αρχείου.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Το αρχείο προσαρτήθηκε ήδη.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Η μορφή του αρχείου δεν υποστηρίζεται ή το αρχείο είναι κατεστραμμένο.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Περιμένετε, γίνεται σάρωση του αρχείου…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Αυτό το αρχείο προστατεύεται με κωδικό πρόσβασης",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Κωδικός πρόσβασης",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Αποδοχή",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Άκυρο",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Απομνημόνευση",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en/messages.json
deleted file mode 100644
index d59b942b395..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Open ZIP files in Files app.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Failed to open an archive.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "The archive is already mounted.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "The archive format is not supported, or the file is broken.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Please wait, the archive is being scanned...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "This file is password protected",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Password",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Accept",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Cancel",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Remember",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-}
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en_GB/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en_GB/messages.json
deleted file mode 100644
index 5d2c37199b3..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/en_GB/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Open ZIP files in Files app.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Failed to open an archive.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "The archive is already mounted.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "The archive format is not supported, or the file is broken.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Please wait, the archive is being scanned...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "This file is password protected",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Password",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Accept",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Cancel",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Remember",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es/messages.json
deleted file mode 100644
index f8f85fd9c31..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Descompresor ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Abre archivos ZIP en la aplicación Archivos.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Error al abrir el archivo.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "El archivo ya está activado.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "El formato del archivo no es compatible o el archivo está dañado.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Espera, se está analizando el archivo...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Este archivo está protegido por contraseña",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Contraseña",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Aceptar",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Cancelar",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Recordar",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es_419/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es_419/messages.json
deleted file mode 100644
index c86051e12b1..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/es_419/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Abre archivos ZIP en la aplicación Archivos.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Error al abrir un archivo",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Ya se montó el archivo.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "El formato de archivo no es compatible o el archivo está dañado.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Espera, se está analizando el archivo…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Este archivo está protegido por contraseña",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Contraseña",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Aceptar",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Cancelar",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Recordar",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/et/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/et/messages.json
deleted file mode 100644
index 4239a246148..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/et/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP-lahtipakkija",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "ZIP-failide avamine rakenduses Failid.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Arhiivi avamine ebaõnnestus.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arhiiv on juba ühendatud.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Arhiivi formaati ei toetata või on fail katki.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Oodake, arhiivi skannitakse ...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "See fail on parooliga kaitstud",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Parool",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Nõustu",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Tühista",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Pea meeles",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fa/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fa/messages.json
deleted file mode 100644
index a353dde68c3..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fa/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "بازکننده ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "فایل‌های ZIP را در برنامه Files باز کنید.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "بایگانی باز نشد.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "بایگانی قبلاً نشانده شده است.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "قالب بایگانی پشتیبانی نمی‌شود یا فایل خراب است.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "لطفاً صبر کنید، بایگانی در حال اسکن شدن است...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "این فایل با گذرواژه محافظت می‌شود",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "گذرواژه",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "پذیرش",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "لغو",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "به خاطر سپردن",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fi/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fi/messages.json
deleted file mode 100644
index cd7f2413ee8..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fi/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP-purkaja",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Avaa ZIP-tiedostot Tiedostot-sovelluksessa.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Arkiston avaaminen epäonnistui.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arkisto on jo otettu käyttöön.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Tätä arkistomuotoa ei tueta tai tiedosto ei toimi.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Odota hetki, arkistoa tarkistetaan…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Tämä tiedosto on suojattu salasanalla.",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Salasana",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Hyväksy",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Peruuta",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Muista",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fil/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fil/messages.json
deleted file mode 100644
index 4fc2c70b781..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fil/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Magbukas ng mga ZIP file sa Files app.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Hindi nakapagbukas ng isang archive.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Na-mount na ang archive.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Hindi sinusuportahan ang format ng archive o sira ang file.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Mangyaring maghintay, ini-scan ang archive...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Pinoprotektahan ng password ang file na ito",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Password",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Tanggapin",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Kanselahin",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Tandaan",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fr/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fr/messages.json
deleted file mode 100644
index b39038e5296..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/fr/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Ouvrir les fichiers ZIP dans l'application Fichiers",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Échec de l'ouverture d'une archive",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "L'archive est déjà installée.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Le format de l'archive n'est pas compatible, ou le fichier est endommagé.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Veuillez patienter, l'archive est en cours d'analyse…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Ce fichier est protégé par un mot de passe",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Mot de passe",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Accepter",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Annuler",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Mémoriser",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/he/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/he/messages.json
deleted file mode 100644
index 0e805e163a6..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/he/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "פתח קובצי ZIP ביישום 'קבצים'.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "פתיחת ארכיון נכשלה.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "הארכיון כבר נטען.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "פורמט הארכיון אינו נתמך, או שהקובץ פגום.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "המתן בזמן שהארכיון נסרק...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "הקובץ הזה מוגן באמצעות סיסמה",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "סיסמה",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "קבל",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "בטל",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "זכור",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hi/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hi/messages.json
deleted file mode 100644
index c1d6330bcb8..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hi/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ज़िप अनपैकर",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "फ़ाइलें ऐप में ज़िप फ़ाइलें खोलें",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "संग्रह को खोलने में विफल रहा.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "संग्रह पहले से माउंट किया हुआ है.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "संग्रह का प्रारूप समर्थित नहीं है या फ़ाइल त्रुटिपूर्ण है.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "कृपया प्रतीक्षा करें, संग्रह स्‍कैन किया जा रहा है...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "यह फ़ाइल पासवर्ड द्वारा सुरक्षित है",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "पासवर्ड",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "स्वीकार करें",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "रहने दें",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "याद रखें",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hr/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hr/messages.json
deleted file mode 100644
index 1f8bc04bee7..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hr/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Alat za otvaranje ZIP datoteka",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Otvaranje ZIP datoteka u aplikaciji Datoteke.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Otvaranje arhive nije uspjelo.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arhiva je već učitana.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Oblik arhive nije podržan ili je datoteka oštećena.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Pričekajte, arhiva se skenira...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Datoteka je zaštićena zaporkom",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Zaporka",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Prihvaćam",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Odustani",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Zapamti",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hu/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hu/messages.json
deleted file mode 100644
index 225066cb7e7..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/hu/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP-kicsomagoló",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "ZIP-fájlok megnyitása a Fájlok alkalmazásban.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Nem sikerült megnyitni egy archív elemet.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Az archív elem már be van töltve.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Az archív elem formátuma nem támogatott, vagy hibás a fájl.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Kérjük, várjon. Az archívum beolvasása folyamatban van…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "A fájl jelszóval védett",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Jelszó",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Elfogadás",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Mégse",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Jegyezze meg",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/id/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/id/messages.json
deleted file mode 100644
index 6604927e781..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/id/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Membuka file ZIP di aplikasi File.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Gagal membuka arsip.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arsip telah terpasang.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Format arsip tidak didukung atau file rusak.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Tunggu, arsip sedang dipindai...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "File ini dilindungi sandi",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Sandi",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Terima",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Batal",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Ingat",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/it/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/it/messages.json
deleted file mode 100644
index da83efcc6b2..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/it/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Apri file ZIP nell'app File.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Apertura di un archivio non riuscita.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "L'archivio è già stato montato.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Il formato dell'archivio non è supportato oppure il file è danneggiato.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Attendi, è in corso la scansione dell'archivio...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Il file è protetto da password",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Password",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Accetta",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Annulla",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Ricorda",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ja/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ja/messages.json
deleted file mode 100644
index 551e0baf1e8..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ja/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP 解凍",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "ZIP ファイルをファイルアプリで開きます。",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "アーカイブを開けませんでした。",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "アーカイブはマウント済みです。",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "アーカイブ形式がサポートされていないか、ファイルが破損しています。",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "アーカイブをスキャンしています。しばらくお待ちください...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "パスワードで保護されたファイル",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "パスワード",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "承認",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "キャンセル",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "パスワードを保存",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ko/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ko/messages.json
deleted file mode 100644
index 51417dfed39..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ko/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP 압축 해제 프로그램",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "파일 앱에서 ZIP 파일 열기",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "보관 파일을 열지 못했습니다.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "보관 파일이 이미 마운트되어 있습니다.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "보관 파일이 지원되지 않는 형식이거나 파일이 손상되었습니다.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "잠시 기다려 주세요. 보관 파일을 검사하는 중입니다.",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "파일이 비밀번호로 보호되어 있습니다.",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "비밀번호",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "수락",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "취소",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "저장",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lt/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lt/messages.json
deleted file mode 100644
index b4b9c161bd2..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lt/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP išpakavimo programa",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Atidarykite ZIP failus naudodami programą „Failai“.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Nepavyko atidaryti archyvo.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Archyvas jau įdėtas.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Archyvo formatas nepalaikomas arba failas yra sugadintas.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Palaukite, archyvas nuskaitomas...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Šis failas apsaugotas slaptažodžiu",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Slaptažodis",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Sutikti",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Atšaukti",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Prisiminti",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lv/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lv/messages.json
deleted file mode 100644
index 0882e86bc88..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/lv/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP izguvējs",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Atveriet ZIP failus lietotnē Faili.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Neizdevās atvērt arhīvu.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arhīvs jau ir iekļauts.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Arhīva formāts netiek atbalstīts, vai fails ir bojāts.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Lūdzu, uzgaidiet, kamēr notiek arhīva pārbaude...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Šis fails ir aizsargāts ar paroli",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Parole",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Pieņemt",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Atcelt",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Atcerēties",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ms/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ms/messages.json
deleted file mode 100644
index 8537a84f3cd..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ms/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Penyahpadat ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Buka fail ZIP dalam apl Fail.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Gagal membuka arkib.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arkib sudah dilekapkan.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Format arkib tidak disokong atau fail rosak.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Sila tunggu, arkib sedang diimbas…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Fail ini dilindungi kata laluan",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Kata laluan",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Terima",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Batal",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Ingat",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/nl/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/nl/messages.json
deleted file mode 100644
index dd970539829..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/nl/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP-uitpakker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Open zipbestanden in de app Bestanden.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Kan een archief niet openen.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Het archief is al gekoppeld.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "De archiefindeling wordt niet ondersteund of het bestand is beschadigd.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Het archief wordt gescand. Een ogenblik geduld…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Dit bestand is beveiligd met een wachtwoord",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Wachtwoord",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Accepteren",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Annuleren",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Onthouden",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/no/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/no/messages.json
deleted file mode 100644
index cd5f57bc19d..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/no/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP-utpakker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Åpne ZIP-filer i Filer-appen.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Et arkiv kunne ikke åpnes.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arkivet er allerede åpnet.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Arkivformatet støttes ikke, eller filen er ødelagt.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Vent litt – arkivet skannes …",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Denne filen er passordbeskyttet.",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Passord",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Godta",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Avbryt",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Husk",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pl/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pl/messages.json
deleted file mode 100644
index ae8556eca7a..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pl/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Program do rozpakowywania plików ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Otwieraj pliki ZIP w aplikacji Pliki.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Nie udało się otworzyć archiwum.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Archiwum zostało już podłączone.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Format archiwum nie jest obsługiwany albo plik jest uszkodzony.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Zaczekaj, trwa skanowanie archiwum...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Ten plik jest chroniony hasłem",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Hasło",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Zaakceptuj",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Anuluj",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Pamiętaj",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_BR/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_BR/messages.json
deleted file mode 100644
index 01dbfe87349..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_BR/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Abra arquivos ZIP no app \"Arquivos\".",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Falha ao abrir um arquivo.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "O arquivo já está ativado.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "O formato do arquivo não é compatível ou o arquivo está corrompido.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Aguarde. O arquivo está sendo verificado...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Este arquivo é protegido por senha",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Senha",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Aceitar",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Cancelar",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Lembrar",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_PT/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_PT/messages.json
deleted file mode 100644
index dc86b5aac07..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/pt_PT/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP unpacker",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Abre ficheiros ZIP na aplicação Ficheiros.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Falha ao abrir um arquivo.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "O arquivo já está montado.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "O formato do arquivo não é suportado ou o ficheiro está danificado.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Aguarde enquanto o arquivo está a ser analisado...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Este ficheiro está protegido por palavra-passe",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Palavra-passe",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Aceitar",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Cancelar",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Memorizar",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ro/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ro/messages.json
deleted file mode 100644
index 3f7ec88107a..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ro/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Dezarhivator ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Deschideți fișiere ZIP în aplicația Fișiere.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Arhiva nu a putut fi deschisă.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arhiva este deja montată.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Formatul arhivei nu este acceptat sau fișierul este deteriorat.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Așteptați, se scanează arhiva...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Fișierul este protejat prin parolă",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Parolă",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Acceptați",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Anulați",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Reține",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ru/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ru/messages.json
deleted file mode 100644
index 5bba0e0fff7..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/ru/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Распаковщик ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Открывает ZIP-архивы в приложении \"Файлы\".",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Не удалось открыть архив",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Архив уже существует.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Архив поврежден, или его формат не поддерживается.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Сканирование архива...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Файл защищен паролем",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Пароль",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "ОК",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Отмена",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Запомнить",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sk/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sk/messages.json
deleted file mode 100644
index 18b16d80cd3..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sk/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Rozbaľovanie priečinkov ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Otvárajte súbory ZIP v aplikácii Súbory.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Archív sa nepodarilo otvoriť",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Archív je už pripojený",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Formát archívu nie je podporovaný alebo je súbor poškodený",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Čakajte, prehľadáva sa archív...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Súbor je chránený heslom",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Heslo",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Prijať",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Zrušiť",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Zapamätať",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sl/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sl/messages.json
deleted file mode 100644
index 9ba38b9dc06..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sl/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Razširitev za odpiranje arhivov ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Odpiranje datotek ZIP v aplikaciji Datoteke.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Arhiva ni bilo mogoče odpreti.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arhiv je že vpet.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Oblika zapisa arhiva ni podprta ali pa je datoteka poškodovana.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Počakajte, poteka preverjanje arhiva ...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Ta datoteka je zaščitena z geslom",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Geslo",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Sprejmi",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Prekliči",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Shrani",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sr/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sr/messages.json
deleted file mode 100644
index 58711406c26..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sr/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP отпакивач",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Отварајте ZIP датотеке у апликацији Датотеке.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Отварање архиве није успело.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Архива је већ учитана",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Формат архиве није подржан или је датотека оштећена.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Сачекајте, архива се скенира...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Ова датотека је заштићена лозинком",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Лозинка",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Прихвати",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Откажи",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Запамти",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sv/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sv/messages.json
deleted file mode 100644
index 7264c317aa0..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/sv/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Uppackningsverktyg för zip-filer",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Öppna zip-filer i appen Filer.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Det gick inte att öppna arkivet.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arkivet har redan monterats.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Arkivformatet stöds inte, eller så är filen trasig.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Arkivet läses in. Vänta ...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Filen är lösenordsskyddad",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Lösenord",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Tacka ja",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Avbryt",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Kom ihåg",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/th/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/th/messages.json
deleted file mode 100644
index 05af54ecce1..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/th/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "โปรแกรมเปิดไฟล์ ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "เปิดไฟล์ ZIP ในแอป Files",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "ไม่สามารถเปิดไฟล์",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "ไฟล์นี้เปิดอยู่แล้ว",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "ไม่สนับสนุนไฟล์รูปแบบนี้ หรือไฟล์เสียหาย",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "โปรดรอสักครู่ ระบบกำลังสแกนไฟล์...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "ไฟล์นี้มีการป้องกันด้วยรหัสผ่าน",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "รหัสผ่าน",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "ยอมรับ",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "ยกเลิก",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "จำ",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/tr/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/tr/messages.json
deleted file mode 100644
index 010aca4e4e1..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/tr/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP paket açıcı",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Zip dosyalarını Dosyalar uygulamasında açın.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Arşiv açılamadı.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Arşiv zaten eklenmiş.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Arşiv biçimi desteklenmiyor veya dosya bozuk.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Arşiv taranırken lütfen bekleyin...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Bu dosya şifre korumalı",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Şifre",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Kabul et",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "İptal",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Hatırla",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/uk/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/uk/messages.json
deleted file mode 100644
index e5abb4144c0..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/uk/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Розпакувальник ZIP-архівів",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Відкривання ZIP-архівів у додатку Файли.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Не вдалося відкрити архів.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Архів уже підключено.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Формат архіву не підтримується або файл пошкоджено.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Сканування архіву. Зачекайте…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Цей файл захищено паролем",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Пароль",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Прийняти",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Скасувати",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Запам’ятати",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/vi/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/vi/messages.json
deleted file mode 100644
index d75cd0b9080..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/vi/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "Trình giải nén ZIP",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "Mở tệp ZIP trong ứng dụng Tệp.",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "Không mở được tệp lưu trữ.",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "Tệp lưu trữ đã được kết nối.",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "Định dạng lưu trữ không được hỗ trợ hoặc tệp bị hỏng.",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "Vui lòng đợi, tệp lưu trữ đang được quét...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "Tệp này được bảo vệ bằng mật khẩu",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "Mật khẩu",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "Chấp nhận",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "Hủy",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "Nhớ",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_CN/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_CN/messages.json
deleted file mode 100644
index f4dfb2f4697..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_CN/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP 解压缩程序",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "在“文件”应用中打开 ZIP 文件。",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "未能打开某个归档文件。",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "该归档文件已打开。",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "该归档文件的格式不受支持,或该文件已损坏。",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "请稍候,正在扫描该归档文件…",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "该文件受密码保护",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "密码",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "接受",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "取消",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "记住密码",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_TW/messages.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_TW/messages.json
deleted file mode 100644
index ef4d3ad0f95..00000000000
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/_locales/zh_TW/messages.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": {
- "message": "ZIP 解壓縮工具",
- "description": "Name of the ZIP unpacker app."
- },
- "description": {
- "message": "可讓您在「檔案」應用程式中開啟 ZIP 檔案。",
- "description": "Short description of the ZIP unpacker app."
- },
- "mountErrorTitle": {
- "message": "無法開啟封存檔案。",
- "description": "Title of a notification with a mounting error message."
- },
- "existsErrorMessage": {
- "message": "這個封存檔案已掛接。",
- "description": "Error message when the archive is already mounted."
- },
- "otherErrorMessage": {
- "message": "您使用了不支援的封存格式,或者檔案已毀損。",
- "description": "Error message when opening an archive fails because of an unknown reason."
- },
- "mountingMessage": {
- "message": "系統正在掃描封存檔案,請稍候...",
- "description": "Message shown when opening an archive takes long time."
- },
- "passphraseTitle": {
- "message": "這個檔案受到密碼保護",
- "description": "Title of the password input dialog."
- },
- "passphraseInputLabel": {
- "message": "密碼",
- "description": "Label of the password input field."
- },
- "passphraseAccept": {
- "message": "接受",
- "description": "Short name of the password accept button."
- },
- "passphraseCancel": {
- "message": "取消",
- "description": "Short name of the password cancel button."
- },
- "passphraseRemember": {
- "message": "記住密碼",
- "description": "Title for of a checkbox whether the password should be remembered. Please keep it as short."
- }
-} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/manifest.json b/chromium/chrome/browser/resources/chromeos/zip_archiver/manifest.json
index 49ef7c0a16d..456a43640de 100644
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/manifest.json
+++ b/chromium/chrome/browser/resources/chromeos/zip_archiver/manifest.json
@@ -1,20 +1,27 @@
{
// chrome-extension://dmboannefpncccogfdikhmhpmdnddgoe
"key": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCxGxJCOLUzHIYc812NFoBC1eV8PhOTuF6he3gSuqzxckUyrDLdl5++DAd1AkQkv6i8SSMWFvDKLg2b+zfCOwk6P7uu3tqNavXXy61Okaq5HKF3xhciNDl4zF6ZlegvE9AhJOTo2eCHVIMS0+YuK5hyno/+xMwN4byvsrOYXQnhcJeOHxkFb9TfVUb3SOBgl4pBZ7+EIMNntEvzY7mxjBzOgnCjBePvwnoMRyAqljCJarz2WSbUOLP3yoCuH9vPKj+0D6hF1woXmd6qBr0ln/7tHdbr1cYmkosfFuJO2y6d00FAJY/G5L6o8JAEBbWG5D0qELt+aBjkG0uos5gcR4ZPAgMBAAECggEBAK3aIjFJU25J6MjQiRvvY5a4O56bnUIb8SDZgAP6pbwZ7R2R9hiaN6AqVMOiptvgHDZAISYU/OerD4b3s0OCCkvYtlcxwh6iSZQ9BvIighFWrpZRqPHVjDktfQuNIS/dZiiy+9Yr0oFmD4jS45idCPgy+K0h6CEUX9GlPTEq24ElECDwQHVyB9LHdenleCdvldIEDxf6/D+zkc/PmCPlZPfwdppK6wgH2GvgqbxV+OoSnNp0XhNinjCN37P5yAo4xEi0UGOxOwkNGkJn0V5bYjH6/JHzmdVH74D40N4/Fcy0bC79oFGeiP0ZzW8AAArfIxbxStodWlBOCsTVtvi4RMECgYEA2pyZRThGx4OH8uXCC94LkdpVjKvLvbUlIVd2zk3UEFpWujgmAI+erkAaE1JSlcJpFNSlfonTX1vQuMgTOfnK7soy4677P1CMQH++GxjMWRIAQsMyx7vLtKOISr5/vQQKAyuFmxzt9xbMOmPzqWxwkuuiF74GtPgE5VXslhvsoyECgYEAz2U7L6YS4u2aMRK4DMDxcf/hZ3BxwHmUl5euknRNcaFJSdv6392y8w3t9Lz7sp8CK56GADXL1bmLrDgg2tlL82f60rtPd6IOoJk10uMmCnyjbZh7aJzuw1CTSs+dwi6qpGUB4YbJn8R2AN79SHxUb4dwVOh4lHeNa415Wka+a28CgYA3Vf5iDB22cO/fpxLYSCtrjvWqtu3KpmiwqOAU1pSAUy2y03WjHLeQ6f7vtx3adKx+rlj5z89mSuppa5OaUEVy7lG1WlyUqUHnLa6kU0GepjTUsW5QKpQktGRSbygMY1JZfRHDsq31ppqpiRVrZFyWg/iyw9IUytcKahaJ5KWgoQKBgFbgY/ugyNaQi3+1BK4rALktZAGNo8jp5SnfWzx0RaCs3GN5J80xNG4GTsCvjYwUebdF74IVBu7fi7e3x2OFlQBAdVxjJHXLx+7UXyyZBG1uKpOVRVTcMFRW42x6Le6S196HhVMwwDMR/BB/WIBNvJz/kjmvLBudPPtpxwTfD5M3AoGBALrrXX4QwqBiq4q09SPKoeOwlV35QETUhQaAKKag9aSrNMONcf77TXUBZ0d9Z+tabHLTGGa6E7q2BL82NdZSZvVeVWA+KaE4ezW2t5KyZqg14Cc0uY9Xys9VkFcVgMqsvtkUzDvAVJcmNAgcrMIEiapUR6LPrneLLXH1ikOt+hM8",
- // TODO(takise): translation
- "name": "ZIP archiver",
- "version": "0.76",
+ "name": "Zip Archiver",
+ "version": "1.0",
"manifest_version": 2,
"minimum_chrome_version": "44.0.2400.0",
- // TODO(takise): translation
- "description": "ZIP archiver",
+ "description": "Zip Archiver - Open and pack ZIP files in Files app.",
"default_locale": "en",
"display_in_launcher": false,
+ "incognito": "split",
"permissions": [
"alwaysOnTopWindows",
"chrome://resources/",
"fileSystemProvider",
- {"fileSystem": ["retainEntries", "write", "directory"]},
+ "fileManagerPrivate",
+ {
+ "fileSystem": [
+ "requestFileSystem",
+ "retainEntries",
+ "write",
+ "directory"
+ ]
+ },
"notifications",
"storage"
],
@@ -47,6 +54,7 @@
"js/unpacker.js",
"js/app.js",
"js/background.js",
+ "js/file_operation_utils.js",
"js/compressor.js",
"js/decompressor.js",
"js/passphrase-manager.js",
@@ -57,4 +65,4 @@
},
"content_security_policy": "default-src 'none'; script-src chrome://resources; style-src 'unsafe-inline' chrome://resources;"
}
-}
+} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/component_extension_resources.grd b/chromium/chrome/browser/resources/component_extension_resources.grd
index 790e53cb609..6ec5019a7ff 100644
--- a/chromium/chrome/browser/resources/component_extension_resources.grd
+++ b/chromium/chrome/browser/resources/component_extension_resources.grd
@@ -132,7 +132,6 @@
<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_LSO_CSS" file="chromeos/arc_support/lso.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_PLAYSTORE_LOGO" file="chromeos/arc_support/icon/playstore.svg" type="BINDATA" />
diff --git a/chromium/chrome/browser/resources/cryptotoken/compiled_resources2.gyp b/chromium/chrome/browser/resources/cryptotoken/compiled_resources2.gyp
new file mode 100644
index 00000000000..a84a888dcca
--- /dev/null
+++ b/chromium/chrome/browser/resources/cryptotoken/compiled_resources2.gyp
@@ -0,0 +1,47 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'errorcodes',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'b64',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'approvedorigins',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'closeable',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'countdown',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'inherits',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'origincheck',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'sha256',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'textfetcher',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'timer',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ]
+}
diff --git a/chromium/chrome/browser/resources/uber/compiled_resources2.gyp b/chromium/chrome/browser/resources/download_internals/compiled_resources2.gyp
index 960d088d392..13baad13e0e 100644
--- a/chromium/chrome/browser/resources/uber/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/download_internals/compiled_resources2.gyp
@@ -1,39 +1,31 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
+# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'targets': [
{
- 'target_name': 'uber_frame',
+ 'target_name': 'download_internals',
'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:load_time_data',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
- '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_outline_manager',
- 'uber_utils',
+ 'download_internals_browser_proxy',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'uber_utils',
+ 'target_name': 'download_internals_browser_proxy',
'dependencies': [
'<(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:util',
- '<(EXTERNS_GYP):chrome_send',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'uber',
+ 'target_name': 'download_internals_visuals',
'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:load_time_data',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
- 'uber_utils',
- '<(EXTERNS_GYP):chrome_send',
+ 'download_internals_browser_proxy',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals.css b/chromium/chrome/browser/resources/download_internals/download_internals.css
new file mode 100644
index 00000000000..63dab4dbfc0
--- /dev/null
+++ b/chromium/chrome/browser/resources/download_internals/download_internals.css
@@ -0,0 +1,41 @@
+/* Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+h1 {
+ color: rgb(74, 142, 230);
+ margin: 0;
+ padding: 0;
+}
+
+.status {
+ font-size: 15px;
+}
+
+.service-entry-new {
+ background-color: rgb(242, 242, 242)
+}
+
+.service-entry-available {
+ background-color: rgb(242, 242, 242)
+}
+
+.service-entry-active {
+ background-color: rgb(214, 249, 245)
+}
+
+.service-entry-paused {
+ background-color: rgb(240, 200, 125)
+}
+
+.service-entry-success {
+ background-color: rgb(157, 239, 133)
+}
+
+.service-entry-fail {
+ background-color: rgb(215, 180, 180)
+}
+
+.service-entry-blocked {
+ background-color: rgb(239, 235, 133)
+} \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals.html b/chromium/chrome/browser/resources/download_internals/download_internals.html
new file mode 100644
index 00000000000..259ed42fc33
--- /dev/null
+++ b/chromium/chrome/browser/resources/download_internals/download_internals.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<html lang="en" dir="ltr">
+ <head>
+ <meta charset="utf-8">
+ <title>Download Internals</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" href="chrome://resources/css/list.css">
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+ <link rel="stylesheet" href="download_internals.css">
+
+ <link rel="import" href="chrome://resources/html/cr.html">
+ <link rel="import" href="chrome://resources/html/cr/ui/list_item.html">
+ <link rel="import" href="chrome://resources/html/cr/ui/list.html">
+ <link rel="import" href="chrome://resources/html/load_time_data.html">
+ <link rel="import" href="chrome://resources/html/util.html">
+
+ <script src="strings.js"></script>
+ <script src="download_internals_browser_proxy.js"></script>
+ <script src="download_internals.js"></script>
+ <script src="download_internals_visuals.js"></script>
+ </head>
+ <body>
+ <h1>Download Internals</h1>
+ <h4>Service State</h4>
+ <div>
+ State: <span id="service-state" class="status"></span>
+ Model: <span id="service-status-model" class="status"></span>
+ Driver: <span id="service-status-driver" class="status"></span>
+ File Monitor: <span id="service-status-file" class="status"></span>
+ </div>
+ <h4>Entry Requests</h4>
+ <div id="download-service-request-info">
+ <table class="styled-table">
+ <thead>
+ <tr>
+ <th>Result</th>
+ <th>Client</th>
+ <th>ID</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr jsselect="requests"
+ jsvalues=".className: downloadInternalsVisuals.getServiceRequestClass($this)">
+ <td jscontent="result"></td>
+ <td jscontent="client"></td>
+ <td jscontent="guid"></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <h4>Completed/Failed Downloads</h4>
+ <div id="download-service-finished-entries-info">
+ <table class="styled-table">
+ <thead>
+ <tr>
+ <th>Result</th>
+ <th>Client</th>
+ <th>ID</th>
+ <th>URL</th>
+ <th>Size</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr jsselect="entries"
+ jsvalues=".className: downloadInternalsVisuals.getFinishedServiceEntryClass($this)">
+ <td jscontent="result"></td>
+ <td jscontent="client"></td>
+ <td jscontent="guid"></td>
+ <td>
+ <div jscontent="url"></div>
+ <div jscontent="file_path"></div>
+ </td>
+ <td jscontent="bytes_downloaded"></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <h4>In-Progress Downloads</h4>
+ <div id="download-service-ongoing-entries-info">
+ <table class="styled-table">
+ <thead>
+ <tr>
+ <th>State</th>
+ <th>Client</th>
+ <th>ID</th>
+ <th>URL</th>
+ <th>Bytes Downloaded</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr jsselect="entries"
+ jsvalues=".className: downloadInternalsVisuals.getOngoingServiceEntryClass($this)">
+ <td>
+ <div jscontent="state"></div>
+ <div jsdisplay="typeof driver != 'undefined'">
+ <span jscontent="driver.state"></span>
+ </div>
+ </td>
+ <td jscontent="client"></td>
+ <td jscontent="guid"></td>
+ <td jscontent="url"></td>
+ <td jscontent="bytes_downloaded"></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <script src="chrome://resources/js/i18n_template.js"></script>
+ <script src="chrome://resources/js/jstemplate_compiled.js"></script>
+ </body>
+</html>
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals.js b/chromium/chrome/browser/resources/download_internals/download_internals.js
new file mode 100644
index 00000000000..62f1f1f0ab8
--- /dev/null
+++ b/chromium/chrome/browser/resources/download_internals/download_internals.js
@@ -0,0 +1,135 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('downloadInternals', function() {
+ 'use strict';
+
+ /** @type {!downloadInternals.DownloadInternalsBrowserProxy} */
+ var browserProxy =
+ downloadInternals.DownloadInternalsBrowserProxyImpl.getInstance();
+
+ /** @type {!Array<ServiceEntry>} */
+ var ongoingServiceEntries = [];
+
+ /** @type {!Array<ServiceEntry>} */
+ var finishedServiceEntries = [];
+
+ /** @type {!Array<ServiceRequest>} */
+ var serviceRequests = [];
+
+ /**
+ * @param {!Array<ServiceEntry>} list A list to remove the entry from.
+ * @param {string} guid The guid to remove from the list.
+ */
+ function removeGuidFromList(list, guid) {
+ var index = list.findIndex(entry => entry.guid == guid);
+ if (index != -1)
+ list.splice(index, 1);
+ }
+
+ /**
+ * Replaces the ServiceEntry specified by guid in the list or, if it's not
+ * found, adds a new entry.
+ * @param {!Array<ServiceEntry>} list A list to update.
+ * @param {!ServiceEntry} newEntry The new entry.
+ */
+ function addOrUpdateEntryByGuid(list, newEntry) {
+ var index = list.findIndex(entry => entry.guid == newEntry.guid);
+ if (index != -1)
+ list[index] = newEntry;
+ else
+ list.unshift(newEntry);
+ }
+
+ function updateEntryTables() {
+ var ongoingInput = new JsEvalContext({entries: ongoingServiceEntries});
+ jstProcess(ongoingInput, $('download-service-ongoing-entries-info'));
+
+ var finishedInput = new JsEvalContext({entries: finishedServiceEntries});
+ jstProcess(finishedInput, $('download-service-finished-entries-info'));
+ }
+
+ /**
+ * @param {!ServiceStatus} state The current status of the download service.
+ */
+ function onServiceStatusChanged(state) {
+ $('service-state').textContent = state.serviceState;
+ $('service-status-model').textContent = state.modelStatus;
+ $('service-status-driver').textContent = state.driverStatus;
+ $('service-status-file').textContent = state.fileMonitorStatus;
+ }
+
+ /**
+ * @param {!Array<!ServiceEntry>} entries A list entries currently tracked by
+ * the download service.
+ */
+ function onServiceDownloadsAvailable(entries) {
+ for (var i = 0; i < entries.length; i++) {
+ var entry = entries[i];
+ if (entry.state == ServiceEntryState.COMPLETE) {
+ finishedServiceEntries.unshift(entry);
+ } else {
+ ongoingServiceEntries.unshift(entry);
+ }
+ }
+
+ updateEntryTables();
+ }
+
+ /**
+ * @param {!ServiceEntry} entry The new state for a particular download
+ * service entry.
+ */
+ function onServiceDownloadChanged(entry) {
+ if (entry.state == ServiceEntryState.COMPLETE) {
+ removeGuidFromList(ongoingServiceEntries, entry.guid);
+ addOrUpdateEntryByGuid(finishedServiceEntries, entry);
+ } else {
+ addOrUpdateEntryByGuid(ongoingServiceEntries, entry);
+ }
+
+ updateEntryTables();
+ }
+
+ /**
+ * @param {!ServiceEntry} entry The new state for a failed download service
+ * entry.
+ */
+ function onServiceDownloadFailed(entry) {
+ removeGuidFromList(ongoingServiceEntries, entry.guid);
+ addOrUpdateEntryByGuid(finishedServiceEntries, entry);
+
+ updateEntryTables();
+ }
+
+ /**
+ * @param {!ServiceRequest} request The state for a newly issued download
+ * service request.
+ */
+ function onServiceRequestMade(request) {
+ serviceRequests.unshift(request);
+ var input = new JsEvalContext({requests: serviceRequests});
+ jstProcess(input, $('download-service-request-info'));
+ }
+
+ function initialize() {
+ // Register all event listeners.
+ cr.addWebUIListener('service-status-changed', onServiceStatusChanged);
+ cr.addWebUIListener(
+ 'service-downloads-available', onServiceDownloadsAvailable);
+ cr.addWebUIListener('service-download-changed', onServiceDownloadChanged);
+ cr.addWebUIListener('service-download-failed', onServiceDownloadFailed);
+ cr.addWebUIListener('service-request-made', onServiceRequestMade);
+
+ // Kick off requests for the current system state.
+ browserProxy.getServiceStatus().then(onServiceStatusChanged);
+ browserProxy.getServiceDownloads().then(onServiceDownloadsAvailable);
+ }
+
+ return {
+ initialize: initialize,
+ };
+});
+
+document.addEventListener('DOMContentLoaded', downloadInternals.initialize);
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js b/chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js
new file mode 100644
index 00000000000..89642e117d5
--- /dev/null
+++ b/chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js
@@ -0,0 +1,131 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Contains the possible states a ServiceEntry can be in.
+ * @enum {string}
+ */
+var ServiceEntryState = {
+ NEW: 'NEW',
+ AVAILABLE: 'AVAILABLE',
+ ACTIVE: 'ACTIVE',
+ PAUSED: 'PAUSED',
+ COMPLETE: 'COMPLETE',
+};
+
+/**
+ * Contains the possible states a ServiceEntry's driver can be in.
+ * @enum {string}
+ */
+var DriverEntryState = {
+ IN_PROGRESS: 'IN_PROGRESS',
+ COMPLETE: 'COMPLETE',
+ CANCELLED: 'CANCELLED',
+ INTERRUPTED: 'INTERRUPTED',
+};
+
+/**
+ * Contains the possible results a ServiceEntry can have.
+ * @enum {string}
+ */
+var ServiceEntryResult = {
+ SUCCEED: 'SUCCEED',
+ FAIL: 'FAIL',
+ ABORT: 'ABORT',
+ TIMEOUT: 'TIMEOUT',
+ UNKNOWN: 'UNKNOWN',
+ CANCEL: 'CANCEL',
+ OUT_OF_RETRIES: 'OUT_OF_RETRIES',
+ OUT_OF_RESUMPTIONS: 'OUT_OF_RESUMPTIONS',
+};
+
+/**
+ * Contains the possible results of a ServiceRequest.
+ * @enum {string}
+ */
+var ServiceRequestResult = {
+ ACCEPTED: 'ACCEPTED',
+ BACKOFF: 'BACKOFF',
+ UNEXPECTED_CLIENT: 'UNEXPECTED_CLIENT',
+ UNEXPECTED_GUID: 'UNEXPECTED_GUID',
+ CLIENT_CANCELLED: 'CLIENT_CANCELLED',
+ INTERNAL_ERROR: 'INTERNAL_ERROR',
+};
+
+/**
+ * @typedef {{
+ * serviceState: string,
+ * modelStatus: string,
+ * driverStatus: string,
+ * fileMonitorStatus: string
+ * }}
+ */
+var ServiceStatus;
+
+/**
+ * @typedef {{
+ * client: string,
+ * guid: string,
+ * state: !ServiceEntryState,
+ * url: string,
+ * bytes_downloaded: number,
+ * result: (!ServiceEntryResult|undefined),
+ * driver: {
+ * state: !DriverEntryState,
+ * paused: boolean,
+ * done: boolean
+ * }
+ * }}
+ */
+var ServiceEntry;
+
+/**
+ * @typedef {{
+ * client: string,
+ * guid: string,
+ * result: !ServiceRequestResult
+ * }}
+ */
+var ServiceRequest;
+
+cr.define('downloadInternals', function() {
+ /** @interface */
+ class DownloadInternalsBrowserProxy {
+ /**
+ * Gets the current status of the Download Service.
+ * @return {!Promise<ServiceStatus>} A promise firing when the service
+ * status is fetched.
+ */
+ getServiceStatus() {}
+
+ /**
+ * Gets the current list of downloads the Download Service is aware of.
+ * @return {!Promise<!Array<!ServiceEntry>>} A promise firing when the list
+ * of downloads is fetched.
+ */
+ getServiceDownloads() {}
+ }
+
+ /**
+ * @implements {downloadInternals.DownloadInternalsBrowserProxy}
+ */
+ class DownloadInternalsBrowserProxyImpl {
+ /** @override */
+ getServiceStatus() {
+ return cr.sendWithPromise('getServiceStatus');
+ }
+
+ /** @override */
+ getServiceDownloads() {
+ return cr.sendWithPromise('getServiceDownloads');
+ }
+ }
+
+ cr.addSingletonGetter(DownloadInternalsBrowserProxyImpl);
+
+ return {
+ DownloadInternalsBrowserProxy: DownloadInternalsBrowserProxy,
+ DownloadInternalsBrowserProxyImpl: DownloadInternalsBrowserProxyImpl
+ };
+});
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals_visuals.js b/chromium/chrome/browser/resources/download_internals/download_internals_visuals.js
new file mode 100644
index 00000000000..c3945574222
--- /dev/null
+++ b/chromium/chrome/browser/resources/download_internals/download_internals_visuals.js
@@ -0,0 +1,55 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('downloadInternalsVisuals', function() {
+ 'use strict';
+
+ function getOngoingServiceEntryClass(entry) {
+ switch (entry.state) {
+ case ServiceEntryState.NEW:
+ return 'service-entry-new';
+ case ServiceEntryState.AVAILABLE:
+ return 'service-entry-available';
+ case ServiceEntryState.ACTIVE:
+ if (entry.driver == undefined || !entry.driver.paused ||
+ entry.driver.state == DriverEntryState.INTERRUPTED)
+ return 'service-entry-active';
+ else
+ return 'service-entry-blocked';
+ case ServiceEntryState.PAUSED:
+ return 'service-entry-paused';
+ case ServiceEntryState.COMPLETE:
+ return 'service-entry-success';
+ default:
+ return '';
+ }
+ }
+
+ function getFinishedServiceEntryClass(entry) {
+ switch (entry.result) {
+ case ServiceEntryResult.SUCCEED:
+ return 'service-entry-success';
+ default:
+ return 'service-entry-fail';
+ }
+ }
+
+ function getServiceRequestClass(request) {
+ switch (request.result) {
+ case ServiceRequestResult.ACCEPTED:
+ return 'service-entry-success';
+ case ServiceRequestResult.BACKOFF:
+ case ServiceRequestResult.CLIENT_CANCELLED:
+ return 'service-entry-blocked';
+ default:
+ return 'service-entry-fail';
+ }
+ }
+
+ return {
+ getOngoingServiceEntryClass: getOngoingServiceEntryClass,
+ getFinishedServiceEntryClass: getFinishedServiceEntryClass,
+ getServiceRequestClass: getServiceRequestClass
+ };
+}); \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/extensions/compiled_resources2.gyp b/chromium/chrome/browser/resources/extensions/compiled_resources2.gyp
index 86bdc2d6130..c2f646198d0 100644
--- a/chromium/chrome/browser/resources/extensions/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/extensions/compiled_resources2.gyp
@@ -4,24 +4,10 @@
{
'targets': [
{
- 'target_name': 'shortcut_util',
- 'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'drag_and_drop_handler',
+ 'target_name': 'extensions',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:drag_wrapper',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:webui_listener_tracker',
],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'extensions',
'variables': {
'script_args': ['--custom_sources'],
'source_files': [
@@ -64,12 +50,12 @@
'extension_command_list.js',
'<(DEPTH)/ui/webui/resources/js/cr/ui/controlled_indicator.js',
'extension_error_overlay.js',
- 'drag_and_drop_handler.js',
+ '../md_extensions/drag_and_drop_handler.js',
'<(DEPTH)/ui/webui/resources/js/cr/ui/list_selection_model.js',
'<(DEPTH)/third_party/jstemplate/jstemplate.js',
'chromeos/kiosk_app_list.js',
'<(DEPTH)/third_party/closure_compiler/externs/developer_private.js',
- 'shortcut_util.js',
+ '../md_extensions/shortcut_util.js',
'pack_extension_overlay.js',
],
},
diff --git a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.html b/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.html
deleted file mode 100644
index d5665f77bec..00000000000
--- a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="import" href="chrome://resources/html/cr.html">
-<script src="chrome://extensions/drag_and_drop_handler.js"></script>
diff --git a/chromium/chrome/browser/resources/extensions/extension_command_list.js b/chromium/chrome/browser/resources/extensions/extension_command_list.js
index eca1797c75b..1aa48e3052f 100644
--- a/chromium/chrome/browser/resources/extensions/extension_command_list.js
+++ b/chromium/chrome/browser/resources/extensions/extension_command_list.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// <include src="shortcut_util.js">
+// <include src="../md_extensions/shortcut_util.js">
cr.define('extensions', function() {
'use strict';
@@ -378,8 +378,8 @@ cr.define('extensions', function() {
*/
handleSetCommandScope_: function(event) {
var parsed = this.parseElementId_('setCommandScope', event.target.id);
- var element = document.getElementById(
- 'setCommandScope-' + parsed.extensionId + '-' + parsed.commandName);
+ var element =
+ $('setCommandScope-' + parsed.extensionId + '-' + parsed.commandName);
var scope = element.selectedIndex == 1 ?
chrome.developerPrivate.CommandScope.GLOBAL :
chrome.developerPrivate.CommandScope.CHROME;
diff --git a/chromium/chrome/browser/resources/extensions/extensions.html b/chromium/chrome/browser/resources/extensions/extensions.html
index bcca289b8c7..40d6ce3f016 100644
--- a/chromium/chrome/browser/resources/extensions/extensions.html
+++ b/chromium/chrome/browser/resources/extensions/extensions.html
@@ -19,7 +19,7 @@
<link rel="stylesheet" href="chrome://resources/css/overlay.css">
<link rel="stylesheet" href="chrome://resources/css/spinner.css">
<link rel="stylesheet" href="chrome://resources/css/trash.css">
-<link rel="stylesheet" href="../uber/uber_shared.css">
+<link rel="stylesheet" href="../uber_shared.css">
<script src="chrome://resources/js/action_link.js"></script>
<script src="chrome://resources/js/cr.js"></script>
@@ -48,6 +48,8 @@
</script>
<script src="chrome://resources/js/cr/ui/list_item.js"></script>
<script src="chrome://resources/js/cr/ui/list.js"></script>
+<script src="chrome://resources/js/promise_resolver.js"></script>
+<script src="chrome://resources/js/webui_listener_tracker.js"></script>
</if>
<script src="chrome://extensions/extensions.js"></script>
diff --git a/chromium/chrome/browser/resources/extensions/extensions.js b/chromium/chrome/browser/resources/extensions/extensions.js
index e6b511b28f1..d46ea50ad19 100644
--- a/chromium/chrome/browser/resources/extensions/extensions.js
+++ b/chromium/chrome/browser/resources/extensions/extensions.js
@@ -4,7 +4,7 @@
// <include src="../../../../ui/webui/resources/js/cr/ui/focus_row.js">
// <include src="../../../../ui/webui/resources/js/cr/ui/focus_grid.js">
-// <include src="drag_and_drop_handler.js">
+// <include src="../md_extensions/drag_and_drop_handler.js">
// <include src="extension_code.js">
// <include src="extension_commands_overlay.js">
// <include src="extension_error_overlay.js">
diff --git a/chromium/chrome/browser/resources/feedback/html/default.html b/chromium/chrome/browser/resources/feedback/html/default.html
index debe0a53e2b..8f839557466 100644
--- a/chromium/chrome/browser/resources/feedback/html/default.html
+++ b/chromium/chrome/browser/resources/feedback/html/default.html
@@ -40,7 +40,7 @@
</div>
</div>
<div id="content-pane" class="content">
- <textarea id="description-text" aria-labelledby="title-bar"></textarea>
+ <textarea id="description-text" aria-labelledby="page-title"></textarea>
<div>
<p id="additional-info-label" i18n-content="additionalInfo"><p>
</div>
@@ -72,7 +72,7 @@
<div id="screenshot-container" class="checkbox-field-container">
<input id="screenshot-checkbox" type="checkbox" aria-labelledby="screenshot-label">
<label id="screenshot-label" i18n-content="screenshot"></label>
- <img id="screenshot-image" alt="screenshot">
+ <img id="screenshot-image">
</div>
<!-- System Information -->
<div class="checkbox-field-container">
diff --git a/chromium/chrome/browser/resources/feedback/js/feedback.js b/chromium/chrome/browser/resources/feedback/js/feedback.js
index 76f6e26ab49..62712dab768 100644
--- a/chromium/chrome/browser/resources/feedback/js/feedback.js
+++ b/chromium/chrome/browser/resources/feedback/js/feedback.js
@@ -348,7 +348,11 @@ function initialize() {
chrome.app.window.current().show();
var screenshotDataUrl = screenshotCanvas.toDataURL('image/png');
+
+ // Only set the alt text when the src url is available, otherwise we'd
+ // get a broken image picture instead. crbug.com/773985.
$('screenshot-image').src = screenshotDataUrl;
+ $('screenshot-image').alt = 'screenshot';
$('screenshot-image')
.classList.toggle(
'wide-screen',
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
index 878224e9f32..4d1bc38391f 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -73,7 +73,6 @@ cr.define('cr.login', function() {
'constrained', // Whether the extension is loaded in a constrained
// window.
'clientId', // Chrome client id.
- 'useEafe', // Whether to use EAFE.
'needPassword', // Whether the host is interested in getting a password.
// If this set to |false|, |confirmPasswordCallback| is
// not called before dispatching |authCopleted|.
@@ -144,7 +143,6 @@ cr.define('cr.login', function() {
this.newGapsCookie_ = null;
this.readyFired_ = false;
- this.useEafe_ = false;
this.clientId_ = null;
this.samlHandler_ = new cr.login.SamlHandler(this.webview_);
@@ -168,7 +166,6 @@ cr.define('cr.login', function() {
this.webview_.addEventListener(
'contentload', this.onContentLoad_.bind(this));
this.webview_.addEventListener('loadabort', this.onLoadAbort_.bind(this));
- this.webview_.addEventListener('loadstop', this.onLoadStop_.bind(this));
this.webview_.addEventListener('loadcommit', this.onLoadCommit_.bind(this));
this.webview_.request.onCompleted.addListener(
this.onRequestCompleted_.bind(this),
@@ -232,7 +229,6 @@ cr.define('cr.login', function() {
this.continueUrl_;
this.isConstrainedWindow_ = data.constrained == '1';
this.isNewGaiaFlow = data.isNewGaiaFlow;
- this.useEafe_ = data.useEafe || false;
this.clientId_ = data.clientId;
this.gapsCookie_ = data.gapsCookie;
this.gapsCookieSent_ = false;
@@ -562,17 +558,6 @@ cr.define('cr.login', function() {
return false;
}
- // EAFE passes back auth code via message.
- if (this.useEafe_ && typeof e.data == 'object' &&
- e.data.hasOwnProperty('authorizationCode')) {
- assert(!this.oauthCode_);
- this.oauthCode_ = e.data.authorizationCode;
- this.dispatchEvent(new CustomEvent(
- 'authCompleted',
- {detail: {authCodeOnly: true, authCode: this.oauthCode_}}));
- return;
- }
-
// Gaia messages must be an object with 'method' property.
if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) {
return false;
@@ -846,27 +831,6 @@ cr.define('cr.login', function() {
};
/**
- * Invoked when the webview finishes loading a page.
- * @private
- */
- Authenticator.prototype.onLoadStop_ = function(e) {
- // Sends client id to EAFE on every loadstop after a small timeout. This is
- // needed because EAFE sits behind SSO and initialize asynchrounouly
- // and we don't know for sure when it is loaded and ready to listen
- // for message. The postMessage is guarded by EAFE's origin.
- if (this.useEafe_) {
- // An arbitrary small timeout for delivering the initial message.
- var EAFE_INITIAL_MESSAGE_DELAY_IN_MS = 500;
- window.setTimeout(
- (function() {
- var msg = {'clientId': this.clientId_};
- this.webview_.contentWindow.postMessage(msg, this.idpOrigin_);
- }).bind(this),
- EAFE_INITIAL_MESSAGE_DELAY_IN_MS);
- }
- };
-
- /**
* Invoked when the webview navigates withing the current document.
* @private
*/
diff --git a/chromium/chrome/browser/resources/instant/instant.css b/chromium/chrome/browser/resources/instant/instant.css
index af57b887194..795df5d309d 100644
--- a/chromium/chrome/browser/resources/instant/instant.css
+++ b/chromium/chrome/browser/resources/instant/instant.css
@@ -9,38 +9,7 @@ body {
padding-bottom: 65px;
}
-img {
- float: left;
- height: 16px;
- padding-right: 5px;
- width: 16px;
-}
-
-.section {
- background-color: rgb(235, 239, 249);
- border-top: 1px solid rgb(181, 199, 222);
- font-weight: bold;
- margin: 10px 0 0;
- padding: 2px 2px;
-}
-
.row {
border-bottom: 1px solid #a0a0a0;
padding: 5px;
}
-
-.url {
- color: #a0a0a0;
-}
-
-.debug {
- margin: 1px;
-}
-
-.debug span+span {
- padding-left: 5px;
-}
-
-.timestamp {
- color: blue;
-}
diff --git a/chromium/chrome/browser/resources/instant/instant.html b/chromium/chrome/browser/resources/instant/instant.html
index 0482eca02db..80fdc497c14 100644
--- a/chromium/chrome/browser/resources/instant/instant.html
+++ b/chromium/chrome/browser/resources/instant/instant.html
@@ -20,10 +20,5 @@ found in the LICENSE file.
<button id="save-button">Save</button>
</div>
<hr/>
- <div>
- <h2>Instant Event Log</h2>
- <button id="clear-button">Clear</button><br><br>
- <div id="instant-debug-info"></div>
- </div>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/instant/instant.js b/chromium/chrome/browser/resources/instant/instant.js
index 2cb4b971bf9..be590061c23 100644
--- a/chromium/chrome/browser/resources/instant/instant.js
+++ b/chromium/chrome/browser/resources/instant/instant.js
@@ -5,8 +5,8 @@
// Redefine '$' here rather than including 'cr.js', since this is
// the only function needed. This allows this file to be loaded
// in a browser directly for layout and some testing purposes.
-// eslint-disable-next-line no-restricted-properties
var $ = function(id) {
+ // eslint-disable-next-line no-restricted-properties
return document.getElementById(id);
};
@@ -138,37 +138,6 @@ var instantConfig = (function() {
return false;
}
- /**
- * Request debug info.
- * The method is asynchronous, results being provided via getDebugInfoResult.
- */
- function getDebugInfo() {
- chrome.send('getDebugInfo');
- }
-
- /**
- * Handles callback from getDebugInfo.
- * @param {Object} info The debug info.
- */
- function getDebugInfoResult(info) {
- for (var i = 0; i < info.entries.length; ++i) {
- var entry = info.entries[i];
- var row = createElementWithClass('p', 'debug');
- row.appendChild(createElementWithClass('span', 'timestamp')).textContent =
- entry.time;
- row.appendChild(document.createElement('span')).textContent = entry.text;
- $('instant-debug-info').appendChild(row);
- }
- }
-
- /**
- * Resets list of debug events.
- */
- function clearDebugInfo() {
- $('instant-debug-info').innerHTML = '';
- chrome.send('clearDebugInfo');
- }
-
function loadForm() {
for (var i = 0; i < FIELDS.length; i++)
getPreferenceValue(FIELDS[i].key);
@@ -181,15 +150,12 @@ var instantConfig = (function() {
buildForm();
loadForm();
initForm();
- getDebugInfo();
$('save-button').onclick = onSave.bind(this);
- $('clear-button').onclick = clearDebugInfo.bind(this);
}
return {
initialize: initialize,
- getDebugInfoResult: getDebugInfoResult,
getPreferenceValueResult: getPreferenceValueResult
};
})();
diff --git a/chromium/chrome/browser/resources/interventions_internals/index.css b/chromium/chrome/browser/resources/interventions_internals/index.css
new file mode 100644
index 00000000000..4ee2351451c
--- /dev/null
+++ b/chromium/chrome/browser/resources/interventions_internals/index.css
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.hidden-tab {
+ display: none;
+ padding: 12px;
+}
+
+.selected-tab {
+ display: block;
+ padding: 12px;
+}
+
+.tab-select input[type=radio] {
+ display: none;
+}
+
+.tab-select label {
+ background: #ddd;
+ border: outset 1px silver;
+ cursor: pointer;
+ margin-right: -5px;
+ padding: 5px 5px;
+}
+
+.tab-select input:checked + span {
+ background: #aaa;
+ border: inset 1px silver;
+}
+
+table {
+ border: 1px solid black;
+ border-collapse: collapse;
+}
+
+th {
+ border: 1px solid black;
+ padding: 15px;
+ text-align: left;
+}
+
+td {
+ border: 1px solid black;
+ padding: 15px;
+ text-align: left;
+}
+
+.error-header {
+ font-size: 150%;
+ font-weight: bold;
+}
+
+.error-message {
+ font-style: italic;
+}
diff --git a/chromium/chrome/browser/resources/interventions_internals/index.html b/chromium/chrome/browser/resources/interventions_internals/index.html
new file mode 100644
index 00000000000..4de45b78f77
--- /dev/null
+++ b/chromium/chrome/browser/resources/interventions_internals/index.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width">
+ <title>Interventions-Internals</title>
+ <script src="chrome://resources/js/cr.js"></script>
+ <script src="chrome://resources/js/mojo_bindings.js"></script>
+ <script src="chrome://resources/js/util.js"></script>
+ <script src="chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.js">
+ </script>
+ <script src="index.js"></script>
+ <link rel="stylesheet" type="text/css" href="index.css">
+ </head>
+
+ <body>
+ <nav class="tab-select">
+ <label>
+ <input type="radio" id="statuses" name="tabs"
+ value="previews-statuses" checked="checked">
+ <span>Previews Modes</span>
+ </label>
+ <label>
+ <input type="radio" id="logs" name="tabs" value="message-logs">
+ <span>Logs</span>
+ </label>
+ </nav>
+
+ <div class="tab-content" id="previews-statuses">
+ </div>
+
+ <div class="tab-content" id="message-logs">
+ <table id="message-logs-table">
+ <tr>
+ <th id="time-table-header">Time</th>
+ <th id="type-table-header">Type</th>
+ <th id="description-table-header">Description</th>
+ <th id="url-table-header">URL</th>
+ </tr>
+ </table>
+ </div>
+ </body>
+</html>
diff --git a/chromium/chrome/browser/resources/interventions_internals/index.js b/chromium/chrome/browser/resources/interventions_internals/index.js
new file mode 100644
index 00000000000..b01f1b2bfe8
--- /dev/null
+++ b/chromium/chrome/browser/resources/interventions_internals/index.js
@@ -0,0 +1,160 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Switch the selected tab to 'selected-tab' class.
+ */
+function setSelectedTab() {
+ let selected =
+ document.querySelector('input[type=radio][name=tabs]:checked').value;
+ let selectedTab = document.querySelector('#' + selected);
+ selectedTab.className =
+ selectedTab.className.replace('hidden-tab', 'selected-tab');
+}
+
+/**
+ * Change the previously selected element to 'hidden-tab' class, and switch the
+ * selected element to 'selected-tab' class.
+ */
+function changeTab() {
+ let lastSelected = document.querySelector('.selected-tab');
+ lastSelected.className =
+ lastSelected.className.replace('selected-tab', 'hidden-tab');
+
+ setSelectedTab();
+}
+
+/**
+ * Initialize the navigation bar, and setup OnChange listeners for the tabs.
+ */
+function setupTabControl() {
+ // Initialize on change listeners.
+ let tabs = document.querySelectorAll('input[type=radio][name=tabs]');
+ tabs.forEach((tab) => {
+ tab.addEventListener('change', changeTab);
+ });
+
+ let tabContents = document.querySelectorAll('.tab-content');
+ tabContents.forEach((tab) => {
+ tab.className += ' hidden-tab';
+ });
+
+ // Turn on the default selected tab.
+ setSelectedTab();
+}
+
+/** @constructor */
+let InterventionsInternalPageImpl = function(request) {
+ this.binding_ =
+ new mojo.Binding(mojom.InterventionsInternalsPage, this, request);
+};
+
+InterventionsInternalPageImpl.prototype = {
+ /**
+ * Post a new log message to the web page.
+ *
+ * @override
+ * @param {!MessageLog} log The new log message recorded by
+ * PreviewsLogger.
+ */
+ logNewMessage: function(log) {
+ let logsTable = $('message-logs-table');
+ let tableRow = document.createElement('tr');
+ tableRow.setAttribute('class', 'log-message');
+
+ let timeTd = document.createElement('td');
+ let date = new Date(log.time);
+ timeTd.textContent = date.toISOString();
+ timeTd.setAttribute('class', 'log-time');
+ tableRow.appendChild(timeTd);
+
+ let typeTd = document.createElement('td');
+ typeTd.setAttribute('class', 'log-type');
+ typeTd.textContent = log.type;
+ tableRow.appendChild(typeTd);
+
+ let descriptionTd = document.createElement('td');
+ descriptionTd.setAttribute('class', 'log-description');
+ descriptionTd.textContent = log.description;
+ tableRow.appendChild(descriptionTd);
+
+ // TODO(thanhdle): Truncate url and show full url when user clicks on it.
+ // crbug.com/773019
+ let urlTd = document.createElement('td');
+ urlTd.setAttribute('class', 'log-url');
+ urlTd.textContent = log.url.url;
+ tableRow.appendChild(urlTd);
+
+ logsTable.appendChild(tableRow);
+ },
+};
+
+cr.define('interventions_internals', () => {
+ let pageHandler = null;
+
+ function init(handler) {
+ pageHandler = handler;
+ getPreviewsEnabled();
+ }
+
+ /**
+ * Retrieves the statuses of previews (i.e. Offline, LoFi, AMP Redirection),
+ * and posts them on chrome://intervention-internals.
+ */
+ function getPreviewsEnabled() {
+ pageHandler.getPreviewsEnabled()
+ .then((response) => {
+ let statuses = $('previews-statuses');
+
+ // TODO(thanhdle): The statuses are not printed in alphabetic order of
+ // the key. crbug.com/772458
+ response.statuses.forEach((value, key) => {
+ let message = value.description + ': ';
+ message += value.enabled ? 'Enabled' : 'Disabled';
+
+ assert(!$(key), 'Component ' + key + ' already existed!');
+
+ let node = document.createElement('p');
+ node.setAttribute('id', key);
+ node.textContent = message;
+ statuses.appendChild(node);
+ });
+ })
+ .catch((error) => {
+ console.error(error.message);
+ });
+ }
+
+ return {
+ init: init,
+ };
+});
+
+window.setupFn = window.setupFn || function() {
+ return Promise.resolve();
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ setupTabControl();
+ let pageHandler = null;
+ let pageImpl = null;
+
+ window.setupFn().then(() => {
+ if (window.testPageHandler) {
+ pageHandler = window.testPageHandler;
+ } else {
+ pageHandler = new mojom.InterventionsInternalsPageHandlerPtr;
+ Mojo.bindInterface(
+ mojom.InterventionsInternalsPageHandler.name,
+ mojo.makeRequest(pageHandler).handle);
+
+ // Set up client side mojo interface.
+ let client = new mojom.InterventionsInternalsPagePtr;
+ pageImpl = new InterventionsInternalPageImpl(mojo.makeRequest(client));
+ pageHandler.setClientPage(client);
+ }
+
+ interventions_internals.init(pageHandler);
+ });
+});
diff --git a/chromium/chrome/browser/resources/interventions_internals/unsupported_page.html b/chromium/chrome/browser/resources/interventions_internals/unsupported_page.html
new file mode 100644
index 00000000000..733210fcbe3
--- /dev/null
+++ b/chromium/chrome/browser/resources/interventions_internals/unsupported_page.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width">
+ <title>Interventions-Internals</title>
+ <link rel="stylesheet" type="text/css" href="index.css">
+ </head>
+
+ <body>
+ <div class="error-messages">
+ <div class="error-header">
+ Not supported.
+ </div>
+ <div class="error-message">
+ chrome://interventions-internals is not supported in Guest Mode or
+ Incognito mode.
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/chromium/chrome/browser/resources/local_ntp/OWNERS b/chromium/chrome/browser/resources/local_ntp/OWNERS
index 8d329af858c..9c2e2d6a1f3 100644
--- a/chromium/chrome/browser/resources/local_ntp/OWNERS
+++ b/chromium/chrome/browser/resources/local_ntp/OWNERS
@@ -1,5 +1,4 @@
jeremycho@chromium.org
-samarth@chromium.org
mathp@chromium.org
fserb@chromium.org
huangs@chromium.org
diff --git a/chromium/chrome/browser/resources/local_ntp/local_ntp.css b/chromium/chrome/browser/resources/local_ntp/local_ntp.css
index ce120114c42..7c507af4ae1 100644
--- a/chromium/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chromium/chrome/browser/resources/local_ntp/local_ntp.css
@@ -70,18 +70,34 @@ body.hide-fakebox-logo #fakebox {
display: none;
}
-#logo-default {
+#logo-default,
+#logo-non-white,
+#logo-doodle {
+ position: absolute;
+}
+
+#logo-default,
+#logo-doodle {
+ opacity: 0;
+}
+
+#logo-default.fade,
+#logo-doodle.fade {
+ transition: opacity 130ms;
+}
+
+#logo-default,
+#logo-non-white {
background-image: url(../../../../ui/webui/resources/images/google_logo.svg);
background-repeat: no-repeat;
- bottom: 0;
height: 92px;
left: calc(50% - 272px/2);
- position: absolute;
- transition: opacity 130ms;
+ top: 157px;
width: 272px;
}
-body.alternate-logo #logo-default {
+body.alternate-logo #logo-default,
+body.alternate-logo #logo-non-white {
-webkit-mask-image:
url(../../../../ui/webui/resources/images/google_logo.svg);
-webkit-mask-repeat: no-repeat;
@@ -89,6 +105,106 @@ body.alternate-logo #logo-default {
background: #eee;
}
+#logo-default,
+.non-white-bg #logo-non-white {
+ display: block;
+}
+#logo-non-white,
+.non-white-bg #logo-default {
+ display: none;
+}
+
+#logo-doodle {
+ /* Normally, logos are aligned with tiles and bounded to their left and right
+ * edges. Doodles may be larger than this. In order that they are centered and
+ * cropped, instead of left-aligned, give them 100px of extra space on the
+ * left and the right side.
+ */
+ left: -100px;
+ right: -100px;
+ top: 44px;
+}
+
+#logo-doodle-link {
+ cursor: pointer;
+ margin: 0 auto;
+}
+
+.non-white-bg #logo-doodle-link {
+ display: none;
+}
+
+#logo-doodle-notifier {
+ display: none;
+}
+.non-white-bg #logo-doodle-notifier {
+ cursor: pointer;
+ display: inline-block;
+ height: 24px;
+ left: 148px;
+ position: relative;
+ top: 100px;
+ width: 24px;
+}
+@keyframes anim-pos {
+ 0% { transform: translate(-98%, 0); }
+ 100% { transform: translate(98%, 0); }
+}
+@keyframes anim-z-order {
+ 0% { z-index: 100; }
+ 100% { z-index: 1; }
+}
+.non-white-bg #logo-doodle-notifier .outer {
+ animation: anim-z-order 3520ms linear infinite;
+ height: 37.5%;
+ left: 50%;
+ margin-left: -18.75%;
+ margin-top: -18.75%;
+ position: absolute;
+ top: 50%;
+ width: 37.5%;
+}
+.non-white-bg #logo-doodle-notifier .inner {
+ animation: anim-pos 880ms cubic-bezier(0.445, 0.05, 0.55, 0.95)
+ infinite alternate;
+ border-radius: 50%;
+ height: 100%;
+ position: absolute;
+ transform: rotate(90deg);
+ width: 100%;
+}
+.non-white-bg #logo-doodle-notifier .ball0 {
+ animation-delay: 2640ms;
+ transform: rotate(45deg);
+}
+.non-white-bg #logo-doodle-notifier .ball1 {
+ animation-delay: 1760ms;
+ transform: rotate(135deg);
+}
+.non-white-bg #logo-doodle-notifier .ball2 {
+ transform: rotate(225deg);
+}
+.non-white-bg #logo-doodle-notifier .ball3 {
+ animation-delay: 880ms;
+ transform: rotate(315deg);
+}
+.non-white-bg #logo-doodle-notifier .ball0 .inner {
+ background: linear-gradient(
+ 315deg, rgb(0, 85, 221), rgb(0, 119, 255), rgb(0, 119, 255));
+}
+.non-white-bg #logo-doodle-notifier .ball1 .inner {
+ background: linear-gradient(
+ 225deg, rgb(221, 0, 0), rgb(238, 51, 51), rgb(255, 119, 85));
+}
+.non-white-bg #logo-doodle-notifier .ball2 .inner {
+ background: linear-gradient(
+ 90deg, rgb(0, 119, 68), rgb(0, 153, 68), rgb(85, 187, 85));
+}
+.non-white-bg #logo-doodle-notifier .ball3 .inner {
+ background: linear-gradient(
+ 0deg, rgb(255, 170, 51), rgb(255, 204, 0), rgb(255, 221, 102));
+}
+
#fakebox {
background-color: #fff;
border-radius: 2px;
@@ -168,7 +284,7 @@ html[dir=rtl] #fakebox-cursor {
right: 13px;
}
-#fakebox-speech {
+#fakebox-microphone {
background: url(googlemic_clr_24px.svg) no-repeat center;
background-size: 24px 24px;
cursor: pointer;
@@ -179,7 +295,7 @@ html[dir=rtl] #fakebox-cursor {
width: 17px;
}
-html[dir=rtl] #fakebox-speech {
+html[dir=rtl] #fakebox-microphone {
left: 0;
right: auto;
}
diff --git a/chromium/chrome/browser/resources/local_ntp/local_ntp.html b/chromium/chrome/browser/resources/local_ntp/local_ntp.html
index 5722d6c1f6c..82ed2ab45ba 100644
--- a/chromium/chrome/browser/resources/local_ntp/local_ntp.html
+++ b/chromium/chrome/browser/resources/local_ntp/local_ntp.html
@@ -16,6 +16,8 @@
<meta charset="utf-8">
<meta name="google" value="notranslate">
</head>
+<!-- Remember to update the test HTML files in chrome/test/data/local_ntp/
+ whenever making changes to this file.-->
<body>
<!-- Container for the OneGoogleBar HTML. -->
<div id="one-google" class="hidden"></div>
@@ -26,13 +28,28 @@
<div id="logo">
<!-- The logo that is displayed in the absence of a doodle. -->
<div id="logo-default" title="Google"></div>
+ <!-- Logo displayed when theme prevents doodles. Doesn't fade. -->
+ <div id="logo-non-white" title="Google"></div>
+ <!-- A doodle, if any: its link and image. -->
+ <div id="logo-doodle">
+ <a id="logo-doodle-link">
+ <img id="logo-doodle-image"></img>
+ </a>
+ <!-- A spinner, visible on dark-themed NTPs, prompting the doodle -->
+ <div id="logo-doodle-notifier">
+ <div class="outer ball0"><div class="inner"></div></div>
+ <div class="outer ball1"><div class="inner"></div></div>
+ <div class="outer ball2"><div class="inner"></div></div>
+ <div class="outer ball3"><div class="inner"></div></div>
+ </div>
+ </div>
</div>
<div id="fakebox">
<div id="fakebox-text"></div>
- <input id="fakebox-input" autocomplete="off" tabIndex="-1" type="url"
+ <input id="fakebox-input" autocomplete="off" tabindex="-1" type="url"
aria-hidden="true">
<div id="fakebox-cursor"></div>
- <div id="fakebox-speech" tabIndex="0" hidden></div>
+ <div id="fakebox-microphone" tabindex="1" hidden></div>
</div>
</div>
<div id="most-visited">
@@ -43,9 +60,9 @@
<span id="mv-msg"></span>
<!-- Links in the notification. -->
<span id="mv-notice-links">
- <span id="mv-undo" tabIndex="1"></span>
- <span id="mv-restore" tabIndex="1"></span>
- <div id="mv-notice-x" tabIndex="1"></div>
+ <span id="mv-undo" tabindex="2"></span>
+ <span id="mv-restore" tabindex="2"></span>
+ <div id="mv-notice-x" tabindex="2"></div>
</span>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/local_ntp/local_ntp.js b/chromium/chrome/browser/resources/local_ntp/local_ntp.js
index 2c3869364ab..cabafe39fd5 100644
--- a/chromium/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chromium/chrome/browser/resources/local_ntp/local_ntp.js
@@ -54,11 +54,12 @@ var NTP_DESIGN = {
* @const
*/
var CLASSES = {
- ALTERNATE_LOGO: 'alternate-logo', // Shows white logo if required by theme
+ ALTERNATE_LOGO: 'alternate-logo', // Shows white logo if required by theme
DARK: 'dark',
DEFAULT_THEME: 'default-theme',
DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide',
- FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox
+ FADE: 'fade', // Enables opacity transition on logo and doodle.
+ FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox
// Applies drag focus style to the fakebox
FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused',
HIDE_FAKEBOX_AND_LOGO: 'hide-fakebox-logo',
@@ -66,6 +67,7 @@ var CLASSES = {
LEFT_ALIGN_ATTRIBUTION: 'left-align-attribution',
// Vertically centers the most visited section for a non-Google provided page.
NON_GOOGLE_PAGE: 'non-google-page',
+ NON_WHITE_BG: 'non-white-bg',
RTL: 'rtl' // Right-to-left language text.
};
@@ -82,8 +84,13 @@ var IDS = {
FAKEBOX: 'fakebox',
FAKEBOX_INPUT: 'fakebox-input',
FAKEBOX_TEXT: 'fakebox-text',
- FAKEBOX_SPEECH: 'fakebox-speech',
+ FAKEBOX_MICROPHONE: 'fakebox-microphone',
LOGO: 'logo',
+ LOGO_DEFAULT: 'logo-default',
+ LOGO_DOODLE: 'logo-doodle',
+ LOGO_DOODLE_IMAGE: 'logo-doodle-image',
+ LOGO_DOODLE_LINK: 'logo-doodle-link',
+ LOGO_DOODLE_NOTIFIER: 'logo-doodle-notifier',
NOTIFICATION: 'mv-notice',
NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x',
NOTIFICATION_MESSAGE: 'mv-msg',
@@ -96,6 +103,45 @@ var IDS = {
/**
+ * The different types of events that are logged from the NTP. This enum is
+ * used to transfer information from the NTP JavaScript to the renderer and is
+ * not used as a UMA enum histogram's logged value.
+ * Note: Keep in sync with common/ntp_logging_events.h
+ * @enum {number}
+ * @const
+ */
+var LOG_TYPE = {
+ // A static Doodle was shown, coming from cache.
+ NTP_STATIC_LOGO_SHOWN_FROM_CACHE: 30,
+ // A static Doodle was shown, coming from the network.
+ NTP_STATIC_LOGO_SHOWN_FRESH: 31,
+ // A call-to-action Doodle image was shown, coming from cache.
+ NTP_CTA_LOGO_SHOWN_FROM_CACHE: 32,
+ // A call-to-action Doodle image was shown, coming from the network.
+ NTP_CTA_LOGO_SHOWN_FRESH: 33,
+
+ // A static Doodle was clicked.
+ NTP_STATIC_LOGO_CLICKED: 34,
+ // A call-to-action Doodle was clicked.
+ NTP_CTA_LOGO_CLICKED: 35,
+ // An animated Doodle was clicked.
+ NTP_ANIMATED_LOGO_CLICKED: 36,
+
+ // The One Google Bar was shown.
+ NTP_ONE_GOOGLE_BAR_SHOWN: 37,
+};
+
+
+/**
+ * Background colors considered "white". Used to determine if it is possible
+ * to display a Google Doodle, or if the notifier should be used instead.
+ * @type {Array<string>}
+ * @const
+ */
+var WHITE_BACKGROUND_COLORS = ['rgba(255,255,255,1)', 'rgba(0,0,0,0)'];
+
+
+/**
* Enum for keycodes.
* @enum {number}
* @const
@@ -125,13 +171,36 @@ var MAX_NUM_TILES_TO_SHOW = 8;
/**
+ * Returns theme background info, first checking for history.state.notheme. If
+ * the page has notheme set, returns a fallback light-colored theme.
+ */
+function getThemeBackgroundInfo() {
+ if (history.state && history.state.notheme) {
+ return {
+ alternateLogo: false,
+ backgroundColorRgba: [255, 255, 255, 255],
+ colorRgba: [255, 255, 255, 255],
+ headerColorRgba: [150, 150, 150, 255],
+ linkColorRgba: [6, 55, 116, 255],
+ sectionBorderColorRgba: [150, 150, 150, 255],
+ textColorLightRgba: [102, 102, 102, 255],
+ textColorRgba: [0, 0, 0, 255],
+ usingDefaultTheme: true,
+ };
+ }
+ return ntpApiHandle.themeBackgroundInfo;
+}
+
+
+/**
* Heuristic to determine whether a theme should be considered to be dark, so
* the colors of various UI elements can be adjusted.
* @param {ThemeBackgroundInfo|undefined} info Theme background information.
* @return {boolean} Whether the theme is dark.
* @private
*/
-function getIsThemeDark(info) {
+function getIsThemeDark() {
+ var info = getThemeBackgroundInfo();
if (!info)
return false;
// Heuristic: light text implies dark theme.
@@ -146,8 +215,8 @@ function getIsThemeDark(info) {
* @private
*/
function renderTheme() {
- var info = ntpApiHandle.themeBackgroundInfo;
- var isThemeDark = getIsThemeDark(info);
+ var info = getThemeBackgroundInfo();
+ var isThemeDark = getIsThemeDark();
$(IDS.NTP_CONTENTS).classList.toggle(CLASSES.DARK, isThemeDark);
if (!info) {
return;
@@ -161,6 +230,8 @@ function renderTheme() {
document.body.style.background = background;
document.body.classList.toggle(CLASSES.ALTERNATE_LOGO, info.alternateLogo);
+ var isNonWhiteBackground = !WHITE_BACKGROUND_COLORS.includes(background);
+ document.body.classList.toggle(CLASSES.NON_WHITE_BG, isNonWhiteBackground);
updateThemeAttribution(info.attributionUrl, info.imageHorizontalAlignment);
setCustomThemeStyle(info);
@@ -194,7 +265,7 @@ function renderOneGoogleBarTheme() {
var oneGoogleBarApi = window.gbar.a;
var oneGoogleBarPromise = oneGoogleBarApi.bf();
oneGoogleBarPromise.then(function(oneGoogleBar) {
- var isThemeDark = getIsThemeDark(ntpApiHandle.themeBackgroundInfo);
+ var isThemeDark = getIsThemeDark();
var setForegroundStyle = oneGoogleBar.pc.bind(oneGoogleBar);
setForegroundStyle(isThemeDark ? 1 : 0);
});
@@ -428,7 +499,7 @@ function isFakeboxFocused() {
*/
function isFakeboxClick(event) {
return $(IDS.FAKEBOX).contains(event.target) &&
- !$(IDS.FAKEBOX_SPEECH).contains(event.target);
+ !$(IDS.FAKEBOX_MICROPHONE).contains(event.target);
}
@@ -454,21 +525,32 @@ function registerKeyHandler(element, keycode, handler) {
/**
- * Event handler for the focus changed and blacklist messages on link elements.
- * Used to toggle visual treatment on the tiles (depending on the message).
+ * Event handler for messages from the most visited iframe.
* @param {Event} event Event received.
*/
function handlePostMessage(event) {
var cmd = event.data.cmd;
var args = event.data;
- if (cmd == 'tileBlacklisted') {
+ if (cmd == 'loaded') {
+ if (configData.isGooglePage && !$('one-google-loader')) {
+ // Load the OneGoogleBar script. It'll create a global variable name "og"
+ // which is a dict corresponding to the native OneGoogleBarData type.
+ // We do this only after all the tiles have loaded, to avoid slowing down
+ // the main page load.
+ var ogScript = document.createElement('script');
+ ogScript.id = 'one-google-loader';
+ ogScript.src = 'chrome-search://local-ntp/one-google.js';
+ document.body.appendChild(ogScript);
+ ogScript.onload = function() {
+ injectOneGoogleBar(og);
+ };
+ }
+ } else if (cmd == 'tileBlacklisted') {
showNotification();
lastBlacklistedTile = args.tid;
ntpApiHandle.deleteMostVisitedItem(args.tid);
}
- // TODO(treib): Should we also handle the 'loaded' message from the iframe
- // here? We could hide the page until it arrives, to avoid flicker.
}
@@ -522,7 +604,7 @@ function init() {
if (configData.isVoiceSearchEnabled) {
speech.init(
configData.googleBaseUrl, configData.translatedStrings,
- $(IDS.FAKEBOX_SPEECH), searchboxApiHandle);
+ $(IDS.FAKEBOX_MICROPHONE), searchboxApiHandle);
}
// Listener for updating the key capture state.
@@ -561,14 +643,39 @@ function init() {
// Update the fakebox style to match the current key capturing state.
setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled);
- // Load the OneGoogleBar script. It'll create a global variable name "og"
- // which is a dict corresponding to the native OneGoogleBarData type.
- var ogScript = document.createElement('script');
- ogScript.src = 'chrome-search://local-ntp/one-google.js';
- document.body.appendChild(ogScript);
- ogScript.onload = function() {
- injectOneGoogleBar(og);
- };
+ // Load the Doodle. After the first request completes (getting cached
+ // data), issue a second request for fresh Doodle data.
+ loadDoodle(/*v=*/null, function(ddl) {
+ if (ddl === null) {
+ // Got no ddl object at all, the feature is probably disabled. Just show
+ // the logo.
+ showLogoOrDoodle(null, null, /*fromCache=*/true);
+ return;
+ }
+
+ // Got a (possibly empty) ddl object. Show logo or doodle.
+ showLogoOrDoodle(
+ ddl.image || null, ddl.metadata || null, /*fromCache=*/true);
+ // If we got a valid ddl object (from cache), load a fresh one.
+ if (ddl.v !== null) {
+ loadDoodle(ddl.v, function(ddl) {
+ if (ddl.usable) {
+ fadeToLogoOrDoodle(ddl.image, ddl.metadata);
+ }
+ });
+ }
+ });
+
+ // Set up doodle notifier (but it may be invisible).
+ var doodleNotifier = $(IDS.LOGO_DOODLE_NOTIFIER);
+ doodleNotifier.title = configData.translatedStrings.clickToViewDoodle;
+ doodleNotifier.addEventListener('click', function(e) {
+ e.preventDefault();
+ var state = window.history.state || {};
+ state.notheme = true;
+ window.history.replaceState(state, document.title);
+ onThemeChange();
+ });
} else {
document.body.classList.add(CLASSES.NON_GOOGLE_PAGE);
}
@@ -648,9 +755,186 @@ function injectOneGoogleBar(ogb) {
endOfBodyScript.type = 'text/javascript';
endOfBodyScript.appendChild(document.createTextNode(ogb.endOfBodyScript));
document.body.appendChild(endOfBodyScript);
+
+ ntpApiHandle.logEvent(LOG_TYPE.NTP_ONE_GOOGLE_BAR_SHOWN);
}
+/** Loads the Doodle. On success, the loaded script declares a global variable
+ * ddl, which onload() receives as its single argument. On failure, onload() is
+ * called with null as the argument. If v is null, then the call requests a
+ * cached logo. If non-null, it must be the ddl.v of a previous request for a
+ * cached logo, and the corresponding fresh logo is returned.
+ * @param {?number} v
+ * @param {function(?{v, usable, image, metadata})} onload
+ */
+var loadDoodle = function(v, onload) {
+ var ddlScript = document.createElement('script');
+ ddlScript.src = 'chrome-search://local-ntp/doodle.js';
+ if (v !== null)
+ ddlScript.src += '?v=' + v;
+ ddlScript.onload = function() {
+ onload(ddl);
+ };
+ ddlScript.onerror = function() {
+ onload(null);
+ };
+ // TODO(treib,sfiera): Add a timeout in case something goes wrong?
+ document.body.appendChild(ddlScript);
+};
+
+
+/** Returns true if |element| is fully hidden. Returns false if fully visible,
+ * fading in, or fading out.
+ * @param {HTMLElement} element
+ */
+var isFadedOut = function(element) {
+ return (element.style.opacity == 0) &&
+ (window.getComputedStyle(element).opacity == 0);
+};
+
+
+/** Returns true if the doodle given by |image| and |metadata| is currently
+ * visible. If |image| is null, returns true when the default logo is visible;
+ * if non-null, checks that it matches the doodle that is currently visible.
+ * Here, "visible" means fully-visible or fading in.
+ *
+ * @param {?Object} image
+ * @param {?Object} metadata
+ * @returns {boolean}
+ */
+var isDoodleCurrentlyVisible = function(image, metadata) {
+ var haveDoodle = ($(IDS.LOGO_DOODLE).style.opacity != 0);
+ var wantDoodle = (image !== null) && (metadata !== null);
+ if (!haveDoodle || !wantDoodle)
+ return haveDoodle === wantDoodle;
+
+ // Have a visible doodle and a query doodle. Test that they match.
+ var logoDoodleImage = $(IDS.LOGO_DOODLE_IMAGE);
+ return (logoDoodleImage.src === image) ||
+ (logoDoodleImage.src === metadata.animatedUrl);
+};
+
+
+var showLogoOrDoodle = function(image, metadata, fromCache) {
+ if (metadata !== null) {
+ applyDoodleMetadata(metadata);
+ $(IDS.LOGO_DOODLE_IMAGE).src = image;
+ $(IDS.LOGO_DOODLE).style.opacity = 1;
+
+ var isCta = !!metadata.animatedUrl;
+ var eventType = isCta ?
+ (fromCache ? LOG_TYPE.NTP_CTA_LOGO_SHOWN_FROM_CACHE :
+ LOG_TYPE.NTP_CTA_LOGO_SHOWN_FRESH) :
+ (fromCache ? LOG_TYPE.NTP_STATIC_LOGO_SHOWN_FROM_CACHE :
+ LOG_TYPE.NTP_STATIC_LOGO_SHOWN_FRESH);
+ ntpApiHandle.logEvent(eventType);
+ } else {
+ $(IDS.LOGO_DEFAULT).style.opacity = 1;
+ }
+};
+
+
+/** The image and metadata that should be shown, according to the latest fetch.
+ * After a logo fades out, onDoodleTransitionEnd fades in a logo according to
+ * targetDoodle.
+ */
+var targetDoodle = {
+ image: null,
+ metadata: null,
+};
+
+
+/**
+ * Starts fading out the given element, which should be either the default logo
+ * or the doodle.
+ *
+ * @param {HTMLElement} element
+ */
+var startFadeOut = function(element) {
+ // Compute style now, to ensure that the transition from 1 -> 0 is properly
+ // recognized. Otherwise, if a 0 -> 1 -> 0 transition is too fast, the
+ // element might stay invisible instead of appearing then fading out.
+ window.getComputedStyle(element).opacity;
+
+ element.classList.add(CLASSES.FADE);
+ element.addEventListener('transitionend', onDoodleTransitionEnd);
+ element.style.opacity = 0;
+};
+
+
+/**
+ * Integrates a fresh doodle into the page as appropriate. If the correct logo
+ * or doodle is already shown, just updates the metadata. Otherwise, initiates
+ * a fade from the currently-shown logo/doodle to the new one.
+ *
+ * @param {?Object} image
+ * @param {?Object} metadata
+ */
+var fadeToLogoOrDoodle = function(image, metadata) {
+ // If the image is already visible, there's no need to start a fade-out.
+ // However, metadata may have changed, so update the doodle's alt text and
+ // href, if applicable.
+ if (isDoodleCurrentlyVisible(image, metadata)) {
+ if (metadata !== null) {
+ applyDoodleMetadata(metadata);
+ }
+ return;
+ }
+
+ // Set the target to use once the current logo/doodle has finished fading out.
+ targetDoodle.image = image;
+ targetDoodle.metadata = metadata;
+
+ // Start fading out the current logo or doodle. onDoodleTransitionEnd will
+ // apply the change when the fade-out finishes.
+ startFadeOut($(IDS.LOGO_DEFAULT));
+ startFadeOut($(IDS.LOGO_DOODLE));
+};
+
+
+var onDoodleTransitionEnd = function(e) {
+ var logoDoodle = $(IDS.LOGO_DOODLE);
+ var logoDoodleImage = $(IDS.LOGO_DOODLE_IMAGE);
+ var logoDefault = $(IDS.LOGO_DEFAULT);
+
+ if (isFadedOut(logoDoodle) && isFadedOut(logoDefault)) {
+ // Fade-out finished. Start fading in the appropriate logo.
+ showLogoOrDoodle(
+ targetDoodle.image, targetDoodle.metadata, /*fromCache=*/false);
+
+ logoDefault.removeEventListener('transitionend', onDoodleTransitionEnd);
+ logoDoodle.removeEventListener('transitionend', onDoodleTransitionEnd);
+ }
+};
+
+
+var applyDoodleMetadata = function(metadata) {
+ var logoDoodleLink = $(IDS.LOGO_DOODLE_LINK);
+ var logoDoodleImage = $(IDS.LOGO_DOODLE_IMAGE);
+
+ logoDoodleImage.title = metadata.altText;
+
+ if (metadata.animatedUrl) {
+ logoDoodleLink.removeAttribute('href');
+ logoDoodleLink.onclick = function(e) {
+ ntpApiHandle.logEvent(LOG_TYPE.NTP_CTA_LOGO_CLICKED);
+ e.preventDefault();
+ logoDoodleImage.src = metadata.animatedUrl;
+ logoDoodleLink.href = metadata.onClickUrl;
+ logoDoodleLink.onclick = function() {
+ ntpApiHandle.logEvent(LOG_TYPE.NTP_ANIMATED_LOGO_CLICKED);
+ };
+ };
+ } else {
+ logoDoodleLink.href = metadata.onClickUrl;
+ logoDoodleLink.onclick = function() {
+ ntpApiHandle.logEvent(LOG_TYPE.NTP_STATIC_LOGO_CLICKED);
+ };
+ }
+};
+
+
return {
init: init, // Exposed for testing.
listen: listen
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 45e98035dc2..446873a2ce6 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_single.js
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -27,6 +27,21 @@ var LOG_TYPE = {
/**
+ * The different sources where an NTP tile's title can originate from.
+ * Note: Keep in sync with components/ntp_tiles/tile_title_source.h
+ * @enum {number}
+ * @const
+ */
+var TileTitleSource = {
+ UNKNOWN: 0,
+ MANIFEST: 1,
+ META_TAG: 2,
+ TITLE: 3,
+ INFERRED: 4
+};
+
+
+/**
* The different sources that an NTP tile can have.
* Note: Keep in sync with components/ntp_tiles/tile_source.h
* @enum {number}
@@ -113,23 +128,31 @@ var logEvent = function(eventType) {
/**
* Log impression of an NTP tile.
* @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES.
+ * @param {number} tileTitleSource The title's source from TileTitleSource.
* @param {number} tileSource The source from TileSource.
* @param {number} tileType The type from TileVisualType.
+ * @param {Date} dataGenerationTime Timestamp representing when the tile was
+ * produced by a ranking algorithm.
*/
-function logMostVisitedImpression(tileIndex, tileSource, tileType) {
+function logMostVisitedImpression(
+ tileIndex, tileTitleSource, tileSource, tileType, dataGenerationTime) {
chrome.embeddedSearch.newTabPage.logMostVisitedImpression(
- tileIndex, tileSource, tileType);
+ tileIndex, tileTitleSource, tileSource, tileType, dataGenerationTime);
}
/**
* Log click on an NTP tile.
* @param {number} tileIndex Position of the tile, >= 0 and < NUMBER_OF_TILES.
+ * @param {number} tileTitleSource The title's source from TileTitleSource.
* @param {number} tileSource The source from TileSource.
* @param {number} tileType The type from TileVisualType.
+ * @param {Date} dataGenerationTime Timestamp representing when the tile was
+ * produced by a ranking algorithm.
*/
-function logMostVisitedNavigation(tileIndex, tileSource, tileType) {
+function logMostVisitedNavigation(
+ tileIndex, tileTitleSource, tileSource, tileType, dataGenerationTime) {
chrome.embeddedSearch.newTabPage.logMostVisitedNavigation(
- tileIndex, tileSource, tileType);
+ tileIndex, tileTitleSource, tileSource, tileType, dataGenerationTime);
}
/**
@@ -305,8 +328,7 @@ var swapInNewTiles = function() {
*/
var addTile = function(args) {
if (isFinite(args.rid)) {
- // If a valid number passed in |args.rid|: a local Chrome suggestion. Grab
- // the data from the embeddedSearch API.
+ // An actual suggestion. Grab the data from the embeddedSearch API.
var data =
chrome.embeddedSearch.newTabPage.getMostVisitedItemData(args.rid);
if (!data)
@@ -318,15 +340,8 @@ var addTile = function(args) {
window.devicePixelRatio + 'x/' + data.renderViewId + '/' + data.tid;
}
tiles.appendChild(renderTile(data));
- } else if (args.url) {
- // If a URL is passed: a server-side suggestion.
- args.tileSource = TileSource.SUGGESTIONS_SERVICE;
- // check sanity of the arguments
- if (/^javascript:/i.test(args.url) ||
- /^javascript:/i.test(args.thumbnailUrl))
- return;
- tiles.appendChild(renderTile(args));
- } else { // an empty tile
+ } else {
+ // An empty tile
tiles.appendChild(renderTile(null));
}
};
@@ -395,7 +410,9 @@ var renderTile = function(data) {
tile.title = data.title;
tile.addEventListener('click', function(ev) {
- logMostVisitedNavigation(position, data.tileSource, tileType);
+ logMostVisitedNavigation(
+ position, data.tileTitleSource, data.tileSource, tileType,
+ data.dataGenerationTime);
});
tile.addEventListener('keydown', function(event) {
@@ -455,7 +472,9 @@ var renderTile = function(data) {
img.addEventListener('load', function(ev) {
// Store the type for a potential later navigation.
tileType = TileVisualType.THUMBNAIL;
- logMostVisitedImpression(position, data.tileSource, tileType);
+ logMostVisitedImpression(
+ position, data.tileTitleSource, data.tileSource, tileType,
+ data.dataGenerationTime);
// Note: It's important to call countLoad last, because that might emit the
// NTP_ALL_TILES_LOADED event, which must happen after the impression log.
countLoad();
@@ -465,7 +484,9 @@ var renderTile = function(data) {
thumb.removeChild(img);
// Store the type for a potential later navigation.
tileType = TileVisualType.THUMBNAIL_FAILED;
- logMostVisitedImpression(position, data.tileSource, tileType);
+ logMostVisitedImpression(
+ position, data.tileTitleSource, data.tileSource, tileType,
+ data.dataGenerationTime);
// Note: It's important to call countLoad last, because that might emit the
// NTP_ALL_TILES_LOADED event, which must happen after the impression log.
countLoad();
@@ -473,21 +494,17 @@ var renderTile = function(data) {
thumb.appendChild(img);
var favicon = tile.querySelector('.mv-favicon');
- if (data.faviconUrl) {
- var fi = document.createElement('img');
- fi.src = data.faviconUrl;
- // Set the title to empty so screen readers won't say the image name.
- fi.title = '';
- loadedCounter += 1;
- fi.addEventListener('load', countLoad);
- fi.addEventListener('error', countLoad);
- fi.addEventListener('error', function(ev) {
- favicon.classList.add('failed-favicon');
- });
- favicon.appendChild(fi);
- } else {
+ var fi = document.createElement('img');
+ fi.src = data.faviconUrl;
+ // Set the title to empty so screen readers won't say the image name.
+ fi.title = '';
+ loadedCounter += 1;
+ fi.addEventListener('load', countLoad);
+ fi.addEventListener('error', countLoad);
+ fi.addEventListener('error', function(ev) {
favicon.classList.add('failed-favicon');
- }
+ });
+ favicon.appendChild(fi);
var mvx = tile.querySelector('.mv-x');
mvx.addEventListener('click', function(ev) {
diff --git a/chromium/chrome/browser/resources/local_ntp/most_visited_util.js b/chromium/chrome/browser/resources/local_ntp/most_visited_util.js
index 63a6f03056f..12eb39e78d5 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_util.js
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_util.js
@@ -225,13 +225,7 @@ function fillMostVisited(location, fill) {
domain: params.dom || ''
};
} else {
- var apiHandle = chrome.embeddedSearch.newTabPage;
- // Note: This does not actually result in any logging; it's a workaround for
- // crbug.com/698675. It effectively sets the "instant support" state of the
- // tab to true, which makes later calls to fetch the most visited items
- // succeed.
- apiHandle.logEvent(NTP_LOGGING_EVENT_TYPE.NTP_ALL_TILES_RECEIVED);
- data = apiHandle.getMostVisitedItemData(params.rid);
+ data = chrome.embeddedSearch.newTabPage.getMostVisitedItemData(params.rid);
if (!data)
return;
}
diff --git a/chromium/chrome/browser/resources/local_ntp/voice.css b/chromium/chrome/browser/resources/local_ntp/voice.css
index 37f783b1623..bcd24e9fa0e 100644
--- a/chromium/chrome/browser/resources/local_ntp/voice.css
+++ b/chromium/chrome/browser/resources/local_ntp/voice.css
@@ -78,6 +78,11 @@
width: 15px;
}
+html[dir=rtl] .close-button {
+ left: 0;
+ right: auto;
+}
+
.close-button:hover {
opacity: .8;
}
@@ -189,6 +194,10 @@
transition: transform 218ms, opacity 218ms ease-in;
}
+html[dir=rtl] .button-container {
+ float: left;
+}
+
/* Common styles applied to the button-container. */
.overlay .button-container,
.overlay-hidden .button-container {
@@ -198,6 +207,12 @@
width: 165px;
}
+html[dir=rtl] .overlay .button-container,
+html[dir=rtl] .overlay-hidden .button-container {
+ left: -70px;
+ right: auto;
+}
+
/* Container style when speech recognition is inactive. */
.overlay-hidden .button-container {
transform: scale(.1);
@@ -216,7 +231,6 @@
/* TEXT */
/* Classes:
* - voice-text - Text area style class
- * - voice-text-area - Link style class
* - voice-text-2l - 2 line style class
* - voice-text-3l - 3 line style class
* - voice-text-4l - 4 line style class
@@ -245,11 +259,20 @@
top 0s linear 218ms;
}
+html[dir=rtl] .voice-text {
+ text-align: right;
+}
+
/* Recognition results text hidden in the Full Page UI. */
.overlay-hidden .voice-text {
margin-left: 44px;
}
+html[dir=rtl] .overlay-hidden .voice-text {
+ margin-left: 0;
+ margin-right: 44px;
+}
+
/* Styles applied to the text output elements. Common style for the text area
* class for the full Page UI. To vertically center the text as longer queries
* are wrapped, the 'top' position is specified in em here and below. */
@@ -261,6 +284,12 @@
width: 460px;
}
+html[dir=rtl] .overlay .voice-text,
+html[dir=rtl] .overlay-hidden .voice-text {
+ left: auto;
+ right: -44px;
+}
+
/* Common style for when the text areas are made visible. */
.overlay .voice-text {
margin-left: 0;
@@ -268,6 +297,11 @@
transition: opacity 500ms ease-out, margin-left 500ms ease-out;
}
+html[dir=rtl] .overlay .voice-text {
+ margin-left: auto;
+ margin-right: 0;
+}
+
/* Interim (low confidence) text. */
#voice-text-i {
color: var(--grey);
@@ -279,7 +313,7 @@
}
/* Text area links. */
-#voice-text-area {
+.voice-text-link {
color: var(--text_link_color);
cursor: pointer;
font-size: 18px;
@@ -350,6 +384,7 @@
/* Container element for microphone icon. */
.microphone {
+ direction: ltr;
height: 87px;
left: 43px;
pointer-events: none;
diff --git a/chromium/chrome/browser/resources/local_ntp/voice.js b/chromium/chrome/browser/resources/local_ntp/voice.js
index 3e8623c89d5..1ba0323c44e 100644
--- a/chromium/chrome/browser/resources/local_ntp/voice.js
+++ b/chromium/chrome/browser/resources/local_ntp/voice.js
@@ -36,20 +36,59 @@ function getChromeUILanguage() {
/**
- * Enum for keycodes.
- * @enum {number}
+ * The different types of user action and error events that are logged
+ * from Voice Search. This enum is used to transfer information to
+ * the renderer and is not used as a UMA enum histogram's logged value.
+ * Note: Keep in sync with common/ntp_logging_events.h
+ * @enum {!number}
+ * @const
+ */
+const LOG_TYPE = {
+ // Activated by clicking on the fakebox icon.
+ ACTION_ACTIVATE_FAKEBOX: 13,
+ // Activated by keyboard shortcut.
+ ACTION_ACTIVATE_KEYBOARD: 14,
+ // Close the voice overlay by a user's explicit action.
+ ACTION_CLOSE_OVERLAY: 15,
+ // Submitted voice query.
+ ACTION_QUERY_SUBMITTED: 16,
+ // Clicked on support link in error message.
+ ACTION_SUPPORT_LINK_CLICKED: 17,
+ // Retried by clicking Try Again link.
+ ACTION_TRY_AGAIN_LINK: 18,
+ // Retried by clicking microphone button.
+ ACTION_TRY_AGAIN_MIC_BUTTON: 10,
+ // Errors received from the Speech Recognition API.
+ ERROR_NO_SPEECH: 20,
+ ERROR_ABORTED: 21,
+ ERROR_AUDIO_CAPTURE: 22,
+ ERROR_NETWORK: 23,
+ ERROR_NOT_ALLOWED: 24,
+ ERROR_SERVICE_NOT_ALLOWED: 25,
+ ERROR_BAD_GRAMMAR: 26,
+ ERROR_LANGUAGE_NOT_SUPPORTED: 27,
+ ERROR_NO_MATCH: 28,
+ ERROR_OTHER: 29
+};
+
+
+/**
+ * Enum for keyboard event codes.
+ * @enum {!string}
* @const
*/
const KEYCODE = {
- ENTER: 13,
- ESC: 27,
- PERIOD: 190
+ ENTER: 'Enter',
+ ESC: 'Escape',
+ NUMPAD_ENTER: 'NumpadEnter',
+ PERIOD: 'Period',
+ SPACE: 'Space'
};
/**
* The set of possible recognition errors.
- * @enum {number}
+ * @enum {!number}
* @const
*/
const RecognitionError = {
@@ -85,6 +124,7 @@ let speech = {};
* networkError: string,
* noTranslation: string,
* noVoice: string,
+ * otherError: string,
* permissionError: string,
* ready: string,
* tryAgain: string,
@@ -100,6 +140,7 @@ speech.messages = {
networkError: '',
noTranslation: '',
noVoice: '',
+ otherError: '',
permissionError: '',
ready: '',
tryAgain: '',
@@ -113,7 +154,7 @@ speech.messages = {
* @private
*/
speech.State_ = {
- // Initial state of the controller. Is never re-entered.
+ // Initial state of the controller. It is never re-entered.
// The only state from which the |speech.init()| method can be called.
// The UI overlay is hidden, recognition is inactive.
UNINITIALIZED: -1,
@@ -257,8 +298,17 @@ speech.recognition_;
/**
+ * Log an event from Voice Search.
+ * @param {!number} eventType Event from |LOG_TYPE|.
+ */
+speech.logEvent = function(eventType) {
+ window.chrome.embeddedSearch.newTabPage.logEvent(eventType);
+};
+
+
+/**
* Initialize the speech module as part of the local NTP. Adds event handlers
- * and shows the fakebox speech microphone icon.
+ * and shows the fakebox microphone icon.
* @param {!string} googleBaseUrl Base URL for sending queries to Search.
* @param {!Object} translatedStrings Dictionary of localized string messages.
* @param {!HTMLElement} fakeboxMicrophoneElem Fakebox microphone icon element.
@@ -275,10 +325,18 @@ speech.init = function(
// Initialize event handlers.
fakeboxMicrophoneElem.hidden = false;
fakeboxMicrophoneElem.title = translatedStrings.fakeboxMicrophoneTooltip;
- fakeboxMicrophoneElem.onmouseup = function(event) {
+ fakeboxMicrophoneElem.onclick = function(event) {
// If propagated, closes the overlay (click on the background).
event.stopPropagation();
- speech.toggleStartStop();
+ speech.logEvent(LOG_TYPE.ACTION_ACTIVATE_FAKEBOX);
+ speech.start();
+ };
+ fakeboxMicrophoneElem.onkeydown = function(event) {
+ if (!event.repeat && speech.isSpaceOrEnter_(event.code) &&
+ speech.currentState_ == speech.State_.READY) {
+ event.stopPropagation();
+ speech.start();
+ }
};
window.addEventListener('keydown', speech.onKeyDown);
if (searchboxApiHandle.onfocuschange) {
@@ -297,6 +355,7 @@ speech.init = function(
networkError: translatedStrings.networkError,
noTranslation: translatedStrings.noTranslation,
noVoice: translatedStrings.noVoice,
+ otherError: translatedStrings.otherError,
permissionError: translatedStrings.permissionError,
ready: translatedStrings.ready,
tryAgain: translatedStrings.tryAgain,
@@ -309,27 +368,6 @@ speech.init = function(
/**
- * Resets the internal state of Voice Search and disables the speech
- * recognition interface. Only used for testing.
- * @param {HTMLElement} fakeboxMicrophoneElem Fakebox microphone icon element.
- * @param {!Object} searchboxApiHandle SearchBox API handle.
- * @private
- */
-speech.uninit_ = function(fakeboxMicrophoneElem, searchboxApiHandle) {
- speech.reset_();
- speech.googleBaseUrl_ = null;
- speech.messages = {};
- speech.currentState_ = speech.State_.UNINITIALIZED;
- fakeboxMicrophoneElem.hidden = true;
- fakeboxMicrophoneElem.title = '';
- fakeboxMicrophoneElem.onmouseup = null;
- window.removeEventListener('keydown', speech.onKeyDown);
- searchboxApiHandle.onfocuschange = null;
- speech.recognition_ = null;
-};
-
-
-/**
* Initializes and configures the speech recognition API.
* @private
*/
@@ -338,7 +376,6 @@ speech.initWebkitSpeech_ = function() {
speech.recognition_.continuous = false;
speech.recognition_.interimResults = true;
speech.recognition_.lang = getChromeUILanguage();
- speech.recognition_.maxAlternatives = 4;
speech.recognition_.onaudiostart = speech.handleRecognitionAudioStart_;
speech.recognition_.onend = speech.handleRecognitionEnd_;
speech.recognition_.onerror = speech.handleRecognitionError_;
@@ -351,9 +388,8 @@ speech.initWebkitSpeech_ = function() {
/**
* Sets up the necessary states for voice search and then starts the
* speech recognition interface.
- * @private
*/
-speech.start_ = function() {
+speech.start = function() {
view.show();
speech.resetIdleTimer_(speech.IDLE_TIMEOUT_MS_);
@@ -361,14 +397,14 @@ speech.start_ = function() {
document.addEventListener(
'webkitvisibilitychange', speech.onVisibilityChange_, false);
- if (!speech.isRecognitionInitialized_()) {
+ // Initialize |speech.recognition_| if it isn't already.
+ if (!speech.recognition_) {
speech.initWebkitSpeech_();
}
- // If |speech.start_()| is called too soon after |speech.stop_()| then the
+ // If |speech.start()| is called too soon after |speech.stop()| then the
// recognition interface hasn't yet reset and an error occurs. In this case
// we need to hard-reset it and reissue the |recognition_.start()| command.
- // TODO(oskopek): Add tests + possibly fix the root cause.
try {
speech.recognition_.start();
speech.currentState_ = speech.State_.STARTED;
@@ -378,8 +414,7 @@ speech.start_ = function() {
speech.recognition_.start();
speech.currentState_ = speech.State_.STARTED;
} catch (error2) {
- speech.currentState_ = speech.State_.STOPPED;
- speech.stop_();
+ speech.stop();
}
}
};
@@ -387,9 +422,9 @@ speech.start_ = function() {
/**
* Hides the overlay and resets the speech state.
- * @private
*/
-speech.stop_ = function() {
+speech.stop = function() {
+ speech.recognition_.abort();
speech.currentState_ = speech.State_.STOPPED;
view.hide();
speech.reset_();
@@ -397,16 +432,6 @@ speech.stop_ = function() {
/**
- * Aborts speech recognition and calls |speech.stop_()|.
- * @private
- */
-speech.abort_ = function() {
- speech.recognition_.abort();
- speech.stop_();
-};
-
-
-/**
* Resets the internal state to the READY state.
* @private
*/
@@ -514,6 +539,38 @@ speech.handleRecognitionResult_ = function(responseEvent) {
/**
+ * Convert a |RecognitionError| to a |LOG_TYPE| error constant,
+ * for UMA logging.
+ * @param {RecognitionError} error The received error.
+ * @private
+ */
+speech.errorToLogType_ = function(error) {
+ switch (error) {
+ case RecognitionError.ABORTED:
+ return LOG_TYPE.ERROR_ABORTED;
+ case RecognitionError.AUDIO_CAPTURE:
+ return LOG_TYPE.ERROR_AUDIO_CAPTURE;
+ case RecognitionError.BAD_GRAMMAR:
+ return LOG_TYPE.ERROR_BAD_GRAMMAR;
+ case RecognitionError.LANGUAGE_NOT_SUPPORTED:
+ return LOG_TYPE.ERROR_LANGUAGE_NOT_SUPPORTED;
+ case RecognitionError.NETWORK:
+ return LOG_TYPE.ERROR_NETWORK;
+ case RecognitionError.NO_MATCH:
+ return LOG_TYPE.ERROR_NO_MATCH;
+ case RecognitionError.NO_SPEECH:
+ return LOG_TYPE.ERROR_NO_SPEECH;
+ case RecognitionError.NOT_ALLOWED:
+ return LOG_TYPE.ERROR_NOT_ALLOWED;
+ case RecognitionError.SERVICE_NOT_ALLOWED:
+ return LOG_TYPE.ERROR_SERVICE_NOT_ALLOWED;
+ default:
+ return LOG_TYPE.ERROR_OTHER;
+ }
+};
+
+
+/**
* Handles state transition for the controller when an error occurs
* during speech recognition.
* @param {RecognitionError} error The appropriate error state from
@@ -521,6 +578,7 @@ speech.handleRecognitionResult_ = function(responseEvent) {
* @private
*/
speech.onErrorReceived_ = function(error) {
+ speech.logEvent(speech.errorToLogType_(error));
speech.resetIdleTimer_(speech.IDLE_TIMEOUT_MS_);
speech.errorTimeoutMs_ = speech.getRecognitionErrorTimeout_(error);
if (error != RecognitionError.ABORTED) {
@@ -558,7 +616,6 @@ speech.handleRecognitionOnNoMatch_ = function() {
*/
speech.handleRecognitionEnd_ = function() {
window.clearTimeout(speech.idleTimer_);
- window.clearTimeout(speech.permissionTimer_);
let error;
switch (speech.currentState_) {
@@ -589,6 +646,34 @@ speech.handleRecognitionEnd_ = function() {
/**
+ * Determines whether the user's browser is probably running on a Mac.
+ * @return {boolean} True iff the user's browser is running on a Mac.
+ * @private
+ */
+speech.isUserAgentMac_ = function() {
+ return window.navigator.userAgent.includes('Macintosh');
+};
+
+
+/**
+ * Determines, if the given KeyboardEvent |code| is a space or enter key.
+ * @param {!string} A KeyboardEvent's |code| property.
+ * @return True, iff the code represents a space or enter key.
+ * @private
+ */
+speech.isSpaceOrEnter_ = function(code) {
+ switch (code) {
+ case KEYCODE.ENTER:
+ case KEYCODE.NUMPAD_ENTER:
+ case KEYCODE.SPACE:
+ return true;
+ default:
+ return false;
+ }
+};
+
+
+/**
* Handles the following keyboard actions.
* - <CTRL> + <SHIFT> + <.> starts voice input(<CMD> + <SHIFT> + <.> on mac).
* - <ESC> aborts voice input when the recognition interface is active.
@@ -596,34 +681,34 @@ speech.handleRecognitionEnd_ = function() {
* @param {KeyboardEvent} event The keydown event.
*/
speech.onKeyDown = function(event) {
- function isUserAgentMac(userAgent) {
- return userAgent.includes('Macintosh');
- }
-
- if (!speech.isRecognizing_()) {
- const ctrlKeyPressed = event.ctrlKey ||
- (isUserAgentMac(window.navigator.userAgent) && event.metaKey);
+ if (speech.isUiDefinitelyHidden_()) {
+ const ctrlKeyPressed =
+ event.ctrlKey || (speech.isUserAgentMac_() && event.metaKey);
if (speech.currentState_ == speech.State_.READY &&
- event.keyCode == KEYCODE.PERIOD && event.shiftKey && ctrlKeyPressed) {
- speech.toggleStartStop();
+ event.code == KEYCODE.PERIOD && event.shiftKey && ctrlKeyPressed) {
+ speech.logEvent(LOG_TYPE.ACTION_ACTIVATE_KEYBOARD);
+ speech.start();
}
} else {
// Ensures that keyboard events are not propagated during voice input.
event.stopPropagation();
- if (event.keyCode == KEYCODE.ESC) {
- speech.abort_();
- } else if (event.keyCode == KEYCODE.ENTER && speech.finalResult_) {
+ if (speech.isSpaceOrEnter_(event.code) && speech.finalResult_) {
speech.submitFinalResult_();
+ } else if (
+ speech.isSpaceOrEnter_(event.code) || event.code == KEYCODE.ESC) {
+ speech.logEvent(LOG_TYPE.ACTION_CLOSE_OVERLAY);
+ speech.stop();
}
}
};
/**
- * Stops the recognition interface and closes the UI if no interactions occur
- * after some time and the interface is still active. This is a safety net in
- * case the recognition.onend event doesn't fire, as is sometime the case. If
- * a high confidence transcription was received then show the search results.
+ * Displays the no match error if no interactions occur after some time while
+ * the interface is active. This is a safety net in case the onend event
+ * doesn't fire, or the user has persistent noise in the background, and does
+ * not speak. If a high confidence transcription was received, then this submits
+ * the search query instead of displaying an error.
* @private
*/
speech.onIdleTimeout_ = function() {
@@ -638,7 +723,7 @@ speech.onIdleTimeout_ = function() {
case speech.State_.SPEECH_RECEIVED:
case speech.State_.RESULT_RECEIVED:
case speech.State_.ERROR_RECEIVED:
- speech.abort_();
+ speech.onErrorReceived_(RecognitionError.NO_MATCH);
break;
}
};
@@ -655,7 +740,7 @@ speech.onVisibilityChange_ = function() {
}
if (document.webkitHidden) {
- speech.abort_();
+ speech.stop();
}
};
@@ -665,33 +750,46 @@ speech.onVisibilityChange_ = function() {
*/
speech.onOmniboxFocused = function() {
if (!speech.isUiDefinitelyHidden_()) {
- speech.abort_();
+ speech.logEvent(LOG_TYPE.ACTION_CLOSE_OVERLAY);
+ speech.stop();
}
};
/**
+ * Change the location of this tab to the new URL. Used for query submission.
+ * @param {!URL} The URL to navigate to.
+ * @private
+ */
+speech.navigateToUrl_ = function(url) {
+ window.location.href = url.href;
+};
+
+
+/**
* Submits the final spoken speech query to perform a search.
* @private
*/
speech.submitFinalResult_ = function() {
window.clearTimeout(speech.idleTimer_);
-
if (!speech.finalResult_) {
throw new Error('Submitting empty query.');
}
- // Getting |speech.finalResult_| needs to happen before stopping speech.
- const encodedQuery =
- encodeURIComponent(speech.finalResult_).replace(/%20/g, '+');
- const queryUrl = speech.googleBaseUrl_ +
- // Add the actual query.
- 'search?q=' + encodedQuery +
- // Add a parameter to indicate that this request is a voice search.
- '&gs_ivs=1';
-
- speech.stop_();
- window.location.href = queryUrl;
+ const searchParams = new URLSearchParams();
+ // Add the encoded query. Getting |speech.finalResult_| needs to happen
+ // before stopping speech.
+ searchParams.append('q', speech.finalResult_);
+ // Add a parameter to indicate that this request is a voice search.
+ searchParams.append('gs_ivs', 1);
+
+ // Build the query URL.
+ const queryUrl = new URL('/search', speech.googleBaseUrl_);
+ queryUrl.search = searchParams;
+
+ speech.logEvent(LOG_TYPE.ACTION_QUERY_SUBMITTED);
+ speech.stop();
+ speech.navigateToUrl_(queryUrl);
};
@@ -767,16 +865,26 @@ speech.resetIdleTimer_ = function(duration) {
*/
speech.resetErrorTimer_ = function(duration) {
window.clearTimeout(speech.errorTimer_);
- speech.errorTimer_ = window.setTimeout(speech.stop_, duration);
+ speech.errorTimer_ = window.setTimeout(speech.stop, duration);
+};
+
+
+/**
+ * Check to see if the speech recognition interface is running, and has
+ * received any results.
+ * @return {boolean} True, if the speech recognition interface is running,
+ * and has received any results.
+ */
+speech.hasReceivedResults = function() {
+ return speech.currentState_ == speech.State_.RESULT_RECEIVED;
};
/**
* Check to see if the speech recognition interface is running.
* @return {boolean} True, if the speech recognition interface is running.
- * @private
*/
-speech.isRecognizing_ = function() {
+speech.isRecognizing = function() {
switch (speech.currentState_) {
case speech.State_.STARTED:
case speech.State_.AUDIO_RECEIVED:
@@ -791,7 +899,7 @@ speech.isRecognizing_ = function() {
/**
* Check if the controller is in a state where the UI is definitely hidden.
* Since we show the UI for a few seconds after we receive an error from the
- * API, we need a separate definition to |speech.isRecognizing_()| to indicate
+ * API, we need a separate definition to |speech.isRecognizing()| to indicate
* when the UI is hidden. <strong>Note:</strong> that if this function
* returns false, it might not necessarily mean that the UI is visible.
* @return {boolean} True if the UI is hidden.
@@ -808,53 +916,28 @@ speech.isUiDefinitelyHidden_ = function() {
/**
- * Check if the Web Speech API is initialized and event functions are set.
- * @return {boolean} True if recognition is initialized.
- * @private
- */
-speech.isRecognitionInitialized_ = function() {
- // TODO(oskopek): Do handlers of |recognition_| get reset? Verify and test.
- return !!speech.recognition_;
-};
-
-
-/**
- * Toggles starting and stopping of speech recognition by the speech tool.
- */
-speech.toggleStartStop = function() {
- if (speech.currentState_ == speech.State_.READY) {
- speech.start_();
- } else {
- speech.abort_();
- }
-};
-
-
-/**
* Handles click events during speech recognition.
* @param {boolean} shouldSubmit True if a query should be submitted.
* @param {boolean} shouldRetry True if the interface should be restarted.
+ * @param {boolean} navigatingAway True if the browser is navigating away
+ * from the NTP.
* @private
*/
-speech.onClick_ = function(shouldSubmit, shouldRetry) {
+speech.onClick_ = function(shouldSubmit, shouldRetry, navigatingAway) {
if (speech.finalResult_ && shouldSubmit) {
speech.submitFinalResult_();
} else if (speech.currentState_ == speech.State_.STOPPED && shouldRetry) {
- speech.restart();
+ speech.reset_();
+ speech.start();
+ } else if (speech.currentState_ == speech.State_.STOPPED && navigatingAway) {
+ // If the user clicks on a "Learn more" or "Details" support page link
+ // from an error message, do nothing, and let Chrome navigate to that page.
} else {
- speech.abort_();
+ speech.logEvent(LOG_TYPE.ACTION_CLOSE_OVERLAY);
+ speech.stop();
}
};
-/**
- * Restarts voice recognition. Used for the 'Try again' error link.
- * @private
- */
-speech.restart = function() {
- speech.reset_();
- speech.toggleStartStop();
-};
-
/* TEXT VIEW */
/**
@@ -865,10 +948,24 @@ let text = {};
/**
- * ID for the link shown in error output.
+ * ID for the "Try Again" link shown in error output.
* @const
*/
-text.ERROR_LINK_ID = 'voice-text-area';
+text.RETRY_LINK_ID = 'voice-retry-link';
+
+
+/**
+ * ID for the Voice Search support site link shown in error output.
+ * @const
+ */
+text.SUPPORT_LINK_ID = 'voice-support-link';
+
+
+/**
+ * Class for the links shown in error output.
+ * @const @private
+ */
+text.ERROR_LINK_CLASS_ = 'voice-text-link';
/**
@@ -927,6 +1024,15 @@ text.LISTENING_TIMEOUT_MS_ = 2000;
/**
+ * Base link target for help regarding voice search. To be appended
+ * with a locale string for proper target site localization.
+ * @const @private
+ */
+text.SUPPORT_LINK_BASE_ =
+ 'https://support.google.com/chrome/?p=ui_voice_search&hl=';
+
+
+/**
* The final / high confidence speech recognition result element.
* @private {Element}
*/
@@ -955,15 +1061,6 @@ text.listeningTimer_;
/**
- * Base link target for help regarding voice search. To be appended
- * with a locale string for proper target site localization.
- * @const @private
- */
-text.SUPPORT_LINK_BASE_ =
- 'https://support.google.com/chrome/?p=ui_voice_search&hl=';
-
-
-/**
* Finds the text view elements.
*/
text.init = function() {
@@ -975,39 +1072,38 @@ text.init = function() {
/**
* Updates the text elements with new recognition results.
- * @param {string} interimText Low confidence speech recognition result text.
- * @param {string} opt_finalText High confidence speech recognition result text,
- * defaults to an empty string.
+ * @param {!string} interimText Low confidence speech recognition result text.
+ * @param {!string} opt_finalText High confidence speech recognition result
+ * text, defaults to an empty string.
*/
-text.updateTextArea = function(interimText, opt_finalText) {
- const finalText = opt_finalText || '';
-
+text.updateTextArea = function(interimText, opt_finalText = '') {
window.clearTimeout(text.initializingTimer_);
- text.cancelListeningTimeout();
+ text.clearListeningTimeout();
text.interim_.textContent = interimText;
- text.final_.textContent = finalText;
+ text.final_.textContent = opt_finalText;
text.interim_.className = text.final_.className = text.getTextClassName_();
};
/**
- * Sets the text view to the initializing state.
+ * Sets the text view to the initializing state. The initializing message
+ * shown while waiting for permission is not displayed immediately, but after
+ * a short timeout. The reason for this is that the "Waiting..." message would
+ * still appear ("blink") every time a user opens Voice Search, even if they
+ * have already granted and persisted microphone permission for the NTP,
+ * and could therefore directly proceed to the "Speak now" message.
*/
text.showInitializingMessage = function() {
+ text.interim_.textContent = '';
+ text.final_.textContent = '';
+
const displayMessage = function() {
- if (text.interim_.innerText == '') {
+ if (text.interim_.textContent == '') {
text.updateTextArea(speech.messages.waiting);
}
};
-
- text.interim_.textContent = '';
- text.final_.textContent = '';
-
- // We give the interface some time to get the permission. Once permission
- // is obtained, the ready message is displayed, in which case the
- // initializing message won't be shown.
text.initializingTimer_ =
window.setTimeout(displayMessage, text.INITIALIZING_TIMEOUT_MS_);
};
@@ -1018,12 +1114,14 @@ text.showInitializingMessage = function() {
*/
text.showReadyMessage = function() {
window.clearTimeout(text.initializingTimer_);
+ text.clearListeningTimeout();
text.updateTextArea(speech.messages.ready);
text.startListeningMessageAnimation_();
};
/**
+ * Display an error message in the text area for the given error.
* @param {RecognitionError} error The error that occured.
*/
text.showErrorMessage = function(error) {
@@ -1059,7 +1157,7 @@ text.getErrorMessage_ = function(error) {
case RecognitionError.LANGUAGE_NOT_SUPPORTED:
return speech.messages.languageError;
default:
- throw new Error('Illegal RecognitionError value: ' + error);
+ return speech.messages.otherError;
}
};
@@ -1071,21 +1169,24 @@ text.getErrorMessage_ = function(error) {
*/
text.getErrorLink_ = function(error) {
let linkElement = document.createElement('a');
- linkElement.id = text.ERROR_LINK_ID;
+ linkElement.className = text.ERROR_LINK_CLASS_;
switch (error) {
case RecognitionError.NO_MATCH:
+ linkElement.id = text.RETRY_LINK_ID;
linkElement.textContent = speech.messages.tryAgain;
- linkElement.onclick = speech.restart;
+ // When clicked, |view.onWindowClick_| gets called.
return linkElement;
case RecognitionError.NO_SPEECH:
case RecognitionError.AUDIO_CAPTURE:
+ linkElement.id = text.SUPPORT_LINK_ID;
linkElement.href = text.SUPPORT_LINK_BASE_ + getChromeUILanguage();
linkElement.textContent = speech.messages.learnMore;
linkElement.target = '_blank';
return linkElement;
case RecognitionError.NOT_ALLOWED:
case RecognitionError.SERVICE_NOT_ALLOWED:
+ linkElement.id = text.SUPPORT_LINK_ID;
linkElement.href = text.SUPPORT_LINK_BASE_ + getChromeUILanguage();
linkElement.textContent = speech.messages.details;
linkElement.target = '_blank';
@@ -1100,7 +1201,9 @@ text.getErrorLink_ = function(error) {
* Clears the text elements.
*/
text.clear = function() {
- text.cancelListeningTimeout();
+ text.updateTextArea('');
+
+ text.clearListeningTimeout();
window.clearTimeout(text.initializingTimer_);
text.interim_.className = text.TEXT_AREA_CLASS_;
@@ -1111,7 +1214,7 @@ text.clear = function() {
/**
* Cancels listening message display.
*/
-text.cancelListeningTimeout = function() {
+text.clearListeningTimeout = function() {
window.clearTimeout(text.listeningTimer_);
};
@@ -1152,7 +1255,8 @@ text.getTextClassName_ = function() {
*/
text.startListeningMessageAnimation_ = function() {
const animateListeningText = function() {
- if (text.interim_.innerText == speech.messages.ready) {
+ // If speech is active with no results yet, show the message and animation.
+ if (speech.isRecognizing() && !speech.hasReceivedResults()) {
text.updateTextArea(speech.messages.listening);
text.interim_.classList.add(text.LISTENING_ANIMATION_CLASS_);
}
@@ -1255,7 +1359,7 @@ microphone.init = function() {
/**
- * Starts the volume circles animations.
+ * Starts the volume circles animations, if it has not started yet.
*/
microphone.startInputAnimation = function() {
if (!microphone.isLevelAnimating_) {
@@ -1328,13 +1432,6 @@ view.BACKGROUND_ID_ = 'voice-overlay';
/**
- * ID of the close (x) button.
- * @const @private
- */
-view.CLOSE_BUTTON_ID_ = 'voice-close-button';
-
-
-/**
* ID for the speech output container.
* @const @private
*/
@@ -1411,13 +1508,13 @@ view.show = function() {
if (!view.isVisible_) {
text.showInitializingMessage();
view.showView_();
- window.addEventListener('mouseup', view.onWindowClick_, false);
+ window.addEventListener('click', view.onWindowClick_, false);
}
};
/**
* Sets the output area text to listening. This should only be called when
- * the Web Speech API is receiving audio input (i.e., onaudiostart).
+ * the Web Speech API starts receiving audio input (i.e., onaudiostart).
*/
view.setReadyForSpeech = function() {
if (view.isVisible_) {
@@ -1429,14 +1526,16 @@ view.setReadyForSpeech = function() {
/**
* Shows the pulsing animation emanating from the microphone. This should only
- * be called when the Web Speech API is receiving speech input (i.e.,
- * onspeechstart).
+ * be called when the Web Speech API starts receiving speech input (i.e.,
+ * |onspeechstart|). Do note that this may also be run when the Web Speech API
+ * is receiving speech recognition results (|onresult|), because |onspeechstart|
+ * may not have been called.
*/
view.setReceivingSpeech = function() {
if (view.isVisible_) {
view.container_.className = view.RECEIVING_SPEECH_CLASS_;
microphone.startInputAnimation();
- text.cancelListeningTimeout();
+ text.clearListeningTimeout();
}
};
@@ -1448,7 +1547,11 @@ view.setReceivingSpeech = function() {
*/
view.updateSpeechResult = function(interimResultText, finalResultText) {
if (view.isVisible_) {
- view.container_.className = view.RECEIVING_SPEECH_CLASS_;
+ // If the Web Speech API is receiving speech recognition results
+ // (|onresult|) and |onspeechstart| has not been called.
+ if (view.container_.className != view.RECEIVING_SPEECH_CLASS_) {
+ view.setReceivingSpeech();
+ }
text.updateTextArea(interimResultText, finalResultText);
}
};
@@ -1458,7 +1561,7 @@ view.updateSpeechResult = function(interimResultText, finalResultText) {
* Hides the UI and stops animations.
*/
view.hide = function() {
- window.removeEventListener('mouseup', view.onWindowClick_, false);
+ window.removeEventListener('click', view.onWindowClick_, false);
view.stopMicrophoneAnimations_();
view.hideView_();
view.isNoMatchShown_ = false;
@@ -1543,19 +1646,33 @@ view.stopMicrophoneAnimations_ = function() {
/**
* Makes sure that a click anywhere closes the UI when it is active.
- * @param {Event} event The click event.
+ * @param {!MouseEvent} event The click event.
* @private
*/
view.onWindowClick_ = function(event) {
if (!view.isVisible_) {
return;
}
- const targetId = event.target.id;
- const shouldRetry = (targetId == microphone.RED_BUTTON_ID ||
- targetId == text.ERROR_LINK_ID) &&
- view.isNoMatchShown_;
- const submitQuery =
- targetId == microphone.RED_BUTTON_ID && !view.isNoMatchShown_;
- view.onClick_(submitQuery, shouldRetry);
+ const retryLinkClicked = event.target.id === text.RETRY_LINK_ID;
+ const supportLinkClicked = event.target.id === text.SUPPORT_LINK_ID;
+ const micIconClicked = event.target.id === microphone.RED_BUTTON_ID;
+
+ const submitQuery = micIconClicked && !view.isNoMatchShown_;
+ const shouldRetry =
+ retryLinkClicked || (micIconClicked && view.isNoMatchShown_);
+ const navigatingAway = supportLinkClicked;
+
+ if (shouldRetry) {
+ if (micIconClicked) {
+ speech.logEvent(LOG_TYPE.ACTION_TRY_AGAIN_MIC_BUTTON);
+ } else if (retryLinkClicked) {
+ speech.logEvent(LOG_TYPE.ACTION_TRY_AGAIN_LINK);
+ }
+ }
+ if (supportLinkClicked) {
+ speech.logEvent(LOG_TYPE.ACTION_SUPPORT_LINK_CLICKED);
+ }
+
+ view.onClick_(submitQuery, shouldRetry, navigatingAway);
};
/* END VIEW */
diff --git a/chromium/chrome/browser/resources/local_omnibox_popup/OWNERS b/chromium/chrome/browser/resources/local_omnibox_popup/OWNERS
deleted file mode 100644
index 2037852e71e..00000000000
--- a/chromium/chrome/browser/resources/local_omnibox_popup/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-samarth@chromium.org
diff --git a/chromium/chrome/browser/resources/md_bookmarks/.eslintrc.js b/chromium/chrome/browser/resources/md_bookmarks/.eslintrc.js
new file mode 100644
index 00000000000..847d6e99509
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/.eslintrc.js
@@ -0,0 +1,13 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {
+ 'no-var': 'error',
+ },
+};
diff --git a/chromium/chrome/browser/resources/md_bookmarks/BUILD.gn b/chromium/chrome/browser/resources/md_bookmarks/BUILD.gn
index 16e74988bb3..d1d84aac51f 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/BUILD.gn
+++ b/chromium/chrome/browser/resources/md_bookmarks/BUILD.gn
@@ -1,6 +1,6 @@
-import("../vulcanize.gni")
+import("../optimize_webui.gni")
-vulcanize("build") {
+optimize_webui("build") {
host = "bookmarks"
html_in_files = [ "bookmarks.html" ]
html_out_files = [ "vulcanized.html" ]
diff --git a/chromium/chrome/browser/resources/md_bookmarks/actions.js b/chromium/chrome/browser/resources/md_bookmarks/actions.js
index 8749fdbf598..9eed3f0e0cf 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/actions.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/actions.js
@@ -74,7 +74,7 @@ cr.define('bookmarks.actions', function() {
* @return {!Action}
*/
function removeBookmark(id, parentId, index, nodes) {
- var descendants = bookmarks.util.getDescendants(nodes, id);
+ const descendants = bookmarks.util.getDescendants(nodes, id);
return {
name: 'remove-bookmark',
id: id,
@@ -156,15 +156,15 @@ cr.define('bookmarks.actions', function() {
assert(!config.toggle || !config.range);
assert(!config.toggle || !config.clear);
- var anchor = state.selection.anchor;
- var toSelect = [];
- var newAnchor = id;
+ const anchor = state.selection.anchor;
+ const toSelect = [];
+ let newAnchor = id;
if (config.range && anchor) {
- var displayedList = bookmarks.util.getDisplayedList(state);
- var selectedIndex = displayedList.indexOf(id);
+ const displayedList = bookmarks.util.getDisplayedList(state);
+ const selectedIndex = displayedList.indexOf(id);
assert(selectedIndex != -1);
- var anchorIndex = displayedList.indexOf(anchor);
+ let anchorIndex = displayedList.indexOf(anchor);
if (anchorIndex == -1)
anchorIndex = selectedIndex;
@@ -172,10 +172,10 @@ cr.define('bookmarks.actions', function() {
// was used in this selection.
newAnchor = displayedList[anchorIndex];
- var startIndex = Math.min(anchorIndex, selectedIndex);
- var endIndex = Math.max(anchorIndex, selectedIndex);
+ const startIndex = Math.min(anchorIndex, selectedIndex);
+ const endIndex = Math.max(anchorIndex, selectedIndex);
- for (var i = startIndex; i <= endIndex; i++)
+ for (let i = startIndex; i <= endIndex; i++)
toSelect.push(displayedList[i]);
} else {
toSelect.push(id);
diff --git a/chromium/chrome/browser/resources/md_bookmarks/api_listener.html b/chromium/chrome/browser/resources/md_bookmarks/api_listener.html
index 3fc0a5979ce..0ee48ff8f38 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/api_listener.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/api_listener.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://bookmarks/actions.html">
+<link rel="import" href="chrome://bookmarks/debouncer.html">
<link rel="import" href="chrome://bookmarks/store.html">
<link rel="import" href="chrome://bookmarks/util.html">
<script src="chrome://bookmarks/api_listener.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/api_listener.js b/chromium/chrome/browser/resources/md_bookmarks/api_listener.js
index 534e8902aec..a519a86d7d6 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/api_listener.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/api_listener.js
@@ -10,11 +10,11 @@
cr.define('bookmarks.ApiListener', function() {
/** @type {boolean} */
- var trackUpdates = false;
+ let trackUpdates = false;
/** @type {!Array<string>} */
- var updatedItems = [];
+ let updatedItems = [];
- var debouncer;
+ let debouncer;
/**
* Batches UI updates so that no changes will be made to UI until the next
@@ -22,13 +22,17 @@ cr.define('bookmarks.ApiListener', function() {
* can be called in a tight loop by UI actions.
*/
function batchUIUpdates() {
- if (!debouncer || debouncer.done()) {
- bookmarks.Store.getInstance().beginBatchUpdate();
+ if (!debouncer) {
debouncer = new bookmarks.Debouncer(
() => bookmarks.Store.getInstance().endBatchUpdate());
}
- debouncer.resetTimeout();
+ if (debouncer.done()) {
+ bookmarks.Store.getInstance().beginBatchUpdate();
+ debouncer.reset();
+ }
+
+ debouncer.restartTimeout();
}
/**
@@ -91,7 +95,7 @@ cr.define('bookmarks.ApiListener', function() {
*/
function onBookmarkRemoved(id, removeInfo) {
batchUIUpdates();
- var nodes = bookmarks.Store.getInstance().data.nodes;
+ const nodes = bookmarks.Store.getInstance().data.nodes;
dispatch(bookmarks.actions.removeBookmark(
id, removeInfo.parentId, removeInfo.index, nodes));
}
@@ -152,7 +156,7 @@ cr.define('bookmarks.ApiListener', function() {
dispatch(bookmarks.actions.setCanEditBookmarks(canEdit));
}
- var listeners = [
+ const listeners = [
{api: chrome.bookmarks.onChanged, fn: onBookmarkChanged},
{api: chrome.bookmarks.onChildrenReordered, fn: onChildrenReordered},
{api: chrome.bookmarks.onCreated, fn: onBookmarkCreated},
diff --git a/chromium/chrome/browser/resources/md_bookmarks/app.html b/chromium/chrome/browser/resources/md_bookmarks/app.html
index b047f366b8d..68474352701 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/app.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/app.html
@@ -71,8 +71,8 @@
<bookmarks-toolbar sidebar-width="[[sidebarWidth_]]" role="banner">
</bookmarks-toolbar>
<div id="main-container">
- <div id="sidebar" role="navigation">
- <bookmarks-folder-node item-id="0" depth="-1"></bookmarks-folder-node>
+ <div id="sidebar" role="navigation" aria-label="$i18n{sidebarAxLabel}">
+ <bookmarks-folder-node item-id="0" depth="-1"></bookmarks-folder-node>
</div>
<div id="splitter"></div>
<bookmarks-list></bookmarks-list>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/app.js b/chromium/chrome/browser/resources/md_bookmarks/app.js
index 2622bd0d46e..c95d317ad52 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/app.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/app.js
@@ -44,11 +44,11 @@ Polymer({
});
chrome.bookmarks.getTree((results) => {
- var nodeMap = bookmarks.util.normalizeNodes(results[0]);
- var initialState = bookmarks.util.createEmptyState();
+ const nodeMap = bookmarks.util.normalizeNodes(results[0]);
+ const initialState = bookmarks.util.createEmptyState();
initialState.nodes = nodeMap;
initialState.selectedFolder = nodeMap[ROOT_NODE_ID].children[0];
- var folderStateString =
+ const folderStateString =
window.localStorage[LOCAL_STORAGE_FOLDER_STATE_KEY];
initialState.folderOpenState = folderStateString ?
new Map(
@@ -86,9 +86,9 @@ Polymer({
* @private
*/
initializeSplitter_: function() {
- var splitter = this.$.splitter;
+ const splitter = this.$.splitter;
cr.ui.Splitter.decorate(splitter);
- var splitterTarget = this.$.sidebar;
+ const splitterTarget = this.$.sidebar;
// The splitter persists the size of the left component in the local store.
if (LOCAL_STORAGE_TREE_WIDTH_KEY in window.localStorage) {
@@ -120,7 +120,7 @@ Polymer({
return;
chrome.bookmarks.search(this.searchTerm_, (results) => {
- var ids = results.map(function(node) {
+ const ids = results.map(function(node) {
return node.id;
});
this.dispatch(bookmarks.actions.setSearchResults(ids));
diff --git a/chromium/chrome/browser/resources/md_bookmarks/command_manager.js b/chromium/chrome/browser/resources/md_bookmarks/command_manager.js
index 486b09231eb..07a7a18051b 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/command_manager.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/command_manager.js
@@ -8,7 +8,7 @@
*/
cr.define('bookmarks', function() {
- var CommandManager = Polymer({
+ const CommandManager = Polymer({
is: 'bookmarks-command-manager',
behaviors: [
@@ -124,7 +124,7 @@ cr.define('bookmarks', function() {
this.menuSource_ = source;
this.menuIds_ = items || this.getState().selection.items;
- var dropdown =
+ const dropdown =
/** @type {!CrActionMenuElement} */ (this.$.dropdown.get());
// Ensure that the menu is fully rendered before trying to position it.
Polymer.dom.flush();
@@ -144,7 +144,7 @@ cr.define('bookmarks', function() {
this.menuSource_ = source;
this.menuIds_ = this.getState().selection.items;
- var dropdown =
+ const dropdown =
/** @type {!CrActionMenuElement} */ (this.$.dropdown.get());
// Ensure that the menu is fully rendered before trying to position it.
Polymer.dom.flush();
@@ -172,7 +172,7 @@ cr.define('bookmarks', function() {
* @return {boolean}
*/
canExecute: function(command, itemIds) {
- var state = this.getState();
+ const state = this.getState();
switch (command) {
case Command.OPEN:
return itemIds.size > 0;
@@ -237,7 +237,7 @@ cr.define('bookmarks', function() {
switch (command) {
case Command.EDIT:
case Command.DELETE:
- var state = this.getState();
+ const state = this.getState();
return !this.containsMatchingNode_(itemIds, function(node) {
return !bookmarks.util.canEditNode(state, node.id);
});
@@ -258,18 +258,19 @@ cr.define('bookmarks', function() {
* @param {!Set<string>} itemIds
*/
handle: function(command, itemIds) {
- var state = this.getState();
+ const state = this.getState();
switch (command) {
- case Command.EDIT:
- var id = Array.from(itemIds)[0];
+ case Command.EDIT: {
+ let id = Array.from(itemIds)[0];
/** @type {!BookmarksEditDialogElement} */ (this.$.editDialog.get())
.showEditDialog(state.nodes[id]);
break;
+ }
case Command.COPY_URL:
- case Command.COPY:
- var idList = Array.from(itemIds);
+ case Command.COPY: {
+ let idList = Array.from(itemIds);
chrome.bookmarkManagerPrivate.copy(idList, () => {
- var labelPromise;
+ let labelPromise;
if (command == Command.COPY_URL) {
labelPromise =
Promise.resolve(loadTimeData.getString('toastUrlCopied'));
@@ -285,17 +286,19 @@ cr.define('bookmarks', function() {
labelPromise, state.nodes[idList[0]].title, false);
});
break;
- case Command.SHOW_IN_FOLDER:
- var id = Array.from(itemIds)[0];
+ }
+ case Command.SHOW_IN_FOLDER: {
+ let id = Array.from(itemIds)[0];
this.dispatch(bookmarks.actions.selectFolder(
assert(state.nodes[id].parentId), state.nodes));
bookmarks.DialogFocusManager.getInstance().clearFocus();
this.fire('highlight-items', [id]);
break;
- case Command.DELETE:
- var idList = Array.from(this.minimizeDeletionSet_(itemIds));
- var title = state.nodes[idList[0]].title;
- var labelPromise;
+ }
+ case Command.DELETE: {
+ let idList = Array.from(this.minimizeDeletionSet_(itemIds));
+ const title = state.nodes[idList[0]].title;
+ let labelPromise;
if (idList.length == 1) {
labelPromise =
@@ -309,6 +312,7 @@ cr.define('bookmarks', function() {
this.showTitleToast_(labelPromise, title, true);
});
break;
+ }
case Command.UNDO:
chrome.bookmarkManagerPrivate.undo();
bookmarks.ToastManager.getInstance().hide();
@@ -322,12 +326,12 @@ cr.define('bookmarks', function() {
this.openUrls_(this.expandUrls_(itemIds), command);
break;
case Command.OPEN:
- var isFolder = itemIds.size == 1 &&
+ const isFolder = itemIds.size == 1 &&
this.containsMatchingNode_(itemIds, function(node) {
return !node.url;
});
if (isFolder) {
- var folderId = Array.from(itemIds)[0];
+ const folderId = Array.from(itemIds)[0];
this.dispatch(
bookmarks.actions.selectFolder(folderId, state.nodes));
} else {
@@ -335,7 +339,7 @@ cr.define('bookmarks', function() {
}
break;
case Command.SELECT_ALL:
- var displayedIds = bookmarks.util.getDisplayedList(state);
+ const displayedIds = bookmarks.util.getDisplayedList(state);
this.dispatch(bookmarks.actions.selectAll(displayedIds, state));
break;
case Command.DESELECT_ALL:
@@ -345,8 +349,8 @@ cr.define('bookmarks', function() {
chrome.bookmarkManagerPrivate.cut(Array.from(itemIds));
break;
case Command.PASTE:
- var selectedFolder = state.selectedFolder;
- var selectedItems = state.selection.items;
+ const selectedFolder = state.selectedFolder;
+ const selectedItems = state.selection.items;
bookmarks.ApiListener.trackUpdatedItems();
chrome.bookmarkManagerPrivate.paste(
selectedFolder, Array.from(selectedItems),
@@ -367,9 +371,9 @@ cr.define('bookmarks', function() {
* shortcut.
*/
handleKeyEvent: function(e, itemIds) {
- for (var commandTuple of this.shortcuts_) {
- var command = /** @type {Command} */ (commandTuple[0]);
- var shortcut =
+ for (const commandTuple of this.shortcuts_) {
+ const command = /** @type {Command} */ (commandTuple[0]);
+ const shortcut =
/** @type {cr.ui.KeyboardShortcutList} */ (commandTuple[1]);
if (shortcut.matchesEvent(e) && this.canExecute(command, itemIds)) {
this.handle(command, itemIds);
@@ -398,7 +402,7 @@ cr.define('bookmarks', function() {
* Mac.
*/
addShortcut_: function(command, shortcut, macShortcut) {
- var shortcut = (cr.isMac && macShortcut) ? macShortcut : shortcut;
+ shortcut = (cr.isMac && macShortcut) ? macShortcut : shortcut;
this.shortcuts_.set(command, new cr.ui.KeyboardShortcutList(shortcut));
},
@@ -412,10 +416,10 @@ cr.define('bookmarks', function() {
* @return {!Set<string>}
*/
minimizeDeletionSet_: function(itemIds) {
- var minimizedSet = new Set();
- var nodes = this.getState().nodes;
+ const minimizedSet = new Set();
+ const nodes = this.getState().nodes;
itemIds.forEach(function(itemId) {
- var currentId = itemId;
+ let currentId = itemId;
while (currentId != ROOT_NODE_ID) {
currentId = assert(nodes[currentId].parentId);
if (itemIds.has(currentId))
@@ -442,8 +446,8 @@ cr.define('bookmarks', function() {
if (urls.length == 0)
return;
- var openUrlsCallback = function() {
- var incognito = command == Command.OPEN_INCOGNITO;
+ const openUrlsCallback = function() {
+ const incognito = command == Command.OPEN_INCOGNITO;
if (command == Command.OPEN_NEW_WINDOW || incognito) {
chrome.windows.create({url: urls, incognito: incognito});
} else {
@@ -461,7 +465,7 @@ cr.define('bookmarks', function() {
}
this.confirmOpenCallback_ = openUrlsCallback;
- var dialog = this.$.openDialog.get();
+ const dialog = this.$.openDialog.get();
dialog.querySelector('[slot=body]').textContent =
loadTimeData.getStringF('openDialogBody', urls.length);
@@ -479,16 +483,16 @@ cr.define('bookmarks', function() {
* @private
*/
expandUrls_: function(itemIds) {
- var urls = [];
- var nodes = this.getState().nodes;
+ const urls = [];
+ const nodes = this.getState().nodes;
itemIds.forEach(function(id) {
- var node = nodes[id];
+ const node = nodes[id];
if (node.url) {
urls.push(node.url);
} else {
node.children.forEach(function(childId) {
- var childNode = nodes[childId];
+ const childNode = nodes[childId];
if (childNode.url)
urls.push(childNode.url);
});
@@ -505,7 +509,7 @@ cr.define('bookmarks', function() {
* |predicate|.
*/
containsMatchingNode_: function(itemIds, predicate) {
- var nodes = this.getState().nodes;
+ const nodes = this.getState().nodes;
return Array.from(itemIds).some(function(id) {
return predicate(nodes[id]);
@@ -530,18 +534,18 @@ cr.define('bookmarks', function() {
* @private
*/
getCommandLabel_: function(command) {
- var multipleNodes = this.menuIds_.size > 1 ||
+ const multipleNodes = this.menuIds_.size > 1 ||
this.containsMatchingNode_(this.menuIds_, function(node) {
return !node.url;
});
- var label;
+ let label;
switch (command) {
case Command.EDIT:
if (this.menuIds_.size != 1)
return '';
- var id = Array.from(this.menuIds_)[0];
- var itemUrl = this.getState().nodes[id].url;
+ const id = Array.from(this.menuIds_)[0];
+ const itemUrl = this.getState().nodes[id].url;
label = itemUrl ? 'menuEdit' : 'menuRename';
break;
case Command.COPY_URL:
@@ -573,13 +577,13 @@ cr.define('bookmarks', function() {
* @private
*/
getCommandSublabel_: function(command) {
- var multipleNodes = this.menuIds_.size > 1 ||
+ const multipleNodes = this.menuIds_.size > 1 ||
this.containsMatchingNode_(this.menuIds_, function(node) {
return !node.url;
});
switch (command) {
case Command.OPEN_NEW_TAB:
- var urls = this.expandUrls_(this.menuIds_);
+ const urls = this.expandUrls_(this.menuIds_);
return multipleNodes && urls.length > 0 ? String(urls.length) : '';
default:
return '';
@@ -616,12 +620,12 @@ cr.define('bookmarks', function() {
*/
showTitleToast_: function(labelPromise, title, canUndo) {
labelPromise.then(function(label) {
- var pieces = loadTimeData.getSubstitutedStringPieces(label, title)
- .map(function(p) {
- // Make the bookmark name collapsible.
- p.collapsible = !!p.arg;
- return p;
- });
+ const pieces = loadTimeData.getSubstitutedStringPieces(label, title)
+ .map(function(p) {
+ // Make the bookmark name collapsible.
+ p.collapsible = !!p.arg;
+ return p;
+ });
bookmarks.ToastManager.getInstance().showForStringPieces(
pieces, canUndo);
@@ -660,7 +664,7 @@ cr.define('bookmarks', function() {
* @private
*/
onKeydown_: function(e) {
- var selection = this.getState().selection.items;
+ const selection = this.getState().selection.items;
if (e.target == document.body &&
!bookmarks.DialogFocusManager.getInstance().hasOpenDialog()) {
this.handleKeyEvent(e, selection);
diff --git a/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
index 0ce298c44a6..bc674665a23 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
@@ -19,8 +19,8 @@
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(EXTERNS_GYP):chrome_extensions',
'actions',
+ 'debouncer',
'store',
- 'timer_proxy',
'util',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
@@ -63,6 +63,13 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
},
{
+ 'target_name': 'debouncer',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'dialog_focus_manager',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
@@ -85,10 +92,10 @@
'<(EXTERNS_GYP):bookmark_manager_private',
'<(EXTERNS_GYP):metrics_private',
'api_listener',
+ 'debouncer',
'dnd_chip',
'folder_node',
'store',
- 'timer_proxy',
'types',
'util',
],
@@ -112,6 +119,7 @@
'target_name': 'folder_node',
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(EXTERNS_GYP):chrome_extensions',
'actions',
'command_manager',
@@ -185,20 +193,10 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi']
},
{
- 'target_name': 'timer_proxy',
- 'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
'target_name': 'toast_manager',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp:iron-a11y-announcer-extracted',
- '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted',
- 'timer_proxy',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/md_bookmarks/constants.js b/chromium/chrome/browser/resources/md_bookmarks/constants.js
index 85a83d391b8..bbda71cb0fd 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/constants.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/constants.js
@@ -8,7 +8,7 @@
* @enum {number}
* @const
*/
-var DropPosition = {
+const DropPosition = {
NONE: 0,
ABOVE: 1,
ON: 2,
@@ -22,7 +22,7 @@ var DropPosition = {
* @enum {number}
* @const
*/
-var Command = {
+const Command = {
EDIT: 0,
COPY_URL: 1,
SHOW_IN_FOLDER: 2,
@@ -47,7 +47,7 @@ var Command = {
* @enum {number}
* @const
*/
-var MenuSource = {
+const MenuSource = {
NONE: 0,
LIST: 1,
TREE: 2,
@@ -58,30 +58,30 @@ var MenuSource = {
* @enum {number}
* @const
*/
-var IncognitoAvailability = {
+const IncognitoAvailability = {
ENABLED: 0,
DISABLED: 1,
FORCED: 2,
};
/** @const */
-var LOCAL_STORAGE_FOLDER_STATE_KEY = 'folderOpenState';
+const LOCAL_STORAGE_FOLDER_STATE_KEY = 'folderOpenState';
/** @const */
-var LOCAL_STORAGE_TREE_WIDTH_KEY = 'treeWidth';
+const LOCAL_STORAGE_TREE_WIDTH_KEY = 'treeWidth';
/** @const */
-var ROOT_NODE_ID = '0';
+const ROOT_NODE_ID = '0';
/** @const */
-var BOOKMARKS_BAR_ID = '1';
+const BOOKMARKS_BAR_ID = '1';
/** @const {number} */
-var OPEN_CONFIRMATION_LIMIT = 15;
+const OPEN_CONFIRMATION_LIMIT = 15;
/**
* Folders that are beneath this depth will be closed by default in the folder
* tree (where the Bookmarks Bar folder is at depth 0).
* @const {number}
*/
-var FOLDER_OPEN_BY_DEFAULT_DEPTH = 1;
+const FOLDER_OPEN_BY_DEFAULT_DEPTH = 1;
diff --git a/chromium/chrome/browser/resources/md_bookmarks/timer_proxy.html b/chromium/chrome/browser/resources/md_bookmarks/debouncer.html
index d70600af6a1..567579dff15 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/timer_proxy.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/debouncer.html
@@ -1,2 +1,2 @@
<link rel="import" href="chrome://resources/html/cr.html">
-<script src="chrome://bookmarks/timer_proxy.js"></script>
+<script src="chrome://bookmarks/debouncer.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/debouncer.js b/chromium/chrome/browser/resources/md_bookmarks/debouncer.js
new file mode 100644
index 00000000000..3bc7464a933
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_bookmarks/debouncer.js
@@ -0,0 +1,86 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A debouncer which fires the given callback after a delay. The
+ * delay can be refreshed by calling restartTimeout. Resetting the timeout with
+ * no delay moves the callback to the end of the task queue.
+ */
+
+cr.define('bookmarks', function() {
+ class Debouncer {
+ /** @param {!function()} callback */
+ constructor(callback) {
+ /** @private {!function()} */
+ this.callback_ = callback;
+ /** @private {!Object} */
+ this.timerProxy_ = window;
+ /** @private {?number} */
+ this.timer_ = null;
+ /** @private {!function()} */
+ this.boundTimerCallback_ = this.timerCallback_.bind(this);
+ /** @private {boolean} */
+ this.isDone_ = false;
+ /** @private {!PromiseResolver} */
+ this.promiseResolver_ = new PromiseResolver();
+ }
+
+ /**
+ * Starts the timer for the callback, cancelling the old timer if there is
+ * one.
+ * @param {number=} delay
+ */
+ restartTimeout(delay) {
+ assert(!this.isDone_);
+
+ this.cancelTimeout_();
+ this.timer_ =
+ this.timerProxy_.setTimeout(this.boundTimerCallback_, delay || 0);
+ }
+
+ /**
+ * @return {boolean} True if the Debouncer has finished processing.
+ */
+ done() {
+ return this.isDone_;
+ }
+
+ /**
+ * @return {!Promise} Promise which resolves immediately after the callback.
+ */
+ get promise() {
+ return this.promiseResolver_.promise;
+ }
+
+ /**
+ * Resets the debouncer as if it had been newly instantiated.
+ */
+ reset() {
+ this.isDone_ = false;
+ this.promiseResolver_ = new PromiseResolver();
+ this.cancelTimeout_();
+ }
+
+ /**
+ * Cancel the timer callback, which can be restarted by calling
+ * restartTimeout().
+ * @private
+ */
+ cancelTimeout_() {
+ if (this.timer_)
+ this.timerProxy_.clearTimeout(this.timer_);
+ }
+
+ /** @private */
+ timerCallback_() {
+ this.isDone_ = true;
+ this.callback_.call();
+ this.promiseResolver_.resolve();
+ }
+ }
+
+ return {
+ Debouncer: Debouncer,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js b/chromium/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
index 68e73b2bda4..79c98298f15 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
@@ -69,7 +69,7 @@ cr.define('bookmarks', function() {
* @private
*/
getFocusedElement_: function() {
- var focus = document.activeElement;
+ let focus = document.activeElement;
while (focus.root && focus.root.activeElement)
focus = focus.root.activeElement;
@@ -82,7 +82,7 @@ cr.define('bookmarks', function() {
* @private
*/
getCloseListener_: function(dialog) {
- var closeListener = (e) => {
+ const closeListener = (e) => {
// If the dialog is open, then it got reshown immediately and we
// shouldn't clear it until it is closed again.
if (dialog.open)
diff --git a/chromium/chrome/browser/resources/md_bookmarks/dnd_chip.js b/chromium/chrome/browser/resources/md_bookmarks/dnd_chip.js
index a4108e320d4..22e3b63f9a3 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/dnd_chip.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/dnd_chip.js
@@ -29,7 +29,7 @@ Polymer({
if (this.showing_)
return;
- var isFolder = !dragItem.url;
+ const isFolder = !dragItem.url;
this.isMultiItem_ = items.length > 1;
this.$.icon.className = isFolder ? 'folder-icon' : 'website-icon';
diff --git a/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html
index dc6db92bf87..0a8b34b82f3 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.html
@@ -1,4 +1,4 @@
<link rel="import" href="chrome://bookmarks/constants.html">
+<link rel="import" href="chrome://bookmarks/debouncer.html">
<link rel="import" href="chrome://bookmarks/dnd_chip.html">
-<link rel="import" href="chrome://bookmarks/timer_proxy.html">
<script src="chrome://bookmarks/dnd_manager.js"></script>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js
index 98a4d5ab445..f4da5779d79 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/dnd_manager.js
@@ -4,11 +4,11 @@
/** @typedef {?{elements: !Array<BookmarkNode>, sameProfile: boolean}} */
-var NormalizedDragData;
+let NormalizedDragData;
cr.define('bookmarks', function() {
/** @const {number} */
- var DRAG_THRESHOLD = 15;
+ const DRAG_THRESHOLD = 15;
/**
* @param {BookmarkElement} element
@@ -51,7 +51,7 @@ cr.define('bookmarks', function() {
if (!path)
return null;
- for (var i = 0; i < path.length; i++) {
+ for (let i = 0; i < path.length; i++) {
if (isBookmarkItem(path[i]) || isBookmarkFolderNode(path[i]) ||
isBookmarkList(path[i])) {
return path[i];
@@ -65,8 +65,8 @@ cr.define('bookmarks', function() {
* @return {BookmarkElement}
*/
function getDragElement(path) {
- var dragElement = getBookmarkElement(path);
- for (var i = 0; i < path.length; i++) {
+ const dragElement = getBookmarkElement(path);
+ for (let i = 0; i < path.length; i++) {
if (path[i].tagName == 'BUTTON')
return null;
}
@@ -144,8 +144,8 @@ cr.define('bookmarks', function() {
if (!this.isSameProfile())
return false;
- var parentId = nodes[itemId].parentId;
- var parents = {};
+ let parentId = nodes[itemId].parentId;
+ const parents = {};
while (parentId) {
parents[parentId] = true;
parentId = nodes[parentId].parentId;
@@ -166,14 +166,16 @@ cr.define('bookmarks', function() {
/** @const {number} */
this.EXPAND_FOLDER_DELAY = 400;
- /** @private {number} */
- this.lastTimestamp_ = 0;
-
- /** @private {BookmarkElement|null} */
+ /** @private {?BookmarkElement} */
this.lastElement_ = null;
- /** @private {number} */
- this.testTimestamp_ = 0;
+ /** @type {!bookmarks.Debouncer} */
+ this.debouncer_ = new bookmarks.Debouncer(() => {
+ const store = bookmarks.Store.getInstance();
+ store.dispatch(
+ bookmarks.actions.changeFolderOpen(this.lastElement_.itemId, true));
+ this.reset();
+ });
}
AutoExpander.prototype = {
@@ -182,36 +184,85 @@ cr.define('bookmarks', function() {
* @param {?BookmarkElement} overElement
*/
update: function(e, overElement) {
- var eventTimestamp = this.testTimestamp_ || e.timeStamp;
- var itemId = overElement ? overElement.itemId : null;
- var store = bookmarks.Store.getInstance();
+ const itemId = overElement ? overElement.itemId : null;
+ const store = bookmarks.Store.getInstance();
- // If hovering over the same folder as last update, open the folder after
- // the delay has passed.
- if (overElement && overElement == this.lastElement_) {
- if (eventTimestamp - this.lastTimestamp_ < this.EXPAND_FOLDER_DELAY)
- return;
-
- var action = bookmarks.actions.changeFolderOpen(itemId, true);
- store.dispatch(action);
- } else if (
- overElement && isClosedBookmarkFolderNode(overElement) &&
+ // If dragging over a new closed folder node with children reset the
+ // expander. Falls through to reset the expander delay.
+ if (overElement && overElement != this.lastElement_ &&
+ isClosedBookmarkFolderNode(overElement) &&
bookmarks.util.hasChildFolders(itemId, store.data.nodes)) {
- // Since this is a closed folder node that has children, set the auto
- // expander to this element.
- this.lastTimestamp_ = eventTimestamp;
+ this.reset();
this.lastElement_ = overElement;
+ }
+
+ // If dragging over the same node, reset the expander delay.
+ if (overElement && overElement == this.lastElement_) {
+ this.debouncer_.restartTimeout(this.EXPAND_FOLDER_DELAY);
return;
}
- // If the folder has been expanded or we have moved to a different
- // element, reset the auto expander.
- this.lastTimestamp_ = 0;
+ // Otherwise, cancel the expander.
+ this.reset();
+ },
+
+ reset: function() {
+ this.debouncer_.reset();
this.lastElement_ = null;
},
};
/**
+ * Manages auto scrolling of elements on hover during internal drags. Native
+ * drags do this by themselves.
+ * @constructor
+ */
+ function AutoScroller() {
+ /** @const {number} */
+ this.SCROLL_ZONE_LENGTH = 20;
+ /** @const {number} */
+ this.SCROLL_DISTANCE = 10;
+ /** @const {number} */
+ this.SCROLL_INTERVAL = 100;
+ /** @private {?number} */
+ this.intervalId_ = null;
+ }
+
+ AutoScroller.prototype = {
+ /** @param {!Event} e */
+ update: function(e) {
+ this.reset();
+
+ const scrollParent = e.path.find((el) => {
+ return el.nodeType == Node.ELEMENT_NODE &&
+ window.getComputedStyle(el).overflowY == 'auto';
+ });
+
+ if (!scrollParent)
+ return;
+
+ const rect = scrollParent.getBoundingClientRect();
+ let yDelta = 0;
+ if (e.clientY < rect.top + this.SCROLL_ZONE_LENGTH)
+ yDelta = -this.SCROLL_DISTANCE;
+ else if (e.clientY > rect.bottom - this.SCROLL_ZONE_LENGTH)
+ yDelta = this.SCROLL_DISTANCE;
+
+ this.intervalId_ = window.setInterval(() => {
+ scrollParent.scrollTop += yDelta;
+ }, this.SCROLL_INTERVAL);
+ },
+
+ reset: function() {
+ if (this.intervalId_ == null)
+ return;
+
+ window.clearInterval(this.intervalId_);
+ this.intervalId_ = null;
+ },
+ };
+
+ /**
* Encapsulates the behavior of the drag and drop indicator which puts a line
* between items or highlights folders which are valid drop targets.
* @constructor
@@ -237,9 +288,9 @@ cr.define('bookmarks', function() {
/**
* Used to instantly remove the indicator style in tests.
- * @private {bookmarks.TimerProxy}
+ * @private {!Object}
*/
- this.timerProxy = new bookmarks.TimerProxy();
+ this.timerProxy = window;
}
DropIndicator.prototype = {
@@ -250,7 +301,7 @@ cr.define('bookmarks', function() {
* @param {DropPosition} position
*/
addDropIndicatorStyle: function(indicatorElement, position) {
- var indicatorStyleName = position == DropPosition.ABOVE ?
+ const indicatorStyleName = position == DropPosition.ABOVE ?
'drag-above' :
position == DropPosition.BELOW ? 'drag-below' : 'drag-on';
@@ -280,8 +331,8 @@ cr.define('bookmarks', function() {
update: function(dropDest) {
this.timerProxy.clearTimeout(this.removeDropIndicatorTimeoutId_);
- var indicatorElement = dropDest.element.getDropTarget();
- var position = dropDest.position;
+ const indicatorElement = dropDest.element.getDropTarget();
+ const position = dropDest.position;
this.removeDropIndicatorStyle();
this.addDropIndicatorStyle(indicatorElement, position);
@@ -334,11 +385,17 @@ cr.define('bookmarks', function() {
/** @private {Object<string, function(!Event)>} */
this.documentListeners_ = null;
+ /** @private {?bookmarks.AutoScroller} */
+ this.autoScroller_ = null;
+
+ /** @private {?bookmarks.AutoExpander} */
+ this.autoExpander_ = null;
+
/**
* Used to instantly clearDragData in tests.
- * @private {bookmarks.TimerProxy}
+ * @private {!Object}
*/
- this.timerProxy_ = new bookmarks.TimerProxy();
+ this.timerProxy_ = window;
/**
* The bookmark drag and drop indicator chip.
@@ -365,6 +422,7 @@ cr.define('bookmarks', function() {
this.dragInfo_ = new DragInfo();
this.dropIndicator_ = new DropIndicator();
this.autoExpander_ = new AutoExpander();
+ this.autoScroller_ = new AutoScroller();
this.documentListeners_ = {
'mousedown': this.onMousedown_.bind(this),
@@ -380,7 +438,7 @@ cr.define('bookmarks', function() {
'dragend': this.clearDragData_.bind(this),
// TODO(calamity): Add touch support.
};
- for (var event in this.documentListeners_)
+ for (const event in this.documentListeners_)
document.addEventListener(event, this.documentListeners_[event]);
chrome.bookmarkManagerPrivate.onDragEnter.addListener(
@@ -395,7 +453,7 @@ cr.define('bookmarks', function() {
if (this.chip_ && this.chip_.parentElement)
document.body.removeChild(this.chip_);
- for (var event in this.documentListeners_)
+ for (const event in this.documentListeners_)
document.removeEventListener(event, this.documentListeners_[event]);
},
@@ -407,7 +465,7 @@ cr.define('bookmarks', function() {
* @param {Event} e
*/
onMousedown_: function(e) {
- var dragElement = getDragElement(e.path);
+ const dragElement = getDragElement(e.path);
if (e.button != 0 || !dragElement)
return;
@@ -437,6 +495,8 @@ cr.define('bookmarks', function() {
// Prevents a native drag from starting.
e.preventDefault();
+ this.autoScroller_.update(e);
+
// On the first mousemove after a mousedown, calculate the items to drag.
// This can't be done in mousedown because the user may be shift-clicking
// an item.
@@ -447,7 +507,7 @@ cr.define('bookmarks', function() {
return;
}
- var dragData = this.calculateDragData_();
+ const dragData = this.calculateDragData_();
if (!dragData) {
this.clearDragData_();
return;
@@ -456,8 +516,8 @@ cr.define('bookmarks', function() {
this.dragInfo_.dragData = dragData;
}
- var state = bookmarks.Store.getInstance().data;
- var items = this.dragInfo_.dragData.elements;
+ const state = bookmarks.Store.getInstance().data;
+ const items = this.dragInfo_.dragData.elements;
this.dndChip.showForItems(
e.clientX, e.clientY, items,
this.internalDragElement_ ?
@@ -489,15 +549,17 @@ cr.define('bookmarks', function() {
if (this.dropDestination_) {
// Complete the drag by moving all dragged items to the drop
// destination.
- var dropInfo = this.calculateDropInfo_(this.dropDestination_);
- var shouldHighlight = this.shouldHighlight_(this.dropDestination_);
+ const dropInfo = this.calculateDropInfo_(this.dropDestination_);
+ const shouldHighlight = this.shouldHighlight_(this.dropDestination_);
- var movePromises = this.dragInfo_.dragData.elements.map((item) => {
+ const movePromises = this.dragInfo_.dragData.elements.map((item) => {
return new Promise((resolve) => {
- chrome.bookmarks.move(item.id, {
- parentId: dropInfo.parentId,
- index: dropInfo.index == -1 ? undefined : dropInfo.index
- }, resolve);
+ chrome.bookmarks.move(
+ item.id, {
+ parentId: dropInfo.parentId,
+ index: dropInfo.index == -1 ? undefined : dropInfo.index
+ },
+ resolve);
});
});
@@ -523,7 +585,7 @@ cr.define('bookmarks', function() {
onDragStart_: function(e) {
// |e| will be for the originally dragged bookmark item which dragstart
// was disabled for due to mousemove's preventDefault.
- var dragElement = getDragElement(e.path);
+ const dragElement = getDragElement(e.path);
if (!dragElement)
return;
@@ -536,7 +598,7 @@ cr.define('bookmarks', function() {
// If we are dragging a single link, we can do the *Link* effect.
// Otherwise, we only allow copy and move.
if (e.dataTransfer) {
- var draggedNodes = this.dragInfo_.dragData.elements;
+ const draggedNodes = this.dragInfo_.dragData.elements;
e.dataTransfer.effectAllowed =
draggedNodes.length == 1 && draggedNodes[0].url ? 'copyLink' :
'copyMove';
@@ -556,9 +618,9 @@ cr.define('bookmarks', function() {
if (this.dropDestination_) {
e.preventDefault();
- var dropInfo = this.calculateDropInfo_(this.dropDestination_);
- var index = dropInfo.index != -1 ? dropInfo.index : undefined;
- var shouldHighlight = this.shouldHighlight_(this.dropDestination_);
+ const dropInfo = this.calculateDropInfo_(this.dropDestination_);
+ const index = dropInfo.index != -1 ? dropInfo.index : undefined;
+ const shouldHighlight = this.shouldHighlight_(this.dropDestination_);
if (shouldHighlight)
bookmarks.ApiListener.trackUpdatedItems();
@@ -623,8 +685,10 @@ cr.define('bookmarks', function() {
/** @private */
clearDragData_: function() {
this.dndChip.hide();
+ this.autoScroller_.reset();
this.internalDragElement_ = null;
this.mouseDownPos_ = null;
+ this.autoExpander_.reset();
// Defer the clearing of the data so that the bookmark manager API's drop
// event doesn't clear the drop data before the web drop event has a
@@ -642,12 +706,12 @@ cr.define('bookmarks', function() {
* @return {boolean}
*/
startNativeDrag_: function() {
- var state = bookmarks.Store.getInstance().data;
+ const state = bookmarks.Store.getInstance().data;
if (!this.dragInfo_.isDragValid())
return false;
- var draggedNodes =
+ const draggedNodes =
this.dragInfo_.dragData.elements.map((item) => item.id);
// Clear the drag data here so that the chip is hidden. The native drag
@@ -666,10 +730,10 @@ cr.define('bookmarks', function() {
* @return {boolean}
*/
onDragOverCommon_: function(e) {
- var state = bookmarks.Store.getInstance().data;
- var items = this.dragInfo_.dragData.elements;
+ const state = bookmarks.Store.getInstance().data;
+ const items = this.dragInfo_.dragData.elements;
- var overElement = getBookmarkElement(e.path);
+ const overElement = getBookmarkElement(e.path);
this.autoExpander_.update(e, overElement);
if (!overElement) {
this.dropIndicator_.finish();
@@ -705,13 +769,13 @@ cr.define('bookmarks', function() {
};
}
- var node = getBookmarkNode(dropDestination.element);
- var position = dropDestination.position;
- var index = -1;
- var parentId = node.id;
+ const node = getBookmarkNode(dropDestination.element);
+ const position = dropDestination.position;
+ let index = -1;
+ let parentId = node.id;
if (position != DropPosition.ON) {
- var state = bookmarks.Store.getInstance().data;
+ const state = bookmarks.Store.getInstance().data;
// Drops between items in the normal list and the sidebar use the drop
// destination node's parent.
@@ -734,12 +798,12 @@ cr.define('bookmarks', function() {
* @private
*/
calculateDragData_: function() {
- var dragId = this.internalDragElement_.itemId;
- var store = bookmarks.Store.getInstance();
- var state = store.data;
+ const dragId = this.internalDragElement_.itemId;
+ const store = bookmarks.Store.getInstance();
+ const state = store.data;
// Determine the selected bookmarks.
- var draggedNodes = Array.from(state.selection.items);
+ let draggedNodes = Array.from(state.selection.items);
// Change selection to the dragged node if the node is not part of the
// existing selection.
@@ -757,7 +821,7 @@ cr.define('bookmarks', function() {
}
// If any node can't be dragged, end the drag.
- var anyUnmodifiable = draggedNodes.some(
+ const anyUnmodifiable = draggedNodes.some(
(itemId) => !bookmarks.util.canEditNode(state, itemId));
if (anyUnmodifiable)
@@ -780,15 +844,15 @@ cr.define('bookmarks', function() {
* position - A |DropPosition| relative to the |element|.
*/
calculateDropDestination_: function(elementClientY, overElement) {
- var validDropPositions = this.calculateValidDropPositions_(overElement);
+ const validDropPositions = this.calculateValidDropPositions_(overElement);
if (validDropPositions == DropPosition.NONE)
return null;
- var above = validDropPositions & DropPosition.ABOVE;
- var below = validDropPositions & DropPosition.BELOW;
- var on = validDropPositions & DropPosition.ON;
- var rect = overElement.getDropTarget().getBoundingClientRect();
- var yRatio = (elementClientY - rect.top) / rect.height;
+ const above = validDropPositions & DropPosition.ABOVE;
+ const below = validDropPositions & DropPosition.BELOW;
+ const on = validDropPositions & DropPosition.ON;
+ const rect = overElement.getDropTarget().getBoundingClientRect();
+ const yRatio = (elementClientY - rect.top) / rect.height;
if (above && (yRatio <= .25 || yRatio <= .5 && (!below || !on)))
return {element: overElement, position: DropPosition.ABOVE};
@@ -810,9 +874,9 @@ cr.define('bookmarks', function() {
* @return {DropPosition} An bit field enumeration of valid drop locations.
*/
calculateValidDropPositions_: function(overElement) {
- var dragInfo = this.dragInfo_;
- var state = bookmarks.Store.getInstance().data;
- var itemId = overElement.itemId;
+ const dragInfo = this.dragInfo_;
+ const state = bookmarks.Store.getInstance().data;
+ let itemId = overElement.itemId;
// Drags aren't allowed onto the search result list.
if ((isBookmarkList(overElement) || isBookmarkItem(overElement)) &&
@@ -833,7 +897,7 @@ cr.define('bookmarks', function() {
return DropPosition.NONE;
}
- var validDropPositions = this.calculateDropAboveBelow_(overElement);
+ let validDropPositions = this.calculateDropAboveBelow_(overElement);
if (this.canDropOn_(overElement))
validDropPositions |= DropPosition.ON;
@@ -846,8 +910,8 @@ cr.define('bookmarks', function() {
* @return {DropPosition}
*/
calculateDropAboveBelow_: function(overElement) {
- var dragInfo = this.dragInfo_;
- var state = bookmarks.Store.getInstance().data;
+ const dragInfo = this.dragInfo_;
+ const state = bookmarks.Store.getInstance().data;
if (isBookmarkList(overElement))
return DropPosition.NONE;
@@ -856,16 +920,16 @@ cr.define('bookmarks', function() {
if (getBookmarkNode(overElement).parentId == ROOT_NODE_ID)
return DropPosition.NONE;
- var isOverFolderNode = isBookmarkFolderNode(overElement);
+ const isOverFolderNode = isBookmarkFolderNode(overElement);
// We can only drop between items in the tree if we have any folders.
if (isOverFolderNode && !dragInfo.isDraggingFolders())
return DropPosition.NONE;
- var validDropPositions = DropPosition.NONE;
+ let validDropPositions = DropPosition.NONE;
// Cannot drop above if the item above is already in the drag source.
- var previousElem = overElement.previousElementSibling;
+ const previousElem = overElement.previousElementSibling;
if (!previousElem || !dragInfo.isDraggingBookmark(previousElem.itemId))
validDropPositions |= DropPosition.ABOVE;
@@ -876,7 +940,7 @@ cr.define('bookmarks', function() {
return validDropPositions;
}
- var nextElement = overElement.nextElementSibling;
+ const nextElement = overElement.nextElementSibling;
// Cannot drop below if the item below is already in the drag source.
if (!nextElement || !dragInfo.isDraggingBookmark(nextElement.itemId))
@@ -896,7 +960,7 @@ cr.define('bookmarks', function() {
canDropOn_: function(overElement) {
// Allow dragging onto empty bookmark lists.
if (isBookmarkList(overElement)) {
- var state = bookmarks.Store.getInstance().data;
+ const state = bookmarks.Store.getInstance().data;
return state.selectedFolder &&
state.nodes[state.selectedFolder].children.length == 0;
}
@@ -917,7 +981,7 @@ cr.define('bookmarks', function() {
isBookmarkList(dropDestination.element);
},
- /** @param {bookmarks.TimerProxy} timerProxy */
+ /** @param {!Object} timerProxy */
setTimerProxyForTesting: function(timerProxy) {
this.timerProxy_ = timerProxy;
this.dropIndicator_.timerProxy = timerProxy;
@@ -937,6 +1001,8 @@ cr.define('bookmarks', function() {
};
return {
+ AutoExpander: AutoExpander,
+ AutoScroller: AutoScroller,
DNDManager: DNDManager,
DragInfo: DragInfo,
DropIndicator: DropIndicator,
diff --git a/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js b/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js
index d3138fa8b93..d46092be5fc 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/edit_dialog.js
@@ -82,7 +82,7 @@ Polymer({
* @private
*/
getDialogTitle_: function(isFolder, isEdit) {
- var title;
+ let title;
if (isEdit)
title = isFolder ? 'renameFolderTitle' : 'editBookmarkTitle';
else
@@ -98,8 +98,8 @@ Polymer({
* @private
*/
validateUrl_: function() {
- var urlInput = /** @type {PaperInputElement} */ (this.$.url);
- var originalValue = this.urlValue_;
+ const urlInput = /** @type {PaperInputElement} */ (this.$.url);
+ const originalValue = this.urlValue_;
if (urlInput.validate())
return true;
@@ -115,7 +115,7 @@ Polymer({
/** @private */
onSaveButtonTap_: function() {
- var edit = {'title': this.titleValue_};
+ const edit = {'title': this.titleValue_};
if (!this.isFolder_) {
if (!this.validateUrl_())
return;
diff --git a/chromium/chrome/browser/resources/md_bookmarks/folder_node.html b/chromium/chrome/browser/resources/md_bookmarks/folder_node.html
index 57a4100e22a..182b0226544 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/folder_node.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/folder_node.html
@@ -83,7 +83,7 @@
on-tap="selectFolder_"
on-dblclick="toggleFolder_"
on-contextmenu="onContextMenu_"
- tabindex$="[[getTabIndex_(isSelectedFolder_)]]"
+ tabindex$="[[getTabIndex_(selectedFolder_, itemId)]]"
hidden="[[isRootFolder_(depth)]]"
role="treeitem">
<template is="dom-if" if="[[hasChildFolder_]]">
@@ -92,7 +92,7 @@
on-tap="toggleFolder_"
on-mousedown="preventDefault_"
tabindex="-1"
- aria-hidden="true">
+ aria-label$="[[getButtonAriaLabel_(isOpen, item_)]]">
<iron-icon icon="cr:arrow-drop-down" is-open$="[[isOpen]]">
</iron-icon>
</button>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/folder_node.js b/chromium/chrome/browser/resources/md_bookmarks/folder_node.js
index b84e0b4c8f0..ba8e361c0b9 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/folder_node.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/folder_node.js
@@ -102,9 +102,9 @@ Polymer({
* @param {!Event} e
*/
onKeydown_: function(e) {
- var yDirection = 0;
- var xDirection = 0;
- var handled = true;
+ let yDirection = 0;
+ let xDirection = 0;
+ let handled = true;
if (e.key == 'ArrowUp') {
yDirection = -1;
} else if (e.key == 'ArrowDown') {
@@ -113,6 +113,8 @@ Polymer({
xDirection = -1;
} else if (e.key == 'ArrowRight') {
xDirection = 1;
+ } else if (e.key == ' ') {
+ this.selectFolder_();
} else {
handled = false;
}
@@ -142,8 +144,8 @@ Polymer({
* @param {!HTMLElement} currentFocus
*/
changeKeyboardSelection_: function(xDirection, yDirection, currentFocus) {
- var newFocusFolderNode = null;
- var isChildFolderNodeFocused =
+ let newFocusFolderNode = null;
+ const isChildFolderNodeFocused =
currentFocus.tagName == 'BOOKMARKS-FOLDER-NODE';
if (xDirection == 1) {
@@ -163,7 +165,7 @@ Polymer({
if (this.hasChildFolder_ && this.isOpen) {
this.dispatch(bookmarks.actions.changeFolderOpen(this.item_.id, false));
} else {
- var parentFolderNode = this.getParentFolderNode_();
+ const parentFolderNode = this.getParentFolderNode_();
if (parentFolderNode.itemId != ROOT_NODE_ID) {
parentFolderNode.selectFolder_();
parentFolderNode.getFocusTarget().focus();
@@ -176,7 +178,7 @@ Polymer({
// The current node's successor is its first child when open.
if (!isChildFolderNodeFocused && yDirection == 1 && this.isOpen) {
- var children = this.getChildFolderNodes_();
+ const children = this.getChildFolderNodes_();
if (children.length)
newFocusFolderNode = children[0];
}
@@ -219,10 +221,10 @@ Polymer({
* before/after |child|.
*/
getNextChild_: function(reverse, child) {
- var newFocus = null;
- var children = this.getChildFolderNodes_();
+ let newFocus = null;
+ const children = this.getChildFolderNodes_();
- var index = children.indexOf(child);
+ const index = children.indexOf(child);
assert(index != -1);
if (reverse) {
// A child node's predecessor is either the previous child's last visible
@@ -243,7 +245,7 @@ Polymer({
* @return {BookmarksFolderNodeElement|null}
*/
getParentFolderNode_: function() {
- var parentFolderNode = this.parentNode;
+ let parentFolderNode = this.parentNode;
while (parentFolderNode &&
parentFolderNode.tagName != 'BOOKMARKS-FOLDER-NODE') {
parentFolderNode = parentFolderNode.parentNode || parentFolderNode.host;
@@ -256,7 +258,7 @@ Polymer({
* @return {BookmarksFolderNodeElement}
*/
getLastVisibleDescendant_: function() {
- var children = this.getChildFolderNodes_();
+ const children = this.getChildFolderNodes_();
if (!this.isOpen || children.length == 0)
return this;
@@ -364,7 +366,10 @@ Polymer({
* @return {string}
*/
getTabIndex_: function() {
- return this.isSelectedFolder_ ? '0' : '-1';
+ // This returns a tab index of 0 for the cached selected folder when the
+ // search is active, even though this node is not technically selected. This
+ // allows the sidebar to be focusable during a search.
+ return this.selectedFolder_ == this.itemId ? '0' : '-1';
},
/**
@@ -390,4 +395,14 @@ Polymer({
return openState != null ? openState :
depth <= FOLDER_OPEN_BY_DEFAULT_DEPTH;
},
+
+ /**
+ * @private
+ * @return {string}
+ */
+ getButtonAriaLabel_: function() {
+ return loadTimeData.getStringF(
+ this.isOpen ? 'sidebarNodeCollapseAxLabel' : 'sidebarNodeExpandAxLabel',
+ this.item_.title);
+ },
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/item.html b/chromium/chrome/browser/resources/md_bookmarks/item.html
index 30c219c6e3b..da6943d36fc 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/item.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/item.html
@@ -51,6 +51,7 @@
class="more-vert-button"
tabindex$="[[ironListTabIndex]]"
title="$i18n{moreActionsButtonTitle}"
+ aria-label$="[[getButtonAriaLabel_(item_)]]"
on-click="onMenuButtonClick_"
on-dblclick="onMenuButtonDblClick_"
aria-haspopup="menu">
diff --git a/chromium/chrome/browser/resources/md_bookmarks/item.js b/chromium/chrome/browser/resources/md_bookmarks/item.js
index 91e3f038970..c3c12c3bede 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/item.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/item.js
@@ -138,7 +138,7 @@ Polymer({
// Ignore double clicks so that Ctrl double-clicking an item won't deselect
// the item before opening.
if (e.detail != 2) {
- var addKey = cr.isMac ? e.metaKey : e.ctrlKey;
+ const addKey = cr.isMac ? e.metaKey : e.ctrlKey;
this.dispatch(bookmarks.actions.selectItem(this.itemId, this.getState(), {
clear: !addKey,
range: e.shiftKey,
@@ -168,8 +168,8 @@ Polymer({
if (!this.isSelectedItem_)
this.selectThisItem_();
- var commandManager = bookmarks.CommandManager.getInstance();
- var itemSet = this.getState().selection.items;
+ const commandManager = bookmarks.CommandManager.getInstance();
+ const itemSet = this.getState().selection.items;
if (commandManager.canExecute(Command.OPEN, itemSet))
commandManager.handle(Command.OPEN, itemSet);
},
@@ -186,9 +186,9 @@ Polymer({
if (this.isFolder_)
return;
- var commandManager = bookmarks.CommandManager.getInstance();
- var itemSet = this.getState().selection.items;
- var command = e.shiftKey ? Command.OPEN : Command.OPEN_NEW_TAB;
+ const commandManager = bookmarks.CommandManager.getInstance();
+ const itemSet = this.getState().selection.items;
+ const command = e.shiftKey ? Command.OPEN : Command.OPEN_NEW_TAB;
if (commandManager.canExecute(command, itemSet))
commandManager.handle(command, itemSet);
},
@@ -212,4 +212,10 @@ Polymer({
this.$.icon.className = url ? 'website-icon' : 'folder-icon';
this.$.icon.style.backgroundImage = url ? cr.icon.getFavicon(url) : null;
},
+
+ /** @private */
+ getButtonAriaLabel_: function() {
+ return loadTimeData.getStringF(
+ 'moreActionsButtonAxLabel', this.item_.title);
+ }
});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/list.html b/chromium/chrome/browser/resources/md_bookmarks/list.html
index 00f86dbff22..2f5ed7aa577 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/list.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/list.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
@@ -38,8 +39,11 @@
user-select: none;
}
</style>
- <iron-list id="list" items="[[displayedList_]]"
- hidden$="[[isEmptyList_(displayedList_.length)]]" role="list">
+ <iron-list id="list"
+ items="[[displayedList_]]"
+ hidden$="[[isEmptyList_(displayedList_.length)]]"
+ role="group"
+ aria-label="$i18n{listAxLabel}">
<template>
<bookmarks-item item-id="[[item.id]]" draggable="true"
tabindex$="[[tabIndex]]" iron-list-tab-index="[[tabIndex]]">
diff --git a/chromium/chrome/browser/resources/md_bookmarks/list.js b/chromium/chrome/browser/resources/md_bookmarks/list.js
index 823f955e8b1..3898fc089c9 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/list.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/list.js
@@ -50,7 +50,7 @@ Polymer({
},
attached: function() {
- var list = /** @type {IronListElement} */ (this.$.list);
+ const list = /** @type {IronListElement} */ (this.$.list);
list.scrollTarget = this;
this.watch('displayedIds_', function(state) {
@@ -70,6 +70,10 @@ Polymer({
/** @private {function(!Event)} */
this.boundOnHighlightItems_ = this.onHighlightItems_.bind(this);
document.addEventListener('highlight-items', this.boundOnHighlightItems_);
+
+ Polymer.RenderStatus.afterNextRender(this, function() {
+ Polymer.IronA11yAnnouncer.requestAvailability();
+ });
},
detached: function() {
@@ -95,12 +99,12 @@ Polymer({
return {id: id};
});
} else {
- var splices = Polymer.ArraySplice.calculateSplices(
+ const splices = Polymer.ArraySplice.calculateSplices(
/** @type {!Array<string>} */ (newValue),
/** @type {!Array<string>} */ (oldValue));
splices.forEach((splice) => {
// TODO(calamity): Could use notifySplices to improve performance here.
- var additions =
+ const additions =
newValue.slice(splice.index, splice.index + splice.addedCount)
.map(function(id) {
return {id: id};
@@ -109,6 +113,10 @@ Polymer({
'displayedList_', splice.index, splice.removed.length
].concat(additions));
});
+
+ cr.sendWithPromise(
+ 'getPluralString', 'listChanged', this.displayedList_.length)
+ .then((label) => this.fire('iron-announce', {text: label}));
}
},
@@ -123,8 +131,8 @@ Polymer({
* @private
*/
scrollToId_: function(itemId) {
- var index = this.displayedIds_.indexOf(itemId);
- var list = this.$.list;
+ const index = this.displayedIds_.indexOf(itemId);
+ const list = this.$.list;
if (index >= 0 && index < list.firstVisibleIndex ||
index > list.lastVisibleIndex) {
list.scrollToIndex(index);
@@ -133,7 +141,7 @@ Polymer({
/** @private */
emptyListMessage_: function() {
- var emptyListMessage = this.searchTerm_ ? 'noSearchResults' : 'emptyList';
+ const emptyListMessage = this.searchTerm_ ? 'noSearchResults' : 'emptyList';
return loadTimeData.getString(emptyListMessage);
},
@@ -174,18 +182,18 @@ Polymer({
// Ensure that we only select items which are actually being displayed.
// This should only matter if an unrelated update to the bookmark model
// happens with the perfect timing to end up in a tracked batch update.
- var toHighlight = /** @type {!Array<string>} */
+ const toHighlight = /** @type {!Array<string>} */
(e.detail.filter((item) => this.displayedIds_.indexOf(item) != -1));
assert(toHighlight.length > 0);
- var leadId = toHighlight[0];
+ const leadId = toHighlight[0];
this.dispatch(
bookmarks.actions.selectAll(toHighlight, this.getState(), leadId));
// Allow iron-list time to render additions to the list.
this.async(function() {
this.scrollToId_(leadId);
- var leadIndex = this.displayedIds_.indexOf(leadId);
+ const leadIndex = this.displayedIds_.indexOf(leadId);
assert(leadIndex != -1);
this.$.list.focusItem(leadIndex);
});
@@ -196,13 +204,13 @@ Polymer({
* @private
*/
onItemKeydown_: function(e) {
- var handled = true;
- var list = this.$.list;
- var focusMoved = false;
- var focusedIndex =
+ let handled = true;
+ const list = this.$.list;
+ let focusMoved = false;
+ let focusedIndex =
this.getIndexForItemElement_(/** @type {HTMLElement} */ (e.target));
- var oldFocusedIndex = focusedIndex;
- var cursorModifier = cr.isMac ? e.metaKey : e.ctrlKey;
+ const oldFocusedIndex = focusedIndex;
+ const cursorModifier = cr.isMac ? e.metaKey : e.ctrlKey;
if (e.key == 'ArrowUp') {
focusedIndex--;
focusMoved = true;
@@ -243,7 +251,7 @@ Polymer({
// If the focus moved from something other than a Ctrl + move event,
// update the selection.
- var config = {
+ const config = {
clear: !cursorModifier,
range: e.shiftKey,
toggle: false,
diff --git a/chromium/chrome/browser/resources/md_bookmarks/mouse_focus_behavior.js b/chromium/chrome/browser/resources/md_bookmarks/mouse_focus_behavior.js
index 63755568cee..32d505c0f91 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/mouse_focus_behavior.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/mouse_focus_behavior.js
@@ -4,7 +4,7 @@
cr.define('bookmarks', function() {
/** @const */
- var HIDE_FOCUS_RING_ATTRIBUTE = 'hide-focus-ring';
+ const HIDE_FOCUS_RING_ATTRIBUTE = 'hide-focus-ring';
/**
* Behavior which adds the 'hide-focus-ring' attribute to a target element
@@ -12,7 +12,7 @@ cr.define('bookmarks', function() {
* to be hidden without affecting keyboard users.
* @polymerBehavior
*/
- var MouseFocusBehavior = {
+ const MouseFocusBehavior = {
attached: function() {
this.boundOnMousedown_ = this.onMousedown_.bind(this);
this.boundOnKeydown = this.onKeydown_.bind(this);
diff --git a/chromium/chrome/browser/resources/md_bookmarks/reducers.js b/chromium/chrome/browser/resources/md_bookmarks/reducers.js
index 2255f7971ef..a307e5551e2 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/reducers.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/reducers.js
@@ -10,7 +10,7 @@
*/
cr.define('bookmarks', function() {
- var SelectionState = {};
+ const SelectionState = {};
/**
* @param {SelectionState} selectionState
@@ -18,12 +18,12 @@ cr.define('bookmarks', function() {
* @return {SelectionState}
*/
SelectionState.selectItems = function(selectionState, action) {
- var newItems = new Set();
+ let newItems = new Set();
if (!action.clear)
newItems = new Set(selectionState.items);
action.items.forEach(function(id) {
- var add = true;
+ let add = true;
if (action.toggle)
add = !newItems.has(id);
@@ -107,7 +107,7 @@ cr.define('bookmarks', function() {
}
};
- var SearchState = {};
+ const SearchState = {};
/**
* @param {SearchState} search
@@ -152,7 +152,7 @@ cr.define('bookmarks', function() {
if (!search.results)
return search;
- var newResults = [];
+ const newResults = [];
search.results.forEach(function(id) {
if (!deletedIds.has(id))
newResults.push(id);
@@ -183,7 +183,7 @@ cr.define('bookmarks', function() {
}
};
- var NodeState = {};
+ const NodeState = {};
/**
* @param {NodeMap} nodes
@@ -192,7 +192,7 @@ cr.define('bookmarks', function() {
* @return {NodeMap}
*/
NodeState.modifyNode_ = function(nodes, id, callback) {
- var nodeModification = {};
+ const nodeModification = {};
nodeModification[id] = callback(nodes[id]);
return Object.assign({}, nodes, nodeModification);
};
@@ -203,11 +203,11 @@ cr.define('bookmarks', function() {
* @return {NodeMap}
*/
NodeState.createBookmark = function(nodes, action) {
- var nodeModifications = {};
+ const nodeModifications = {};
nodeModifications[action.id] = action.node;
- var parentNode = nodes[action.parentId];
- var newChildren = parentNode.children.slice();
+ const parentNode = nodes[action.parentId];
+ const newChildren = parentNode.children.slice();
newChildren.splice(action.parentIndex, 0, action.id);
nodeModifications[action.parentId] = Object.assign({}, parentNode, {
children: newChildren,
@@ -238,23 +238,23 @@ cr.define('bookmarks', function() {
* @return {NodeMap}
*/
NodeState.moveBookmark = function(nodes, action) {
- var nodeModifications = {};
- var id = action.id;
+ const nodeModifications = {};
+ const id = action.id;
// Change node's parent.
nodeModifications[id] =
Object.assign({}, nodes[id], {parentId: action.parentId});
// Remove from old parent.
- var oldParentId = action.oldParentId;
- var oldParentChildren = nodes[oldParentId].children.slice();
+ const oldParentId = action.oldParentId;
+ const oldParentChildren = nodes[oldParentId].children.slice();
oldParentChildren.splice(action.oldIndex, 1);
nodeModifications[oldParentId] =
Object.assign({}, nodes[oldParentId], {children: oldParentChildren});
// Add to new parent.
- var parentId = action.parentId;
- var parentChildren = oldParentId == parentId ?
+ const parentId = action.parentId;
+ const parentChildren = oldParentId == parentId ?
oldParentChildren :
nodes[parentId].children.slice();
parentChildren.splice(action.index, 0, action.id);
@@ -270,9 +270,9 @@ cr.define('bookmarks', function() {
* @return {NodeMap}
*/
NodeState.removeBookmark = function(nodes, action) {
- var newState =
+ const newState =
NodeState.modifyNode_(nodes, action.parentId, function(node) {
- var newChildren = node.children.slice();
+ const newChildren = node.children.slice();
newChildren.splice(action.index, 1);
return /** @type {BookmarkNode} */ (
Object.assign({}, node, {children: newChildren}));
@@ -317,7 +317,7 @@ cr.define('bookmarks', function() {
}
};
- var SelectedFolderState = {};
+ const SelectedFolderState = {};
/**
* @param {NodeMap} nodes
@@ -326,7 +326,7 @@ cr.define('bookmarks', function() {
* @return {boolean}
*/
SelectedFolderState.isAncestorOf = function(nodes, ancestorId, childId) {
- var currentId = childId;
+ let currentId = childId;
// Work upwards through the tree from child.
while (currentId) {
if (currentId == ancestorId)
@@ -368,7 +368,7 @@ cr.define('bookmarks', function() {
}
};
- var FolderOpenState = {};
+ const FolderOpenState = {};
/**
* @param {FolderOpenState} folderOpenState
@@ -378,9 +378,9 @@ cr.define('bookmarks', function() {
*/
FolderOpenState.openFolderAndAncestors = function(
folderOpenState, id, nodes) {
- var newFolderOpenState =
+ const newFolderOpenState =
/** @type {FolderOpenState} */ (new Map(folderOpenState));
- for (var currentId = id; currentId; currentId = nodes[currentId].parentId)
+ for (let currentId = id; currentId; currentId = nodes[currentId].parentId)
newFolderOpenState.set(currentId, true);
return newFolderOpenState;
@@ -392,7 +392,7 @@ cr.define('bookmarks', function() {
* @return {FolderOpenState}
*/
FolderOpenState.changeFolderOpen = function(folderOpenState, action) {
- var newFolderOpenState =
+ const newFolderOpenState =
/** @type {FolderOpenState} */ (new Map(folderOpenState));
newFolderOpenState.set(action.id, action.open);
@@ -427,7 +427,7 @@ cr.define('bookmarks', function() {
}
};
- var PreferencesState = {};
+ const PreferencesState = {};
/**
* @param {PreferencesState} prefs
diff --git a/chromium/chrome/browser/resources/md_bookmarks/router.js b/chromium/chrome/browser/resources/md_bookmarks/router.js
index 89267f9ef2b..144586d47d4 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/router.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/router.js
@@ -49,8 +49,8 @@ Polymer({
/** @private */
onQueryParamsChanged_: function() {
- var searchTerm = this.queryParams_.q || '';
- var selectedId = this.queryParams_.id;
+ const searchTerm = this.queryParams_.q || '';
+ let selectedId = this.queryParams_.id;
if (!selectedId && !searchTerm)
selectedId = BOOKMARKS_BAR_ID;
diff --git a/chromium/chrome/browser/resources/md_bookmarks/store.js b/chromium/chrome/browser/resources/md_bookmarks/store.js
index 0b679e2a5c1..3b0f7cad98a 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/store.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/store.js
@@ -55,7 +55,7 @@ cr.define('bookmarks', function() {
/** @param {!StoreObserver} observer */
removeObserver: function(observer) {
- var index = this.observers_.indexOf(observer);
+ const index = this.observers_.indexOf(observer);
this.observers_.splice(index, 1);
},
diff --git a/chromium/chrome/browser/resources/md_bookmarks/store_client.js b/chromium/chrome/browser/resources/md_bookmarks/store_client.js
index b7149ea2831..bc5b4342930 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/store_client.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/store_client.js
@@ -12,7 +12,7 @@ cr.define('bookmarks', function() {
* @polymerBehavior
* @implements {StoreObserver}
*/
- var StoreClient = {
+ const StoreClient = {
created: function() {
/**
* @type {!Array<{
@@ -80,8 +80,8 @@ cr.define('bookmarks', function() {
/** @param {string} newState */
onStateChanged: function(newState) {
this.watches_.forEach((watch) => {
- var oldValue = this[watch.localProperty];
- var newValue = watch.valueGetter(newState);
+ const oldValue = this[watch.localProperty];
+ const newValue = watch.valueGetter(newState);
// Avoid poking Polymer unless something has actually changed. Reducers
// must return new objects rather than mutating existing objects, so
diff --git a/chromium/chrome/browser/resources/md_bookmarks/timer_proxy.js b/chromium/chrome/browser/resources/md_bookmarks/timer_proxy.js
deleted file mode 100644
index 091023fecb5..00000000000
--- a/chromium/chrome/browser/resources/md_bookmarks/timer_proxy.js
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A class that mediates window timer calls to support mockability
- * in tests.
- */
-
-cr.define('bookmarks', function() {
- /** @constructor */
- function TimerProxy() {}
-
- TimerProxy.prototype = {
- /**
- * @param {function()|string} fn
- * @param {number=} delay
- * @return {number}
- */
- setTimeout: function(fn, delay) {
- return window.setTimeout(fn, delay);
- },
-
- /** @param {number|undefined?} id */
- clearTimeout: function(id) {
- window.clearTimeout(id);
- },
- };
-
- /**
- * A one-shot debouncer which fires the given callback after a delay. The
- * delay can be refreshed by calling resetTimer. Resetting with no delay moves
- * the callback to the end of the task queue.
- * @param {!function()} callback
- * @constructor
- */
- function Debouncer(callback) {
- /** @private {!function()} */
- this.callback_ = callback;
- /** @private {!bookmarks.TimerProxy} */
- this.timerProxy_ = new TimerProxy();
- /** @private {?number} */
- this.timer_ = null;
- /** @private {!function()} */
- this.boundTimerCallback_ = this.timerCallback_.bind(this);
- /** @private {boolean} */
- this.isDone_ = false;
- /** @private {!PromiseResolver} */
- this.promiseResolver_ = new PromiseResolver();
- }
-
- Debouncer.prototype = {
- /**
- * @param {number=} delay
- */
- resetTimeout: function(delay) {
- if (this.timer_)
- this.timerProxy_.clearTimeout(this.timer_);
- this.timer_ =
- this.timerProxy_.setTimeout(this.boundTimerCallback_, delay);
- },
-
- /**
- * @return {boolean} True if the Debouncer has finished processing.
- */
- done: function() {
- return this.isDone_;
- },
-
- /**
- * @return {Promise} Promise which resolves immediately after the callback.
- */
- get promise() {
- return this.promiseResolver_.promise;
- },
-
- /** @private */
- timerCallback_: function() {
- this.isDone_ = true;
- this.callback_.call();
- this.promiseResolver_.resolve();
- },
- };
-
- return {
- Debouncer: Debouncer,
- TimerProxy: TimerProxy,
- };
-});
diff --git a/chromium/chrome/browser/resources/md_bookmarks/toast_manager.html b/chromium/chrome/browser/resources/md_bookmarks/toast_manager.html
index cb30e2209fd..0e5b0b60e1f 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/toast_manager.html
+++ b/chromium/chrome/browser/resources/md_bookmarks/toast_manager.html
@@ -1,12 +1,14 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
<link rel="import" href="chrome://bookmarks/shared_style.html">
<dom-module id="bookmarks-toast-manager">
<template>
<style include="shared-style">
#content {
+ color: #fff;
display: flex;
flex: 1;
overflow: hidden;
@@ -32,39 +34,13 @@
span {
white-space: pre;
}
-
- #toast {
- align-items: center;
- background-color: #323232;
- border-radius: 4px;
- bottom: 0;
- box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.28);
- box-sizing: border-box;
- color: #fff;
- display: flex;
- margin: 24px;
- max-width: 568px;
- min-height: 52px;
- min-width: 288px;
- opacity: 0;
- padding: 0 24px;
- position: fixed;
- transform: translateY(100px);
- transition: transform 300ms, opacity 300ms;
- white-space: nowrap;
- }
-
- #toast[aria-hidden=false] {
- opacity: 1;
- transform: translateY(0);
- }
</style>
- <div id="toast">
+ <cr-toast id="toast" duration="[[duration]]">
<div id="content"></div>
<paper-button id="button" hidden$="[[!showUndo_]]" on-tap="onUndoTap_">
$i18n{undo}
</paper-button>
- </div>
+ </cr-toast>
</template>
<script src="chrome://bookmarks/toast_manager.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_bookmarks/toast_manager.js b/chromium/chrome/browser/resources/md_bookmarks/toast_manager.js
index d2da7a5d5f8..a489b15db48 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/toast_manager.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/toast_manager.js
@@ -7,7 +7,7 @@
*/
cr.define('bookmarks', function() {
- var ToastManager = Polymer({
+ const ToastManager = Polymer({
is: 'bookmarks-toast-manager',
properties: {
@@ -17,22 +17,9 @@ cr.define('bookmarks', function() {
},
/** @private */
- open_: {
- type: Boolean,
- observer: 'openChanged_',
- value: false,
- },
-
- /** @private */
showUndo_: Boolean,
},
- /** @private {bookmarks.TimerProxy} */
- timerProxy_: new bookmarks.TimerProxy(),
-
- /** @private {number|null} */
- hideTimeoutId_: null,
-
/** @override */
attached: function() {
assert(ToastManager.instance_ == null);
@@ -54,6 +41,7 @@ cr.define('bookmarks', function() {
show: function(label, showUndo) {
this.$.content.textContent = label;
this.showInternal_(showUndo);
+ this.$.toast.show();
},
/**
@@ -62,13 +50,13 @@ cr.define('bookmarks', function() {
* @param {boolean} showUndo Whether the undo button should be shown.
*/
showForStringPieces: function(pieces, showUndo) {
- var content = this.$.content;
+ const content = this.$.content;
content.textContent = '';
pieces.forEach(function(p) {
if (p.value.length == 0)
return;
- var span = document.createElement('span');
+ const span = document.createElement('span');
span.textContent = p.value;
if (p.collapsible)
span.classList.add('collapsible');
@@ -84,26 +72,13 @@ cr.define('bookmarks', function() {
* @private
*/
showInternal_: function(showUndo) {
- this.open_ = true;
this.showUndo_ = showUndo;
this.fire('iron-announce', {text: this.$.content.textContent});
-
- if (!this.duration)
- return;
-
- if (this.hideTimeoutId_ != null)
- this.timerProxy_.clearTimeout(this.hideTimeoutId_);
-
- this.hideTimeoutId_ = this.timerProxy_.setTimeout(() => {
- this.hide();
- this.hideTimeoutId_ = null;
- }, this.duration);
+ this.$.toast.show();
},
hide: function() {
- this.open_ = false;
- // Hide the undo button to prevent it from being accessed with tab.
- this.showUndo_ = false;
+ this.$.toast.hide();
},
/** @private */
@@ -111,11 +86,6 @@ cr.define('bookmarks', function() {
// Will hide the toast.
this.fire('command-undo');
},
-
- /** @private */
- openChanged_: function() {
- this.$.toast.setAttribute('aria-hidden', String(!this.open_));
- },
});
/** @private {?bookmarks.ToastManager} */
diff --git a/chromium/chrome/browser/resources/md_bookmarks/toolbar.js b/chromium/chrome/browser/resources/md_bookmarks/toolbar.js
index 5923a896234..26ef60991b6 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/toolbar.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/toolbar.js
@@ -94,7 +94,7 @@ Polymer({
* @private
*/
onMenuButtonOpenTap_: function(e) {
- var menu = /** @type {!CrActionMenuElement} */ (this.$.dropdown.get());
+ const menu = /** @type {!CrActionMenuElement} */ (this.$.dropdown.get());
menu.showAt(/** @type {!Element} */ (e.target));
},
@@ -108,7 +108,7 @@ Polymer({
/** @private */
onAddBookmarkTap_: function() {
- var dialog =
+ const dialog =
/** @type {BookmarksEditDialogElement} */ (this.$.addDialog.get());
dialog.showAddDialog(false, assert(this.selectedFolder_));
this.closeDropdownMenu_();
@@ -116,7 +116,7 @@ Polymer({
/** @private */
onAddFolderTap_: function() {
- var dialog =
+ const dialog =
/** @type {BookmarksEditDialogElement} */ (this.$.addDialog.get());
dialog.showAddDialog(true, assert(this.selectedFolder_));
this.closeDropdownMenu_();
@@ -136,8 +136,8 @@ Polymer({
/** @private */
onDeleteSelectionTap_: function() {
- var selection = this.selectedItems_;
- var commandManager = bookmarks.CommandManager.getInstance();
+ const selection = this.selectedItems_;
+ const commandManager = bookmarks.CommandManager.getInstance();
assert(commandManager.canExecute(Command.DELETE, selection));
commandManager.handle(Command.DELETE, selection);
},
@@ -149,7 +149,7 @@ Polymer({
/** @private */
closeDropdownMenu_: function() {
- var menu = /** @type {!CrActionMenuElement} */ (this.$.dropdown.get());
+ const menu = /** @type {!CrActionMenuElement} */ (this.$.dropdown.get());
menu.close();
},
@@ -158,7 +158,7 @@ Polymer({
* @private
*/
onSearchChanged_: function(e) {
- var searchTerm = /** @type {string} */ (e.detail);
+ const searchTerm = /** @type {string} */ (e.detail);
if (searchTerm != this.searchTerm_)
this.dispatch(bookmarks.actions.setSearchTerm(searchTerm));
},
diff --git a/chromium/chrome/browser/resources/md_bookmarks/types.js b/chromium/chrome/browser/resources/md_bookmarks/types.js
index 560cf65d61c..3ff4e59fe53 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/types.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/types.js
@@ -19,12 +19,12 @@
* children: (!Array<string>|undefined),
* }}
*/
-var BookmarkNode;
+let BookmarkNode;
/**
* @typedef {!Object<string, BookmarkNode>}
*/
-var NodeMap;
+let NodeMap;
/**
* @typedef {{
@@ -34,7 +34,7 @@ var NodeMap;
*
* |items| is used as a set and all values in the map are true.
*/
-var SelectionState;
+let SelectionState;
/**
* Note:
@@ -53,10 +53,10 @@ var SelectionState;
* results: ?Array<string>,
* }}
*/
-var SearchState;
+let SearchState;
/** @typedef {!Map<string, boolean>} */
-var FolderOpenState;
+let FolderOpenState;
/**
* @typedef {{
@@ -64,7 +64,7 @@ var FolderOpenState;
* incognitoAvailability: IncognitoAvailability,
* }}
*/
-var PreferencesState;
+let PreferencesState;
/**
* @typedef {{
@@ -76,16 +76,16 @@ var PreferencesState;
* selection: SelectionState,
* }}
*/
-var BookmarksPageState;
+let BookmarksPageState;
/** @typedef {{name: string}} */
-var Action;
+let Action;
/** @typedef {function(function(?Action))} */
-var DeferredAction;
+let DeferredAction;
/** @typedef {{element: BookmarkElement, position: DropPosition}} */
-var DropDestination;
+let DropDestination;
/**
* @record
diff --git a/chromium/chrome/browser/resources/md_bookmarks/util.js b/chromium/chrome/browser/resources/md_bookmarks/util.js
index acdd4240e9d..ea85762bb86 100644
--- a/chromium/chrome/browser/resources/md_bookmarks/util.js
+++ b/chromium/chrome/browser/resources/md_bookmarks/util.js
@@ -25,7 +25,7 @@ cr.define('bookmarks.util', function() {
* @return {!BookmarkNode}
*/
function normalizeNode(treeNode) {
- var node = Object.assign({}, treeNode);
+ const node = Object.assign({}, treeNode);
// Node index is not necessary and not kept up-to-date. Remove it from the
// data structure so we don't accidentally depend on the incorrect
// information.
@@ -46,12 +46,12 @@ cr.define('bookmarks.util', function() {
*/
function normalizeNodes(rootNode) {
/** @type {NodeMap} */
- var nodeMap = {};
- var stack = [];
+ const nodeMap = {};
+ const stack = [];
stack.push(rootNode);
while (stack.length > 0) {
- var node = stack.pop();
+ const node = stack.pop();
nodeMap[node.id] = normalizeNode(node);
if (!node.children)
continue;
@@ -127,8 +127,8 @@ cr.define('bookmarks.util', function() {
* @return {boolean}
*/
function hasChildFolders(id, nodes) {
- var children = nodes[id].children;
- for (var i = 0; i < children.length; i++) {
+ const children = nodes[id].children;
+ for (let i = 0; i < children.length; i++) {
if (nodes[children[i]].children)
return true;
}
@@ -142,13 +142,13 @@ cr.define('bookmarks.util', function() {
* @return {!Set<string>}
*/
function getDescendants(nodes, baseId) {
- var descendants = new Set();
- var stack = [];
+ const descendants = new Set();
+ const stack = [];
stack.push(baseId);
while (stack.length > 0) {
- var id = stack.pop();
- var node = nodes[id];
+ const id = stack.pop();
+ const node = nodes[id];
if (!node)
continue;
@@ -182,7 +182,7 @@ cr.define('bookmarks.util', function() {
* @template T
*/
function removeIdsFromObject(map, ids) {
- var newObject = Object.assign({}, map);
+ const newObject = Object.assign({}, map);
ids.forEach(function(id) {
delete newObject[id];
});
@@ -197,7 +197,7 @@ cr.define('bookmarks.util', function() {
* @template T
*/
function removeIdsFromMap(map, ids) {
- var newMap = new Map(map);
+ const newMap = new Map(map);
ids.forEach(function(id) {
newMap.delete(id);
});
@@ -210,7 +210,7 @@ cr.define('bookmarks.util', function() {
* @return {!Set<string>}
*/
function removeIdsFromSet(set, ids) {
- var difference = new Set(set);
+ const difference = new Set(set);
ids.forEach(function(id) {
difference.delete(id);
});
diff --git a/chromium/chrome/browser/resources/md_downloads/BUILD.gn b/chromium/chrome/browser/resources/md_downloads/BUILD.gn
index 1b340e3511c..f741fce8c0b 100644
--- a/chromium/chrome/browser/resources/md_downloads/BUILD.gn
+++ b/chromium/chrome/browser/resources/md_downloads/BUILD.gn
@@ -1,6 +1,6 @@
-import("../vulcanize.gni")
+import("../optimize_webui.gni")
-vulcanize("build") {
+optimize_webui("build") {
deps = []
host = "downloads"
html_in_files = [ "downloads.html" ]
diff --git a/chromium/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs b/chromium/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs
deleted file mode 100644
index bc3524bc5f9..00000000000
--- a/chromium/chrome/browser/resources/md_downloads/action_service_unittest.gtestjs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @param {!Array<string>} list
- * @return {string}
- */
-function str(list) {
- return JSON.stringify(list);
-}
-
-var ActionServiceUnitTest = class extends testing.Test {
- /** @override */
- get extraLibraries() {
- return [
- '../../../../ui/webui/resources/js/cr.js',
- 'browser_proxy.js',
- 'action_service.js',
- ];
- }
-}
-
-TEST_F('ActionServiceUnitTest', 'splitTerms', function() {
- const ActionService = downloads.ActionService;
- assertEquals(str([]), str(ActionService.splitTerms('')));
- assertEquals(str([]), str(ActionService.splitTerms(' ')));
- assertEquals(str(['a']), str(ActionService.splitTerms('a')));
- assertEquals(str(['a b']), str(ActionService.splitTerms('a b')));
- assertEquals(str(['a', 'b']), str(ActionService.splitTerms('a "b"')));
- assertEquals(str(['a', 'b', 'c']), str(ActionService.splitTerms('a "b" c')));
- assertEquals(str(['a', 'b b', 'c']),
- str(ActionService.splitTerms('a "b b" c')));
-});
-
-TEST_F('ActionServiceUnitTest', 'searchWithSimilarTerms', function() {
- class TestActionService extends downloads.ActionService {
- loadMore() { /* No chrome.send() for you! */ }
- }
-
- const actionService = new TestActionService();
-
- assertTrue(actionService.search('a'));
- assertFalse(actionService.search('a ')); // Same term + space should no-op.
-});
diff --git a/chromium/chrome/browser/resources/md_downloads/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_downloads/compiled_resources2.gyp
index 19accde00e5..b9e2ca905c3 100644
--- a/chromium/chrome/browser/resources/md_downloads/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_downloads/compiled_resources2.gyp
@@ -4,15 +4,6 @@
{
'targets': [
{
- 'target_name': 'action_service',
- 'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
- 'browser_proxy',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
'target_name': 'browser_proxy',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
@@ -58,9 +49,9 @@
'<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:ui',
'<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:command',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-list/compiled_resources2.gyp:iron-list-extracted',
- 'action_service',
'browser_proxy',
'item',
+ 'search_service',
'toolbar',
'<(EXTERNS_GYP):chrome_send',
'externs',
@@ -68,6 +59,15 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'search_service',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ 'browser_proxy',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'toolbar',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
@@ -76,8 +76,8 @@
'<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp:iron-a11y-announcer-extracted',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted',
- 'action_service',
'browser_proxy',
+ 'search_service',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/md_downloads/manager.html b/chromium/chrome/browser/resources/md_downloads/manager.html
index ef562191652..c8c68366be5 100644
--- a/chromium/chrome/browser/resources/md_downloads/manager.html
+++ b/chromium/chrome/browser/resources/md_downloads/manager.html
@@ -1,17 +1,18 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/cr/ui.html">
<link rel="import" href="chrome://resources/html/cr/ui/command.html">
<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://downloads/action_service.html">
<link rel="import" href="chrome://downloads/browser_proxy.html">
<link rel="import" href="chrome://downloads/constants.html">
<link rel="import" href="chrome://downloads/i18n_setup.html">
<link rel="import" href="chrome://downloads/item.html">
+<link rel="import" href="chrome://downloads/search_service.html">
<link rel="import" href="chrome://downloads/toolbar.html">
<dom-module id="downloads-manager">
@@ -37,20 +38,12 @@
z-index: 1;
}
- #toolbar::after {
- box-shadow: inset 0 5px 6px -3px rgba(0, 0, 0, 0.4);
- content: '';
- display: block;
- height: 6px;
- opacity: 0;
- position: absolute;
- top: 100%;
- transition: opacity 500ms;
- width: 100%;
+ #drop-shadow {
+ @apply(--cr-container-shadow);
}
- :host([has-shadow_]) #toolbar::after {
- opacity: 1;
+ :host([has-shadow_]) #drop-shadow {
+ opacity: var(--cr-container-shadow-max-opacity);
}
#downloads-list {
@@ -95,6 +88,7 @@
<downloads-toolbar id="toolbar" spinner-active="{{spinnerActive_}}"
role="none">
</downloads-toolbar>
+ <div id="drop-shadow"></div>
<iron-list id="downloads-list" items="[[items_]]"
hidden="[[!hasDownloads_]]">
<template>
diff --git a/chromium/chrome/browser/resources/md_downloads/manager.js b/chromium/chrome/browser/resources/md_downloads/manager.js
index f6471eafbb0..3716f45b567 100644
--- a/chromium/chrome/browser/resources/md_downloads/manager.js
+++ b/chromium/chrome/browser/resources/md_downloads/manager.js
@@ -58,8 +58,8 @@ cr.define('downloads', function() {
/** @private {?downloads.BrowserProxy} */
browserProxy_: null,
- /** @private {?downloads.ActionService} */
- actionService_: null,
+ /** @private {?downloads.SearchService} */
+ searchService_: null,
/** @private {!PromiseResolver} */
loaded_: new PromiseResolver,
@@ -67,7 +67,7 @@ cr.define('downloads', function() {
/** @override */
created: function() {
this.browserProxy_ = downloads.BrowserProxy.getInstance();
- this.actionService_ = downloads.ActionService.getInstance();
+ this.searchService_ = downloads.SearchService.getInstance();
},
/** @override */
@@ -95,8 +95,16 @@ cr.define('downloads', function() {
* @private
*/
insertItems_: function(index, list) {
- this.splice.apply(this, ['items_', index, 0].concat(list));
+ // Insert |list| at the given |index| via Array#splice().
+ this.items_.splice.apply(this.items_, [index, 0].concat(list));
this.updateHideDates_(index, index + list.length);
+ this.notifySplices('items_', [{
+ index: index,
+ addedCount: list.length,
+ object: this.items_,
+ type: 'splice',
+ removed: [],
+ }]);
if (this.hasAttribute('loading')) {
this.removeAttribute('loading');
@@ -167,7 +175,7 @@ cr.define('downloads', function() {
const list = this.$['downloads-list'];
if (list.scrollHeight - list.scrollTop - list.offsetHeight <= 100) {
// Approaching the end of the scrollback. Attempt to load more items.
- this.actionService_.loadMore();
+ this.searchService_.loadMore();
}
this.hasShadow_ = list.scrollTop > 0;
},
@@ -181,13 +189,13 @@ cr.define('downloads', function() {
document.addEventListener('canExecute', this.onCanExecute_.bind(this));
document.addEventListener('command', this.onCommand_.bind(this));
- this.actionService_.loadMore();
+ this.searchService_.loadMore();
return this.loaded_.promise;
},
/** @private */
onSearchChanged_: function() {
- this.inSearchMode_ = this.actionService_.isSearching();
+ this.inSearchMode_ = this.searchService_.isSearching();
},
/**
@@ -195,12 +203,22 @@ cr.define('downloads', function() {
* @private
*/
removeItem_: function(index) {
- this.splice('items_', index, 1);
+ let removed = this.items_.splice(index, 1);
this.updateHideDates_(index, index);
+ this.notifySplices('items_', [{
+ index: index,
+ addedCount: 0,
+ object: this.items_,
+ type: 'splice',
+ removed: removed,
+ }]);
this.onListScroll_();
},
/**
+ * Updates whether dates should show for |this.items_[start - end]|. Note:
+ * this method does not trigger template bindings. Use notifySplices() or
+ * after calling this method to ensure items are redrawn.
* @param {number} start
* @param {number} end
* @private
@@ -211,8 +229,7 @@ cr.define('downloads', function() {
if (!current)
continue;
const prev = this.items_[i - 1];
- const hideDate = !!prev && prev.date_string == current.date_string;
- this.set('items_.' + i + '.hideDate', hideDate);
+ current.hideDate = !!prev && prev.date_string == current.date_string;
}
},
@@ -222,8 +239,15 @@ cr.define('downloads', function() {
* @private
*/
updateItem_: function(index, data) {
- this.set('items_.' + index, data);
+ this.items_[index] = data;
this.updateHideDates_(index, index);
+ this.notifySplices('items_', [{
+ index: index,
+ addedCount: 0,
+ object: this.items_,
+ type: 'splice',
+ removed: [],
+ }]);
const list = /** @type {!IronListElement} */ (this.$['downloads-list']);
list.updateSizeForItem(index);
},
diff --git a/chromium/chrome/browser/resources/md_downloads/action_service.html b/chromium/chrome/browser/resources/md_downloads/search_service.html
index 7d59ba9e2f0..f37b195b301 100644
--- a/chromium/chrome/browser/resources/md_downloads/action_service.html
+++ b/chromium/chrome/browser/resources/md_downloads/search_service.html
@@ -1,4 +1,4 @@
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://downloads/i18n_setup.html">
<link rel="import" href="chrome://downloads/browser_proxy.html">
-<script src="chrome://downloads/action_service.js"></script>
+<script src="chrome://downloads/search_service.js"></script>
diff --git a/chromium/chrome/browser/resources/md_downloads/action_service.js b/chromium/chrome/browser/resources/md_downloads/search_service.js
index 67e515c6441..991c35289e9 100644
--- a/chromium/chrome/browser/resources/md_downloads/action_service.js
+++ b/chromium/chrome/browser/resources/md_downloads/search_service.js
@@ -3,8 +3,7 @@
// found in the LICENSE file.
cr.define('downloads', function() {
- // TODO(dpapad): Rename to SearchService.
- class ActionService {
+ class SearchService {
constructor() {
/** @private {!Array<string>} */
this.searchTerms_ = [];
@@ -48,7 +47,7 @@ cr.define('downloads', function() {
* @return {boolean} Whether |searchText| resulted in new search terms.
*/
search(searchText) {
- const searchTerms = ActionService.splitTerms(searchText);
+ const searchTerms = SearchService.splitTerms(searchText);
let sameTerms = searchTerms.length == this.searchTerms_.length;
for (let i = 0; sameTerms && i < searchTerms.length; ++i) {
@@ -65,7 +64,7 @@ cr.define('downloads', function() {
}
}
- cr.addSingletonGetter(ActionService);
+ cr.addSingletonGetter(SearchService);
- return {ActionService: ActionService};
+ return {SearchService: SearchService};
});
diff --git a/chromium/chrome/browser/resources/md_downloads/search_service_unittest.gtestjs b/chromium/chrome/browser/resources/md_downloads/search_service_unittest.gtestjs
new file mode 100644
index 00000000000..190c98e3cd8
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_downloads/search_service_unittest.gtestjs
@@ -0,0 +1,45 @@
+// 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.
+
+/**
+ * @param {!Array<string>} list
+ * @return {string}
+ */
+function str(list) {
+ return JSON.stringify(list);
+}
+
+var SearchServiceUnitTest = class extends testing.Test {
+ /** @override */
+ get extraLibraries() {
+ return [
+ '../../../../ui/webui/resources/js/cr.js',
+ 'browser_proxy.js',
+ 'search_service.js',
+ ];
+ }
+}
+
+TEST_F('SearchServiceUnitTest', 'splitTerms', function() {
+ const SearchService = downloads.SearchService;
+ assertEquals(str([]), str(SearchService.splitTerms('')));
+ assertEquals(str([]), str(SearchService.splitTerms(' ')));
+ assertEquals(str(['a']), str(SearchService.splitTerms('a')));
+ assertEquals(str(['a b']), str(SearchService.splitTerms('a b')));
+ assertEquals(str(['a', 'b']), str(SearchService.splitTerms('a "b"')));
+ assertEquals(str(['a', 'b', 'c']), str(SearchService.splitTerms('a "b" c')));
+ assertEquals(str(['a', 'b b', 'c']),
+ str(SearchService.splitTerms('a "b b" c')));
+});
+
+TEST_F('SearchServiceUnitTest', 'searchWithSimilarTerms', function() {
+ class TestSearchService extends downloads.SearchService {
+ loadMore() { /* No chrome.send() for you! */ }
+ }
+
+ const searchService = new TestSearchService();
+
+ assertTrue(searchService.search('a'));
+ assertFalse(searchService.search('a ')); // Same term + space should no-op.
+});
diff --git a/chromium/chrome/browser/resources/md_downloads/toolbar.html b/chromium/chrome/browser/resources/md_downloads/toolbar.html
index e53051b129c..2985c1d09ed 100644
--- a/chromium/chrome/browser/resources/md_downloads/toolbar.html
+++ b/chromium/chrome/browser/resources/md_downloads/toolbar.html
@@ -1,6 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://downloads/action_service.html">
+<link rel="import" href="chrome://downloads/search_service.html">
<link rel="import" href="chrome://downloads/browser_proxy.html">
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="chrome://resources/html/assert.html">
diff --git a/chromium/chrome/browser/resources/md_downloads/toolbar.js b/chromium/chrome/browser/resources/md_downloads/toolbar.js
index a542050d947..e3a23290305 100644
--- a/chromium/chrome/browser/resources/md_downloads/toolbar.js
+++ b/chromium/chrome/browser/resources/md_downloads/toolbar.js
@@ -69,9 +69,9 @@ cr.define('downloads', function() {
* @private
*/
onSearchChanged_: function(event) {
- const actionService = downloads.ActionService.getInstance();
- if (actionService.search(/** @type {string} */ (event.detail)))
- this.spinnerActive = actionService.isSearching();
+ const searchService = downloads.SearchService.getInstance();
+ if (searchService.search(/** @type {string} */ (event.detail)))
+ this.spinnerActive = searchService.isSearching();
this.updateClearAll_();
},
diff --git a/chromium/chrome/browser/resources/md_extensions/BUILD.gn b/chromium/chrome/browser/resources/md_extensions/BUILD.gn
new file mode 100644
index 00000000000..0d1cd29579f
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/BUILD.gn
@@ -0,0 +1,43 @@
+import("../optimize_webui.gni")
+import("//tools/grit/grit_rule.gni")
+import("//chrome/common/features.gni")
+
+extensions_pak_file = "extensions_resources.pak"
+unpak_folder = "extensions_resources.unpak"
+
+optimize_webui("build") {
+ host = "extensions"
+ html_in_files = [ "extensions.html" ]
+ html_out_files = [ "vulcanized.html" ]
+ input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
+ js_out_files = [ "crisper.js" ]
+
+ deps = [
+ ":unpak",
+ ]
+}
+
+unpak("unpak") {
+ pak_file = extensions_pak_file
+ out_folder = unpak_folder
+
+ deps = [
+ ":flattened_resources",
+ ]
+}
+
+grit("flattened_resources") {
+ source = "extensions_resources.grd"
+
+ # The .grd contains references to generated files.
+ source_is_generated = true
+
+ defines = chrome_grit_defines
+ outputs = [
+ "grit/extensions_resources.h",
+ "grit/extensions_resources_map.cc",
+ "grit/extensions_resources_map.h",
+ extensions_pak_file,
+ ]
+ output_dir = "$root_gen_dir/chrome/browser/resources/md_extensions"
+}
diff --git a/chromium/chrome/browser/resources/md_extensions/code_section.html b/chromium/chrome/browser/resources/md_extensions/code_section.html
index dff22ca8375..e0f7858f689 100644
--- a/chromium/chrome/browser/resources/md_extensions/code_section.html
+++ b/chromium/chrome/browser/resources/md_extensions/code_section.html
@@ -7,11 +7,22 @@
<dom-module id="extensions-code-section">
<template>
<style include="cr-hidden-style">
- #main {
+ :host {
+ display: block;
+ }
+
+ #scroll-container {
border: 1px solid var(--paper-grey-500);
+ height: 100%;
+ overflow: auto;
+ position: relative;
+ }
+
+ #main {
color: var(--paper-grey-800);
display: flex;
font-family: monospace;
+ min-height: 100%;
white-space: pre;
}
@@ -29,7 +40,7 @@
flex-direction: column;
}
- .highlight {
+ #highlight {
background: var(--paper-red-100);
}
@@ -38,18 +49,20 @@
text-align: center;
}
</style>
- <div id="main" hidden$="[[isEmpty(code)]]">
- <div id="line-numbers">
- <span>[[computeLineNumbersContent_(code.*)]]</span>
- </div>
- <div id="source">
- <span>[[code.beforeHighlight]]<!-- No whitespace allowed
- --><span class="highlight" title="[[code.message]]"><!--
- -->[[code.highlight]]<!--
- --></span>[[code.afterHighlight]]</span>
+ <div id="scroll-container" hidden$="[[isEmpty(code)]]">
+ <div id="main">
+ <div id="line-numbers">
+ <span>[[computeLineNumbersContent_(code.*)]]</span>
+ </div>
+ <div id="source">
+ <span>[[code.beforeHighlight]]<!-- No whitespace allowed
+ --><span id="highlight" title="[[code.message]]"><!--
+ -->[[code.highlight]]<!--
+ --></span>[[code.afterHighlight]]</span>
+ </div>
</div>
</div>
<div id="no-code" hidden$="[[!isEmpty(code)]]">[[couldNotDisplayCode]]</div>
</template>
- <script src="chrome://extensions/code_section.js"></script>
+ <script src="code_section.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/code_section.js b/chromium/chrome/browser/resources/md_extensions/code_section.js
index 1ea32d783d0..d2fa2caab58 100644
--- a/chromium/chrome/browser/resources/md_extensions/code_section.js
+++ b/chromium/chrome/browser/resources/md_extensions/code_section.js
@@ -28,6 +28,10 @@ cr.define('extensions', function() {
couldNotDisplayCode: String,
},
+ observers: [
+ 'onHighlightChanged_(code.highlight)',
+ ],
+
/**
* Returns true if no code could be displayed (e.g. because the file could
* not be loaded).
@@ -58,6 +62,15 @@ cr.define('extensions', function() {
textContent += i + '\n';
return textContent;
},
+
+ /** @private */
+ onHighlightChanged_: function() {
+ // Smooth scroll the highlight to roughly the middle.
+ this.$['scroll-container'].scrollTo({
+ top: this.$.highlight.offsetTop - this.clientHeight * 0.5,
+ behavior: 'smooth',
+ });
+ },
});
return {CodeSection: CodeSection};
diff --git a/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
index 7dc433766ce..7689bd4eb76 100644
--- a/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/md_extensions/compiled_resources2.gyp
@@ -14,6 +14,7 @@
{
'target_name': 'detail_view',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
@@ -26,18 +27,28 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'drag_and_drop_handler',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:drag_wrapper',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'drop_overlay',
'dependencies': [
- '<(DEPTH)/chrome/browser/resources/extensions/compiled_resources2.gyp:drag_and_drop_handler',
'<(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/cr/ui/compiled_resources2.gyp:drag_wrapper',
+ 'drag_and_drop_handler',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'error_page',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-menu/compiled_resources2.gyp:paper-menu-extracted',
'<(EXTERNS_GYP):developer_private',
@@ -72,10 +83,10 @@
{
'target_name': 'item_list',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
- '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
'<(EXTERNS_GYP):developer_private',
'item',
],
@@ -95,6 +106,7 @@
{
'target_name': 'keyboard_shortcuts',
'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(EXTERNS_GYP):developer_private',
@@ -102,6 +114,22 @@
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'kiosk_browser_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'kiosk_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+ 'kiosk_browser_proxy',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'load_error',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
@@ -124,6 +152,7 @@
'item_util',
'load_error',
'keyboard_shortcuts',
+ 'kiosk_browser_proxy',
'navigation_helper',
'sidebar',
'toolbar',
@@ -136,6 +165,7 @@
'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:load_time_data',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -152,7 +182,6 @@
{
'target_name': 'pack_dialog',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(EXTERNS_GYP):developer_private',
],
@@ -163,6 +192,7 @@
'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:load_time_data',
'<(EXTERNS_GYP):developer_private',
'<(EXTERNS_GYP):management',
'error_page',
@@ -178,11 +208,19 @@
{
'target_name': 'shortcut_input',
'dependencies': [
- '<(DEPTH)/chrome/browser/resources/extensions/compiled_resources2.gyp:shortcut_util',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(EXTERNS_GYP):developer_private',
+ 'shortcut_util',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'shortcut_util',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -191,7 +229,6 @@
'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',
'navigation_helper',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
@@ -199,7 +236,6 @@
{
'target_name': 'toolbar',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
],
diff --git a/chromium/chrome/browser/resources/md_extensions/detail_view.html b/chromium/chrome/browser/resources/md_extensions/detail_view.html
index 3a23f8a31c0..c66a6a5eb6d 100644
--- a/chromium/chrome/browser/resources/md_extensions/detail_view.html
+++ b/chromium/chrome/browser/resources/md_extensions/detail_view.html
@@ -1,9 +1,11 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_tooltip_icon.html">
<link rel="import" href="chrome://resources/html/action_link.html">
<link rel="import" href="chrome://resources/html/action_link_css.html">
@@ -13,18 +15,18 @@
<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-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://extensions/item_util.html">
-<link rel="import" href="chrome://extensions/navigation_helper.html">
+<link rel="import" href="strings.html">
+<link rel="import" href="item_util.html">
+<link rel="import" href="navigation_helper.html">
<dom-module id="extensions-detail-view">
<template>
- <style include=
- "iron-flex cr-hidden-style cr-icons action-link paper-toggle-style">
+ <style include="iron-flex cr-shared-style cr-icons action-link
+ paper-button-style">
:host {
--iron-icon-fill-color: var(--paper-grey-600);
display: block;
height: 100%;
- overflow: auto;
}
#enable-section {
@@ -35,6 +37,11 @@
-webkit-margin-end: 20px;
}
+ #container {
+ height: 100%;
+ overflow: overlay;
+ }
+
#main {
background-color: white;
margin: auto;
@@ -44,9 +51,7 @@
#top-bar {
align-items: center;
- color: var(--paper-grey-700);
display: flex;
- font-size: 14px;
height: 40px;
margin-bottom: 12px;
padding: 8px 12px 0;
@@ -61,6 +66,7 @@
#name {
flex-grow: 1;
+ @apply(--cr-title-text);
}
.control-line {
@@ -88,6 +94,11 @@
border-top: none;
}
+ .section.continuation.warning {
+ padding-left: 21px;
+ padding-right: 8px;
+ }
+
.section:first-child {
border: none;
}
@@ -111,146 +122,210 @@
width: auto; /* override the default button size of 24x24 */
}
+ .warning .action-button {
+ background: white;
+ color: var(--google-blue-500);
+ margin-left: 14px;
+ width: 78px;
+ }
+
+ .warning div {
+ display: flex;
+ }
+
+ .warning span {
+ color: var(--paper-red-700);
+ width: 484px;
+ }
+
+ .warning-icon {
+ --iron-icon-fill-color: var(--paper-red-700);
+ --iron-icon-height: 19px;
+ --iron-icon-width: 19px;
+ margin-right: 16px;
+ }
+
ul {
-webkit-padding-start: 20px;
margin: 0;
}
+
+ #remove-extension {
+ width: 100%;
+ }
</style>
- <div id="main">
- <div id="top-bar">
- <button id="close-button" is="paper-icon-button-light"
- class="icon-arrow-back no-overlap"
- on-tap="onCloseButtonTap_"></button>
- <img alt="" id="icon" src="[[data.iconUrl]]">
- <span id="name">[[data.name]]</span>
- </div>
- <div class="section continuation" id="enable-section">
- <div class="control-line">
- <span>[[computeEnabledText_(data.*)]]</span>
- <div class="layout horizontal">
- <cr-tooltip-icon hidden$="[[!data.controlledInfo]]"
- tooltip-text="[[data.controlledInfo.text]]"
- icon-class="[[getIndicatorIcon_(data.controlledInfo.type)]]"
- icon-aria-label="[[data.controlledInfo.type]]">
- </cr-tooltip-icon>
- <paper-toggle-button id="enable-toggle"
- checked="[[isEnabled_(data.state)]]"
- on-change="onEnableChange_"
- disabled="[[!isEnableToggleEnabled_(data.*)]]">
- </paper-toggle-button>
+ <div id="container">
+ <div id="main">
+ <div id="top-bar">
+ <button id="close-button" is="paper-icon-button-light"
+ class="icon-arrow-back no-overlap"
+ on-tap="onCloseButtonTap_"></button>
+ <img alt="" id="icon" src="[[data.iconUrl]]">
+ <span id="name">[[data.name]]</span>
+ </div>
+ <div class="section continuation" id="enable-section">
+ <div class="control-line">
+ <span>[[computeEnabledText_(data.*)]]</span>
+ <div class="layout horizontal">
+ <cr-tooltip-icon hidden$="[[!data.controlledInfo]]"
+ tooltip-text="[[data.controlledInfo.text]]"
+ icon-class="[[getIndicatorIcon_(data.controlledInfo.type)]]"
+ icon-aria-label="[[data.controlledInfo.type]]">
+ </cr-tooltip-icon>
+ <cr-toggle id="enable-toggle"
+ checked="[[isEnabled_(data.state)]]"
+ on-change="onEnableChange_"
+ disabled="[[!isEnableToggleEnabled_(data.*)]]">
+ </cr-toggle>
+ </div>
</div>
</div>
- </div>
- <div class="section continuation block">
- <div class="section-title">$i18n{itemDescriptionLabel}</div>
- <div class="section-content">[[data.description]]</div>
- </div>
- <div class="section block">
- <div class="section-title">$i18n{itemVersion}</div>
- <div class="section-content">[[data.version]]</div>
- </div>
- <div class="section block" id="id-section" hidden$="[[!inDevMode]]">
- <div class="section-title">$i18n{itemIdHeading}</div>
- <div class="section-content">[[data.id]]</div>
- </div>
- <div class="section" id="inspectable-views" hidden$="[[!inDevMode]]">
- <div class="section-title">$i18n{itemInspectViews}</div>
- <div class="section-content">
- <ul id="inspect-views">
- <template is="dom-repeat" items="[[data.views]]">
- <li>
- <a is="action-link" class="inspectable-view"
- on-tap="onInspectTap_">
- [[computeInspectLabel_(item)]]
- </a>
- </li>
- </template>
- </ul>
+ <div id="warnings" hidden$="[[!hasWarnings_(data.*)]]">
+ <div class="section continuation warning" id="suspicious-warning"
+ hidden$="[[!data.disableReasons.suspiciousInstall]]">
+ <div>
+ <iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
+ <span>$i18n{itemSuspiciousInstall}</span>
+ </div>
+ </div>
+ <div class="section continuation warning" id="corrupted-warning"
+ hidden$="[[!data.disableReasons.corruptInstall]]">
+ <div>
+ <iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
+ <span>$i18n{itemCorruptInstall}</span>
+ </div>
+ <paper-button id="repair-button" class="action-button"
+ on-tap="onRepairTap_">
+ $i18n{itemRepair}
+ </paper-button>
+ </div>
+ <div class="section continuation warning" id="blacklisted-warning"
+ hidden$="[[!data.blacklistText]]">
+ <div>
+ <iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
+ <span>[[data.blacklistText]]</span>
+ </div>
+ </div>
+ <div class="section continuation warning" id="update-required-warning"
+ hidden$="[[!data.disableReasons.updateRequired]]">
+ <div>
+ <iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
+ <span>$i18n{updateRequiredByPolicy}</span>
+ </div>
+ </div>
</div>
- </div>
- <div class="section block">
- <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 class="section continuation block">
+ <div class="section-title">$i18n{itemDescriptionLabel}</div>
+ <div class="section-content">[[data.description]]</div>
</div>
- </div>
- <template is="dom-if"
- if="[[hasDependentExtensions_(data.dependentExtensions.splices)]]">
<div class="section block">
- <div class="section-title">$i18n{itemDependencies}</div>
+ <div class="section-title">$i18n{itemVersion}</div>
+ <div class="section-content">[[data.version]]</div>
+ </div>
+ <div class="section block" id="id-section" hidden$="[[!inDevMode]]">
+ <div class="section-title">$i18n{itemIdHeading}</div>
+ <div class="section-content">[[data.id]]</div>
+ </div>
+ <div class="section" id="inspectable-views" hidden$="[[!inDevMode]]">
+ <div class="section-title">$i18n{itemInspectViews}</div>
<div class="section-content">
- <ul id="dependent-extensions-list">
- <template is="dom-repeat" items="[[data.dependentExtensions]]">
- <li>[[computeDependentEntry_(item)]]</li>
+ <ul id="inspect-views">
+ <template is="dom-repeat" items="[[data.views]]">
+ <li>
+ <a is="action-link" class="inspectable-view"
+ on-tap="onInspectTap_">
+ [[computeInspectLabel_(item)]]
+ </a>
+ </li>
</template>
</ul>
</div>
</div>
- </template>
- <template is="dom-if" if="[[shouldShowOptionsSection_(data.*)]]">
- <div class="section">
- <template is="dom-if" if="[[data.incognitoAccess.isEnabled]]">
- <div class="control-line">
- <span>$i18n{itemAllowIncognito}</span>
- <paper-toggle-button id="allow-incognito"
- checked="[[data.incognitoAccess.isActive]]"
- on-change="onAllowIncognitoChange_"></paper-toggle-button>
- </div>
- </template>
- <template is="dom-if" if="[[data.fileAccess.isEnabled]]">
- <div class="control-line">
- <span>$i18n{itemAllowOnFileUrls}</span>
- <paper-toggle-button id="allow-on-file-urls"
- checked="[[data.fileAccess.isActive]]"
- on-change="onAllowOnFileUrlsChange_"></paper-toggle-button>
- </div>
- </template>
- <template is="dom-if" if="[[data.runOnAllUrls.isEnabled]]">
- <div class="control-line">
- <span>$i18n{itemAllowOnAllSites}</span>
- <paper-toggle-button id="allow-on-all-sites"
- checked="[[data.runOnAllUrls.isActive]]"
- on-change="onAllowOnAllSitesChange_"></paper-toggle-button>
- </div>
- </template>
- <template is="dom-if" if="[[data.errorCollection.isEnabled]]">
- <div class="control-line">
- <span>$i18n{itemCollectErrors}</span>
- <paper-toggle-button id="collect-errors"
- checked="[[data.errorCollection.isActive]]"
- on-change="onCollectErrorsChange_"></paper-toggle-button>
- </div>
- </template>
+ <div class="section block">
+ <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>
- <div class="section"
- hidden$="[[!shouldShowOptionsLink_(data.*)]]">
- <div class="control-line actionable" id="extensions-options"
- on-tap="onOptionsTap_">
- <span>$i18n{itemOptions}</span>
- <button class="icon-external" is="paper-icon-button-light"></button>
+ <template is="dom-if"
+ if="[[hasDependentExtensions_(data.dependentExtensions.splices)]]">
+ <div class="section block">
+ <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">
+ <template is="dom-if" if="[[data.incognitoAccess.isEnabled]]">
+ <div class="control-line">
+ <span>$i18n{itemAllowIncognito}</span>
+ <cr-toggle id="allow-incognito"
+ checked="[[data.incognitoAccess.isActive]]"
+ on-change="onAllowIncognitoChange_"></cr-toggle>
+ </div>
+ </template>
+ <template is="dom-if" if="[[data.fileAccess.isEnabled]]">
+ <div class="control-line">
+ <span>$i18n{itemAllowOnFileUrls}</span>
+ <cr-toggle id="allow-on-file-urls"
+ checked="[[data.fileAccess.isActive]]"
+ on-change="onAllowOnFileUrlsChange_"></cr-toggle>
+ </div>
+ </template>
+ <template is="dom-if" if="[[data.runOnAllUrls.isEnabled]]">
+ <div class="control-line">
+ <span>$i18n{itemAllowOnAllSites}</span>
+ <cr-toggle id="allow-on-all-sites"
+ checked="[[data.runOnAllUrls.isActive]]"
+ on-change="onAllowOnAllSitesChange_"></cr-toggle>
+ </div>
+ </template>
+ <template is="dom-if" if="[[data.errorCollection.isEnabled]]">
+ <div class="control-line">
+ <span>$i18n{itemCollectErrors}</span>
+ <cr-toggle id="collect-errors"
+ checked="[[data.errorCollection.isActive]]"
+ on-change="onCollectErrorsChange_"></cr-toggle>
+ </div>
+ </template>
+ </div>
+ </template>
+ <div class="section"
+ hidden$="[[!shouldShowOptionsLink_(data.*)]]">
+ <div class="control-line actionable" id="extensions-options"
+ on-tap="onOptionsTap_">
+ <span>$i18n{itemOptions}</span>
+ <button class="icon-external" is="paper-icon-button-light"></button>
+ </div>
</div>
- </div>
- <button is="cr-link-row" hidden="[[isControlled_(data.controlledInfo)]]"
- icon-class="subpage-arrow" id="remove-extension"
- label="$i18n{itemRemoveExtension}" on-tap="onRemoveTap_">
- </button>
- <div class="section block">
- <div class="section-title">$i18n{itemSource}</div>
- <div class="section-content">
- [[computeSourceString_(data.*)]]
+ <button class="hr" is="cr-link-row"
+ hidden="[[isControlled_(data.controlledInfo)]]"
+ icon-class="subpage-arrow" id="remove-extension"
+ label="$i18n{itemRemoveExtension}" on-tap="onRemoveTap_">
+ </button>
+ <div class="section block">
+ <div class="section-title">$i18n{itemSource}</div>
+ <div class="section-content">
+ [[computeSourceString_(data.*)]]
+ </div>
</div>
</div>
</div>
</template>
- <script src="chrome://extensions/detail_view.js"></script>
+ <script src="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
index 0ea6870e448..9f7ab51e2db 100644
--- a/chromium/chrome/browser/resources/md_extensions/detail_view.js
+++ b/chromium/chrome/browser/resources/md_extensions/detail_view.js
@@ -8,7 +8,7 @@ cr.define('extensions', function() {
const DetailView = Polymer({
is: 'extensions-detail-view',
- behaviors: [I18nBehavior],
+ behaviors: [I18nBehavior, CrContainerShadowBehavior],
properties: {
/**
@@ -71,6 +71,16 @@ cr.define('extensions', function() {
},
/**
+ * @return {boolean}
+ * @private
+ */
+ hasWarnings_: function() {
+ return this.data.disableReasons.corruptInstall ||
+ this.data.disableReasons.suspiciousInstall ||
+ this.data.disableReasons.updateRequired || !!this.data.blacklistText;
+ },
+
+ /**
* @return {string}
* @private
*/
@@ -143,6 +153,11 @@ cr.define('extensions', function() {
},
/** @private */
+ onRepairTap_: function() {
+ this.delegate.repairItem(this.data.id);
+ },
+
+ /** @private */
onAllowIncognitoChange_: function() {
this.delegate.setItemAllowedIncognito(
this.data.id, this.$$('#allow-incognito').checked);
diff --git a/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.html b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.html
new file mode 100644
index 00000000000..2626f1e7a3f
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="drag_and_drop_handler.js"></script>
diff --git a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.js
index 9643f5ee222..f79bb43cde1 100644
--- a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js
+++ b/chromium/chrome/browser/resources/md_extensions/drag_and_drop_handler.js
@@ -34,7 +34,7 @@ cr.define('extensions', function() {
// not.
// See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p
return !!e.dataTransfer.types &&
- e.dataTransfer.types.indexOf('Files') > -1;
+ e.dataTransfer.types.indexOf('Files') > -1;
},
/** @override */
@@ -61,10 +61,10 @@ cr.define('extensions', function() {
if (e.dataTransfer.files.length != 1)
return;
- var toSend = '';
+ let toSend = '';
// Files lack a check if they're a directory, but we can find out through
// its item entry.
- for (var i = 0; i < e.dataTransfer.items.length; ++i) {
+ for (let i = 0; i < e.dataTransfer.items.length; ++i) {
if (e.dataTransfer.items[i].kind == 'file' &&
e.dataTransfer.items[i].webkitGetAsEntry().isDirectory) {
toSend = 'installDroppedDirectory';
@@ -84,7 +84,7 @@ cr.define('extensions', function() {
}
},
- /** @private */
+ /** @private */
fireDragEnded_: function() {
this.eventTarget_.dispatchEvent(new CustomEvent('extension-drag-ended'));
}
diff --git a/chromium/chrome/browser/resources/md_extensions/drop_overlay.html b/chromium/chrome/browser/resources/md_extensions/drop_overlay.html
index 5e22a036e60..7c6c510578f 100644
--- a/chromium/chrome/browser/resources/md_extensions/drop_overlay.html
+++ b/chromium/chrome/browser/resources/md_extensions/drop_overlay.html
@@ -3,10 +3,9 @@
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/cr/ui/drag_wrapper.html">
-<link rel="import" href="chrome://resources/html/load_time_data.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://extensions/drag_and_drop_handler.html">
+<link rel="import" href="drag_and_drop_handler.html">
<dom-module id="extensions-drop-overlay">
<template>
@@ -40,5 +39,5 @@
<div>$i18n{dropToInstall}</div>
</div>
</template>
- <script src="chrome://extensions/drop_overlay.js"></script>
+ <script src="drop_overlay.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/error_page.html b/chromium/chrome/browser/resources/md_extensions/error_page.html
index b3103aaa277..0ddb9486ee4 100644
--- a/chromium/chrome/browser/resources/md_extensions/error_page.html
+++ b/chromium/chrome/browser/resources/md_extensions/error_page.html
@@ -1,46 +1,75 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/html/cr.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-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-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://extensions/code_section.html">
-<link rel="import" href="chrome://extensions/item_util.html">
-<link rel="import" href="chrome://extensions/navigation_helper.html">
+<link rel="import" href="code_section.html">
+<link rel="import" href="item_util.html">
+<link rel="import" href="navigation_helper.html">
<dom-module id="extensions-error-page">
<template>
- <style include="cr-icons cr-hidden-style">
+ <style include="paper-button-style cr-icons cr-shared-style">
+ :host {
+ display: block;
+ height: 100%;
+ }
+
+ #container {
+ height: 100%;
+ overflow: overlay;
+ }
+
#main {
background-color: white;
- height: 800px;
- width: 90%;
+ margin: auto;
+ min-height: 100%;
+ width: 640px;
+ }
+
+ .section {
+ padding: 0 var(--cr-section-padding);
}
#heading {
- color: var(--paper-grey-600);
height: 40px;
margin-bottom: 30px;
padding: 8px 12px 0;
+ @apply(--cr-title-text);
}
#errors-list {
min-height: 100px;
- padding: 0 10px;
}
.error-item {
- align-items: center;
- color: var(--paper-grey-800);
- display: flex;
- margin: 5px 0;
+ @apply(--cr-section);
+ padding-left: 0;
+ }
+
+ .error-item button[is='paper-icon-button-light'] {
+ -webkit-margin-end: 0;
}
.error-item.selected {
- background-color: #ccc;
+ background-color: rgba(0, 0, 0, 0.08);
+ }
+
+ .error-item .start {
+ align-items: center;
+ align-self: stretch; /* Makes the tappable area fill its parent. */
+ display: flex;
+ flex: 1;
+ padding: 0 var(--cr-section-padding);
}
.error-message {
@@ -60,36 +89,128 @@
.icon-severity-fatal {
content: url(error_severity_fatal.png);
}
+
+ #devtools-controls {
+ padding: 0 var(--cr-section-padding);
+ }
+
+ #stack-trace-heading {
+ @apply(--cr-title-text);
+ align-items: center;
+ display: flex;
+ height: var(--cr-section-min-height);
+ }
+
+ #stack-trace-container {
+ list-style: none;
+ margin-top: 0;
+ padding: 0;
+ }
+
+ #stack-trace-container li {
+ cursor: pointer;
+ font-family: monospace;
+ padding: 4px;
+ }
+
+ #stack-trace-container li.selected,
+ #stack-trace-container li:hover {
+ background: var(--google-blue-100);
+ }
+
+ #dev-tool-button {
+ margin-bottom: 20px;
+ max-width: 300px;
+ }
+
+ extensions-code-section {
+ background: white;
+ height: 200px;
+ }
+
+ /* TODO(scottchen): extract to shared location from settings. */
+ .separator {
+ -webkit-border-start: var(--cr-separator-line);
+ -webkit-margin-end: var(--cr-section-padding);
+ -webkit-margin-start: var(--cr-section-padding);
+ flex-shrink: 0;
+ --separator-gaps: 9px;
+ height: calc(var(--cr-section-min-height) -
+ var(--separator-gaps));
+
+ /**
+ * Makes the tappable area fill its parent.
+ * TODO(scottchen): This is an explicit reminder to override once
+ * .separator styling is extracted from settings.
+ */
+ -webkit-margin-start: 0;
+ }
+
+ /* TODO(scottchen): extract to shared location from settings. */
+ .separator + button[is='paper-icon-button-light'] {
+ -webkit-margin-start: var(--cr-icon-ripple-margin);
+ }
</style>
- <div id="main">
- <div id="heading">
- <button id="close-button" is="paper-icon-button-light"
- class="icon-arrow-back no-overlap" on-tap="onCloseButtonTap_">
- </button>
- <span>$i18n{errorsPageHeading}</span>
- </div>
- <iron-list id="errors-list" items="[[calculateShownItems_(data.*)]]">
- <template>
- <div class$="[[computeErrorClass_(selectedError_, item)]]"
- error="[[item]]"
- tabindex$="[[tabIndex]]"
- on-tap="onErrorItemTap_" on-keydown="onErrorItemKeydown_">
- <img class$="[[computeErrorIconClass_(item)]]">
- <div class="error-message">[[item.message]]</div>
- <button is="paper-icon-button-light" class="icon-delete-gray"
- on-tap="onDeleteErrorTap_" tabindex$="[[tabIndex]]"></button>
- </div>
- </template>
- </iron-list>
- <div id="content-view">
- <extensions-code-section id="code-section"
- could-not-display-code="$i18n{noErrorsToShow}">
- </extensions-code-section>
- </div>
- <div id="devtools-controls">
- <!--TODO-->
+ <div id="container">
+ <div id="main">
+ <div id="heading">
+ <button id="close-button" is="paper-icon-button-light"
+ class="icon-arrow-back no-overlap" on-tap="onCloseButtonTap_">
+ </button>
+ <span>$i18n{errorsPageHeading}</span>
+ </div>
+ <div class="section">
+ <extensions-code-section id="code-section"
+ could-not-display-code="$i18n{noErrorsToShow}">
+ </extensions-code-section>
+ <div id="errors-list">
+ <template is="dom-repeat" items="[[calculateShownItems_(data.*)]]">
+ <div class="item-container">
+ <div class$="error-item [[computeErrorClass_(selectedError_, item)]]">
+ <div class="start" on-tap="onErrorItemAction_"
+ on-keydown="onErrorItemAction_" tabindex="0">
+ <img class$="[[computeErrorIconClass_(item)]]">
+ <div class="error-message">[[item.message]]</div>
+ <cr-expand-button hidden="[[!computeIsRuntimeError_(item)]]"
+ expanded="[[isEqual_(selectedError_, item)]]"
+ tab-index="-1">
+ </cr-expand-button>
+ </div>
+ <div class="separator"></div>
+ <button is="paper-icon-button-light" class="icon-delete-gray"
+ on-tap="onDeleteErrorAction_"
+ on-keydown="onDeleteErrorAction_">
+ </button>
+ </div>
+ <template is="dom-if" if="[[computeIsRuntimeError_(item)]]">
+ <iron-collapse opened="[[isEqual_(selectedError_, item)]]">
+ <div id="devtools-controls">
+ <div id="stack-trace-heading">
+ $i18n{stackTrace}
+ </div>
+ <ul id="stack-trace-container">
+ <template is="dom-repeat" items="[[item.stackTrace]]">
+ <li on-tap="onStackFrameTap_"
+ hidden="[[!shouldDisplayFrame_(item.url)]]"
+ class$="[[getStackFrameClass_(item, selectedStackFrame_)]]">
+ [[getStackTraceLabel_(item)]]
+ </li>
+ </template>
+ </ul>
+ <paper-button id="dev-tool-button" class="action-button"
+ disabled="[[!item.canInspect]]"
+ on-tap="onDevToolButtonTap_">
+ $i18n{openInDevtool}
+ </paper-button>
+ </div>
+ </iron-collapse>
+ </template>
+ </div>
+ </template>
+ </iron-list>
+ </div>
</div>
</div>
</template>
- <script src="chrome://extensions/error_page.js"></script>
+ <script src="error_page.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/error_page.js b/chromium/chrome/browser/resources/md_extensions/error_page.js
index 01bcf79e3cf..113561d6018 100644
--- a/chromium/chrome/browser/resources/md_extensions/error_page.js
+++ b/chromium/chrome/browser/resources/md_extensions/error_page.js
@@ -11,26 +11,43 @@ cr.define('extensions', function() {
'use strict';
/** @interface */
- const ErrorPageDelegate = function() {};
-
- ErrorPageDelegate.prototype = {
+ class ErrorPageDelegate {
/**
* @param {string} extensionId
- * @param {!Array<number>=} opt_errorIds
- * @param {chrome.developerPrivate.ErrorType=} opt_type
+ * @param {!Array<number>=} errorIds
+ * @param {chrome.developerPrivate.ErrorType=} type
*/
- deleteErrors: assertNotReached,
+ deleteErrors(extensionId, errorIds, type) {}
/**
* @param {chrome.developerPrivate.RequestFileSourceProperties} args
* @return {!Promise<!chrome.developerPrivate.RequestFileSourceResponse>}
*/
- requestFileSource: assertNotReached,
- };
+ requestFileSource(args) {}
+
+ /**
+ * @param {!chrome.developerPrivate.OpenDevToolsProperties} args
+ */
+ openDevTools(args) {}
+ }
+
+ /**
+ * Get the URL relative to the main extension url. If the url is
+ * unassociated with the extension, this will be the full url.
+ * @param {string} url
+ * @param {?(ManifestError|RuntimeError)} error
+ * @return {string}
+ */
+ function getRelativeUrl(url, error) {
+ const fullUrl = 'chrome-extension://' + error.extensionId + '/';
+ return url.startsWith(fullUrl) ? url.substring(fullUrl.length) : url;
+ }
const ErrorPage = Polymer({
is: 'extensions-error-page',
+ behaviors: [CrContainerShadowBehavior],
+
properties: {
/** @type {!chrome.developerPrivate.ExtensionInfo|undefined} */
data: Object,
@@ -40,6 +57,14 @@ cr.define('extensions', function() {
/** @private {?(ManifestError|RuntimeError)} */
selectedError_: Object,
+
+ /** @private {?chrome.developerPrivate.StackFrame}*/
+ selectedStackFrame_: {
+ type: Object,
+ value: function() {
+ return null;
+ },
+ },
},
observers: [
@@ -54,9 +79,8 @@ cr.define('extensions', function() {
*/
observeDataChanges_: function() {
assert(this.data);
- const e = this.data.manifestErrors[0] || this.data.runtimeErrors[0];
- if (e)
- this.selectedError_ = e;
+ this.selectedError_ =
+ this.data.manifestErrors[0] || this.data.runtimeErrors[0] || null;
},
/**
@@ -98,14 +122,16 @@ cr.define('extensions', function() {
},
/**
- * @param {!Event} event
+ * @param {!Event} e
* @private
*/
- onDeleteErrorTap_: function(event) {
- // TODO(devlin): It would be cleaner if we could cast this to a
- // PolymerDomRepeatEvent-type thing, but that doesn't exist yet.
- const e = /** @type {!{model:Object}} */ (event);
- this.delegate.deleteErrors(this.data.id, [e.model.item.id]);
+ onDeleteErrorAction_: function(e) {
+ if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter')))
+ return;
+
+ this.delegate.deleteErrors(
+ this.data.id, [(/** @type {!{model:Object}} */ (e)).model.item.id]);
+ e.stopPropagation();
},
/**
@@ -113,6 +139,11 @@ cr.define('extensions', function() {
* @private
*/
onSelectedErrorChanged_: function() {
+ if (!this.selectedError_) {
+ this.$['code-section'].code = null;
+ return;
+ }
+
const error = this.selectedError_;
const args = {
extensionId: error.extensionId,
@@ -130,6 +161,9 @@ cr.define('extensions', function() {
args.lineNumber = error.stackTrace && error.stackTrace[0] ?
error.stackTrace[0].lineNumber :
0;
+ this.selectedStackFrame_ = error.stackTrace && error.stackTrace[0] ?
+ error.stackTrace[0] :
+ null;
break;
}
this.delegate.requestFileSource(args).then(code => {
@@ -138,6 +172,100 @@ cr.define('extensions', function() {
},
/**
+ * @return {boolean}
+ * @private
+ */
+ computeIsRuntimeError_: function(item) {
+ return item.type == chrome.developerPrivate.ErrorType.RUNTIME;
+ },
+
+ /**
+ * The description is a human-readable summation of the frame, in the
+ * form "<relative_url>:<line_number> (function)", e.g.
+ * "myfile.js:25 (myFunction)".
+ * @param {!chrome.developerPrivate.StackFrame} frame
+ * @return {string}
+ * @private
+ */
+ getStackTraceLabel_: function(frame) {
+ let description = getRelativeUrl(frame.url, this.selectedError_) + ':' +
+ frame.lineNumber;
+
+ if (frame.functionName) {
+ const functionName = frame.functionName == '(anonymous function)' ?
+ loadTimeData.getString('anonymousFunction') :
+ frame.functionName;
+ description += ' (' + functionName + ')';
+ }
+
+ return description;
+ },
+
+ /** @private */
+ getExpandedClass_: function() {
+ return this.stackTraceExpanded_ ? 'expanded' : '';
+ },
+
+ /**
+ * @param {chrome.developerPrivate.StackFrame} frame
+ * @return {string}
+ * @private
+ */
+ getStackFrameClass_: function(frame) {
+ return frame == this.selectedStackFrame_ ? 'selected' : '';
+ },
+
+ /**
+ * This function is used to determine whether or not we want to show a
+ * stack frame. We don't want to show code from internal scripts.
+ * @param {string} url
+ * @return {boolean}
+ * @private
+ */
+ shouldDisplayFrame_: function(url) {
+ // All our internal scripts are in the 'extensions::' namespace.
+ return !/^extensions::/.test(url);
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onStackFrameTap_: function(e) {
+ const frame = (/** @type {!{model:Object}} */ (e)).model.item;
+
+ this.selectedStackFrame_ = frame;
+
+ this.delegate
+ .requestFileSource({
+ extensionId: this.selectedError_.extensionId,
+ message: this.selectedError_.message,
+ pathSuffix: getRelativeUrl(frame.url, this.selectedError_),
+ lineNumber: frame.lineNumber,
+ })
+ .then(code => {
+ this.$['code-section'].code = code;
+ });
+ },
+
+ /** @private */
+ onDevToolButtonTap_: function() {
+ // This guarantees renderProcessId and renderViewId.
+ assert(
+ this.selectedError_.type ==
+ chrome.developerPrivate.ErrorType.RUNTIME);
+ assert(this.selectedStackFrame_);
+
+ this.delegate.openDevTools({
+ renderProcessId: this.selectedError_.renderProcessId,
+ renderViewId: this.selectedError_.renderViewId,
+ url: this.selectedStackFrame_.url,
+ lineNumber: this.selectedStackFrame_.lineNumber || 0,
+ columnNumber: this.selectedStackFrame_.columnNumber || 0,
+ });
+ },
+
+ /**
* Computes the class name for the error item depending on whether its
* the currently selected error.
* @param {!RuntimeError|!ManifestError} selectedError
@@ -146,33 +274,37 @@ cr.define('extensions', function() {
* @private
*/
computeErrorClass_: function(selectedError, error) {
- return selectedError == error ? 'error-item selected' : 'error-item';
+ return selectedError == error ? 'selected' : '';
},
/**
- * Causes the given error to become the currently-selected error.
- * @param {!RuntimeError|!ManifestError} error
+ * @param {!RuntimeError|!ManifestError} selected
+ * @param {!RuntimeError|!ManifestError} current
+ * @return {boolean}
* @private
*/
- selectError_: function(error) {
- this.selectedError_ = error;
+ isEqual_: function(selected, current) {
+ return selected == current;
},
/**
- * @param {!{model: !{item: (!RuntimeError|!ManifestError)}}} e
+ * Causes the given error to become the currently-selected error.
+ * @param {!RuntimeError|!ManifestError} error
* @private
*/
- onErrorItemTap_: function(e) {
- this.selectError_(e.model.item);
+ selectError_: function(error) {
+ this.selectedError_ = error;
},
/**
* @param {!{model: !{item: (!RuntimeError|!ManifestError)}}} e
* @private
*/
- onErrorItemKeydown_: function(e) {
- if (e.key == ' ' || e.key == 'Enter')
- this.selectError_(e.model.item);
+ onErrorItemAction_: function(e) {
+ if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter')))
+ return;
+
+ this.selectError_(e.model.item);
},
});
diff --git a/chromium/chrome/browser/resources/md_extensions/extensions.html b/chromium/chrome/browser/resources/md_extensions/extensions.html
index fb287b7b84f..1428eb4e94f 100644
--- a/chromium/chrome/browser/resources/md_extensions/extensions.html
+++ b/chromium/chrome/browser/resources/md_extensions/extensions.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf8">
<title>$i18n{title}</title>
+<if expr="not optimize_webui">
+ <base href="chrome://extensions">
+</if>
<link rel="import" href="chrome://resources/html/polymer.html">
- <link rel="import" href="chrome://extensions/manager.html">
+ <link rel="import" href="manager.html">
<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
<style>
html {
@@ -16,15 +19,15 @@
height: 100%;
line-height: 154%;
margin: 0;
+ overflow: hidden;
+ width: 100%;
}
</style>
</head>
<body>
<extensions-manager></extensions-manager>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="import" href="chrome://resources/html/load_time_data.html">
- <link rel="import" href="chrome://extensions/strings.html">
- <link rel="import" href="chrome://extensions/service.html">
- <script src="chrome://extensions/extensions.js"></script>
+ <link rel="import" href="service.html">
+ <script src="extensions.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/md_extensions/extensions_resources.grd b/chromium/chrome/browser/resources/md_extensions/extensions_resources.grd
new file mode 100644
index 00000000000..c8d179899b3
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/extensions_resources.grd
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+ <outputs>
+ <output filename="grit/extensions_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="grit/extensions_resources_map.cc"
+ type="resource_file_map_source" />
+ <output filename="grit/extensions_resources_map.h"
+ type="resource_map_header" />
+ <output filename="extensions_resources.pak" type="data_package" />
+ </outputs>
+ <release seq="1">
+ <structures>
+ <structure name="IDR_MD_EXTENSIONS_EXTENSIONS_HTML"
+ file="extensions.html"
+ flattenhtml="true"
+ allowexternalscript="true"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_EXTENSIONS_JS"
+ file="extensions.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_CODE_SECTION_HTML"
+ file="code_section.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_CODE_SECTION_JS"
+ file="code_section.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_DETAIL_VIEW_HTML"
+ file="detail_view.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_DETAIL_VIEW_JS"
+ file="detail_view.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_DRAG_AND_DROP_HANDLER_HTML"
+ file="drag_and_drop_handler.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_DRAG_AND_DROP_HANDLER_JS"
+ file="drag_and_drop_handler.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_DROP_OVERLAY_HTML"
+ file="drop_overlay.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_DROP_OVERLAY_JS"
+ file="drop_overlay.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ERROR_PAGE_HTML"
+ file="error_page.html"
+ flattenhtml="true"
+ allowexternalscript="true"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ERROR_PAGE_JS"
+ file="error_page.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_HTML"
+ file="keyboard_shortcuts.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_KEYBOARD_SHORTCUTS_JS"
+ file="keyboard_shortcuts.js"
+ type="chrome_html" />
+ <if expr="chromeos">
+ <structure name="IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_HTML"
+ file="kiosk_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_KIOSK_BROWSER_PROXY_JS"
+ file="kiosk_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_KIOSK_DIALOG_HTML"
+ file="kiosk_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_KIOSK_DIALOG_JS"
+ file="kiosk_dialog.js"
+ type="chrome_html" />
+ </if>
+ <structure name="IDR_MD_EXTENSIONS_MANAGER_HTML"
+ file="manager.html"
+ type="chrome_html"
+ flattenhtml="true"
+ allowexternalscript="true" />
+ <structure name="IDR_MD_EXTENSIONS_MANAGER_JS"
+ file="manager.js"
+ type="chrome_html"
+ flattenhtml="true" />
+ <structure name="IDR_MD_EXTENSIONS_ICONS_HTML"
+ file="icons.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ITEM_HTML"
+ file="item.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ITEM_JS"
+ file="item.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ITEM_LIST_HTML"
+ file="item_list.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ITEM_LIST_JS"
+ file="item_list.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ITEM_UTIL_HTML"
+ file="item_util.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_ITEM_UTIL_JS"
+ file="item_util.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_LOAD_ERROR_HTML"
+ file="load_error.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_LOAD_ERROR_JS"
+ file="load_error.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_NAVIGATION_HELPER_HTML"
+ file="navigation_helper.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_NAVIGATION_HELPER_JS"
+ file="navigation_helper.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_OPTIONS_DIALOG_HTML"
+ file="options_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_OPTIONS_DIALOG_JS"
+ file="options_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_HTML"
+ file="pack_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_JS"
+ file="pack_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_ALERT_HTML"
+ file="pack_dialog_alert.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_ALERT_JS"
+ file="pack_dialog_alert.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SERVICE_HTML"
+ file="service.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SERVICE_JS"
+ file="service.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SHORTCUT_INPUT_HTML"
+ file="shortcut_input.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SHORTCUT_INPUT_JS"
+ file="shortcut_input.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SHORTCUT_UTIL_HTML"
+ file="shortcut_util.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SHORTCUT_UTIL_JS"
+ file="shortcut_util.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SIDEBAR_HTML"
+ file="sidebar.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_SIDEBAR_JS"
+ file="sidebar.js"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_TOOLBAR_HTML"
+ file="toolbar.html"
+ type="chrome_html"
+ flattenhtml="true"
+ allowexternalscript="true" />
+ <structure name="IDR_MD_EXTENSIONS_TOOLBAR_JS"
+ file="toolbar.js"
+ type="chrome_html"
+ flattenhtml="true" />
+ <structure name="IDR_MD_EXTENSIONS_STRINGS_HTML"
+ file="strings.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_VIEW_MANAGER_HTML"
+ file="view_manager.html"
+ type="chrome_html" />
+ <structure name="IDR_MD_EXTENSIONS_VIEW_MANAGER_JS"
+ file="view_manager.js"
+ type="chrome_html" />
+ </structures>
+ </release>
+</grit>
diff --git a/chromium/chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd b/chromium/chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd
new file mode 100644
index 00000000000..d3cb02311e7
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+ <outputs>
+ <output filename="grit/extensions_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="grit/extensions_resources_map.cc"
+ type="resource_file_map_source" />
+ <output filename="grit/extensions_resources_map.h"
+ type="resource_map_header" />
+ <output filename="extensions_resources.pak" type="data_package" />
+ </outputs>
+ <release seq="1">
+ <includes>
+ <include name="IDR_MD_EXTENSIONS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\md_extensions\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MD_EXTENSIONS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\md_extensions\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
+ </includes>
+ </release>
+</grit>
diff --git a/chromium/chrome/browser/resources/md_extensions/item.html b/chromium/chrome/browser/resources/md_extensions/item.html
index c396d2e4c95..2f35703d131 100644
--- a/chromium/chrome/browser/resources/md_extensions/item.html
+++ b/chromium/chrome/browser/resources/md_extensions/item.html
@@ -1,29 +1,28 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html">
<link rel="import" href="chrome://resources/html/action_link.html">
<link rel="import" href="chrome://resources/html/action_link_css.html">
<link rel="import" href="chrome://resources/html/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/load_time_data.html">
-<link rel="import" href="chrome://extensions/icons.html">
-<link rel="import" href="chrome://extensions/item_util.html">
-<link rel="import" href="chrome://extensions/strings.html">
+<link rel="import" href="icons.html">
+<link rel="import" href="item_util.html">
+<link rel="import" href="strings.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/communication-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
-<link rel="import" href="chrome://extensions/navigation_helper.html">
+<link rel="import" href="navigation_helper.html">
<dom-module id="extensions-item">
<template>
- <style include="iron-flex cr-hidden-style cr-icons action-link paper-button-style paper-toggle-style">
+ <style include=
+ "iron-flex cr-hidden-style cr-icons action-link paper-button-style">
#icon-wrapper {
align-self: flex-start;
display: flex;
@@ -41,21 +40,18 @@
display: flex;
flex-direction: column;
height: 160px;
- width: 400px;
+ width: var(--extensions-card-width, 400px);
}
#card.dev-mode {
height: 208px;
}
- #card.disabled {
- opacity: 0.6;
- }
-
#main {
display: flex;
flex-grow: 1;
padding: 16px 20px 17px;
+ position: relative;
}
#content {
@@ -135,26 +131,33 @@
color: white;
display: none;
margin-top: 8px;
+ max-width: 150px;
opacity: 0.6;
padding: 8px 12px;
- position: absolute;
transform: translateX(-50%); /* Move back 50% of width so that the
text and icon share an x-center. */
}
+ :host-context([dir='rtl']) #source-indicator-text {
+ transform: translateX(50%);
+ }
+
#source-indicator:hover #source-indicator-text {
display: block;
}
- paper-toggle-button {
+ cr-toggle {
-webkit-margin-end: 8px; /* Avoid ripple from overlapping container. */
- cursor: pointer;
}
.action-button {
color: var(--google-blue-500);
}
+ #errors-button {
+ color: var(--google-red-700);
+ }
+
#dev-reload-button {
-webkit-margin-end: 12px;
}
@@ -255,13 +258,13 @@
hidden$="[[!isTerminated_(data.state)]]">
$i18n{itemReload}
</paper-button>
- <paper-toggle-button id="enable-toggle" class="action-button"
+ <cr-toggle id="enable-toggle" class="action-button"
checked="[[isEnabled_(data.state)]]" on-change="onEnableChange_"
disabled="[[!isEnableToggleEnabled_(data.*)]]"
hidden$="[[!showEnableToggle_(data.*)]]">
- </paper-toggle-button>
+ </cr-toggle>
</div>
</div>
</template>
- <script src="chrome://extensions/item.js"></script>
+ <script src="item.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/item.js b/chromium/chrome/browser/resources/md_extensions/item.js
index eb7c4c4ebbf..f76a9fc0c95 100644
--- a/chromium/chrome/browser/resources/md_extensions/item.js
+++ b/chromium/chrome/browser/resources/md_extensions/item.js
@@ -4,57 +4,55 @@
cr.define('extensions', function() {
/** @interface */
- const ItemDelegate = function() {};
-
- ItemDelegate.prototype = {
+ class ItemDelegate {
/** @param {string} id */
- deleteItem: assertNotReached,
+ deleteItem(id) {}
/**
* @param {string} id
* @param {boolean} isEnabled
*/
- setItemEnabled: assertNotReached,
+ setItemEnabled(id, isEnabled) {}
/**
* @param {string} id
* @param {boolean} isAllowedIncognito
*/
- setItemAllowedIncognito: assertNotReached,
+ setItemAllowedIncognito(id, isAllowedIncognito) {}
/**
* @param {string} id
* @param {boolean} isAllowedOnFileUrls
*/
- setItemAllowedOnFileUrls: assertNotReached,
+ setItemAllowedOnFileUrls(id, isAllowedOnFileUrls) {}
/**
* @param {string} id
* @param {boolean} isAllowedOnAllSites
*/
- setItemAllowedOnAllSites: assertNotReached,
+ setItemAllowedOnAllSites(id, isAllowedOnAllSites) {}
/**
* @param {string} id
* @param {boolean} collectsErrors
*/
- setItemCollectsErrors: assertNotReached,
+ setItemCollectsErrors(id, collectsErrors) {}
/**
* @param {string} id
* @param {chrome.developerPrivate.ExtensionView} view
*/
- inspectItemView: assertNotReached,
+ inspectItemView(id, view) {}
/** @param {string} id */
- reloadItem: assertNotReached,
+ reloadItem(id) {}
/** @param {string} id */
- repairItem: assertNotReached,
+ repairItem(id) {}
/** @param {string} id */
- showItemOptionsPage: assertNotReached,
- };
+ showItemOptionsPage(id) {}
+ }
const Item = Polymer({
is: 'extensions-item',
@@ -100,7 +98,6 @@ cr.define('extensions', function() {
assert(this.data);
idElement.innerHTML = this.i18n('itemId', this.data.id);
}
- this.fire('extension-item-size-changed', {item: this.data});
},
/**
@@ -282,11 +279,11 @@ cr.define('extensions', function() {
*/
computeDevReloadButtonHidden_: function() {
// Only display the reload spinner if the extension is unpacked and
- // not terminated (since if it's terminated, we'll show a crashed reload
- // buton).
+ // enabled. There's no point in reloading a disabled extension, and we'll
+ // show a crashed reload buton if it's terminated.
const showIcon =
this.data.location == chrome.developerPrivate.Location.UNPACKED &&
- this.data.state != chrome.developerPrivate.ExtensionState.TERMINATED;
+ this.data.state == chrome.developerPrivate.ExtensionState.ENABLED;
return !showIcon;
},
diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.html b/chromium/chrome/browser/resources/md_extensions/item_list.html
index 78791afb6da..13b0c0bc166 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_list.html
+++ b/chromium/chrome/browser/resources/md_extensions/item_list.html
@@ -1,21 +1,21 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/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://extensions/item.html">
+<link rel="import" href="item.html">
<dom-module id="extensions-item-list">
<template>
- <style include="cr-hidden-style">
- :host {
- @apply(--layout-vertical);
+ <style include="cr-shared-style">
+ #items-container,
+ extensions-item {
+ --extensions-card-width: 400px;
}
- iron-list {
- @apply(--layout-flex);
- margin-top: 18px;
+ #container {
+ height: 100%;
+ overflow: overlay;
}
.empty-list-message {
@@ -26,29 +26,45 @@
text-align: center;
}
- .wrapper {
- padding: 6px;
+ #items-container {
+ --grid-gutter: 12px;
+ --max-columns: 3;
+ display: grid;
+ grid-column-gap: var(--grid-gutter);
+ grid-row-gap: var(--grid-gutter);
+ grid-template-columns: repeat(auto-fill, var(--extensions-card-width));
+ justify-content: center;
+ margin: auto;
+ max-width: calc(var(--extensions-card-width) * var(--max-columns) +
+ var(--grid-gutter) * var(--max-columns));
+ padding: calc(var(--grid-gutter) / 2);
}
- </style>
- <div id="no-items" class="empty-list-message"
- hidden$="[[!shouldShowEmptyItemsMessage_(items.length)]]">
- <span>$i18nRaw{noExtensionsOrApps}</span>
- </div>
- <div id="no-search-results" class="empty-list-message"
- hidden$="[[!shouldShowEmptySearchMessage_(shownItems_.length)]]">
- <span>$i18n{noSearchResults}</span>
- </div>
- <iron-list id="list" items="[[shownItems_]]"
- as="item" grid>
- <template>
- <div class="wrapper">
+ extensions-item {
+ grid-column-start: auto;
+ grid-row-start: auto;
+ }
+ </style>
+ <div id="container">
+ <div class="empty-list-message" hidden="[[!isGuest]]">
+ $i18n{guestModeMessage}
+ </div>
+ <div id="no-items" class="empty-list-message"
+ hidden$="[[!shouldShowEmptyItemsMessage_(items.length)]]">
+ <span>$i18nRaw{noExtensionsOrApps}</span>
+ </div>
+ <div id="no-search-results" class="empty-list-message"
+ hidden$="[[!shouldShowEmptySearchMessage_(shownItems_.length)]]">
+ <span>$i18n{noSearchResults}</span>
+ </div>
+ <div id="items-container">
+ <template is="dom-repeat" items="[[shownItems_]]">
<extensions-item data="[[item]]" delegate="[[delegate]]"
- id="[[item.id]]" in-dev-mode="[[inDevMode]]">
+ in-dev-mode="[[inDevMode]]">
</extensions-item>
- </div>
- </template>
- </iron-list>
+ </template>
+ </div>
+ </div>
</template>
- <script src="chrome://extensions/item_list.js"></script>
+ <script src="item_list.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/item_list.js b/chromium/chrome/browser/resources/md_extensions/item_list.js
index a2a38e15a04..e6cd997e5ea 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_list.js
+++ b/chromium/chrome/browser/resources/md_extensions/item_list.js
@@ -6,7 +6,7 @@ cr.define('extensions', function() {
const ItemList = Polymer({
is: 'extensions-item-list',
- behaviors: [Polymer.IronResizableBehavior],
+ behaviors: [CrContainerShadowBehavior],
properties: {
/** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */
@@ -20,6 +20,8 @@ cr.define('extensions', function() {
value: false,
},
+ isGuest: Boolean,
+
filter: String,
/** @private {Array<!chrome.developerPrivate.ExtensionInfo>} */
@@ -29,22 +31,6 @@ cr.define('extensions', function() {
}
},
- listeners: {
- 'list.extension-item-size-changed': 'itemSizeChanged_',
- 'view-enter-start': 'onViewEnterStart_',
- },
-
- /**
- * Updates the size for a given item.
- * @param {CustomEvent} e
- * @private
- * @suppress {checkTypes} Closure doesn't know $.list is an IronList.
- */
- itemSizeChanged_: function(e) {
- this.$.list.updateSizeForItem(e.detail.item);
- this.fire('resize');
- },
-
/**
* Computes the list of items to be shown.
* @param {Object} changeRecord The changeRecord for |items|.
@@ -53,24 +39,21 @@ cr.define('extensions', function() {
* @private
*/
computeShownItems_: function(changeRecord, filter) {
- return this.items.filter(function(item) {
- return item.name.toLowerCase().includes(this.filter.toLowerCase());
- }, this);
+ const formattedFilter = this.filter.trim().toLowerCase();
+ return this.items.filter(
+ item => item.name.toLowerCase().includes(formattedFilter));
},
+ /** @private */
shouldShowEmptyItemsMessage_: function() {
- return this.items.length === 0;
+ return !this.isGuest && this.items.length === 0;
},
+ /** @private */
shouldShowEmptySearchMessage_: function() {
- return !this.shouldShowEmptyItemsMessage_() &&
+ return !this.isGuest && !this.shouldShowEmptyItemsMessage_() &&
this.shownItems_.length === 0;
},
-
- /** @private */
- onViewEnterStart_: function() {
- this.fire('resize'); // This is needed to correctly render iron-list.
- },
});
return {
diff --git a/chromium/chrome/browser/resources/md_extensions/item_util.html b/chromium/chrome/browser/resources/md_extensions/item_util.html
index 6429c3f459a..8836ce076d2 100644
--- a/chromium/chrome/browser/resources/md_extensions/item_util.html
+++ b/chromium/chrome/browser/resources/md_extensions/item_util.html
@@ -1,4 +1,4 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/load_time_data.html">
-<script src="chrome://extensions/item_util.js"></script>
+<link rel="import" href="strings.html">
+<script src="item_util.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
index 1678a875485..ecde827f4f7 100644
--- a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
+++ b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
@@ -1,19 +1,31 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
-<link rel="import" href="chrome://extensions/shortcut_input.html">
+<link rel="import" href="shortcut_input.html">
<dom-module id="extensions-keyboard-shortcuts">
<template>
- <style include="md-select cr-hidden-style">
+ <style include="md-select cr-shared-style">
+ :host {
+ height: 100%;
+ }
+
+ #container {
+ height: 100%;
+ overflow: overlay;
+ padding-top: 24px;
+ }
+
.shortcut-card {
+ @apply(--cr-primary-text);
@apply(--shadow-elevation-2dp);
background-color: white;
- color: var(--paper-grey-600);
margin: 0 auto 16px auto;
max-width: 928px;
min-width: 600px;
@@ -24,26 +36,35 @@
.command-entry {
align-items: center;
display: flex;
- height: 48px;
+ height: var(--cr-section-min-height);
}
.command-name {
- color: var(--paper-grey-900);
flex: 1;
}
.command-entry .md-select-wrapper {
- -webkit-margin-start: 40px;
+ -webkit-margin-start: var(--cr-section-padding);
+ }
+
+ /* Vertically align with paper-input. */
+ .command-entry .md-select {
+ /* TODO(scottchen): line-height needs adjustment to fix large fonts,
+ * same for paper-input. */
+ line-height: 22px;
+ /* Below rules help align md-select and paper-input underline. */
+ margin-top: 3px;
+ padding-bottom: 0;
+ padding-top: 0;
}
.card-title {
align-items: center;
- border-bottom: 1px solid var(--paper-grey-400);
+ border-bottom: var(--cr-separator-line);
display: flex;
- font-size: 14px;
- font-weight: 500;
margin-bottom: 9px;
- padding: 16px 20px;
+ padding: 16px var(--cr-section-padding);
+ @apply(--cr-title-text);
}
.icon {
@@ -58,12 +79,8 @@
-webkit-margin-end: 20px;
-webkit-margin-start: 56px;
}
-
- #main {
- margin-top: 24px;
- }
</style>
- <div id="main">
+ <div id="container">
<template is="dom-repeat" items="[[calculateShownItems_(items.*)]]">
<div class="shortcut-card">
<div class="card-title">
@@ -101,5 +118,5 @@
</template>
</div>
</template>
- <script src="chrome://extensions/keyboard_shortcuts.js"></script>
+ <script src="keyboard_shortcuts.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
index 160e3ce1097..e75b5cecdab 100644
--- a/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
+++ b/chromium/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
@@ -9,6 +9,8 @@ cr.define('extensions', function() {
const KeyboardShortcuts = Polymer({
is: 'extensions-keyboard-shortcuts',
+ behaviors: [CrContainerShadowBehavior],
+
properties: {
/** @type {Array<!chrome.developerPrivate.ExtensionInfo>} */
items: Array,
diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html
new file mode 100644
index 00000000000..58f9bb8fe27
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="kiosk_browser_proxy.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js
new file mode 100644
index 00000000000..91e7a70d4ca
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/kiosk_browser_proxy.js
@@ -0,0 +1,108 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used from the "Kiosk" dialog to interact with
+ * the browser.
+ */
+
+/**
+ * @typedef {{
+ * kioskEnabled: boolean,
+ * autoLaunchEnabled: boolean
+ * }}
+ */
+let KioskSettings;
+
+/**
+ * @typedef {{
+ * id: string,
+ * name: string,
+ * iconURL: string,
+ * autoLaunch: boolean,
+ * isLoading: boolean
+ * }}
+ */
+let KioskApp;
+
+/**
+ * @typedef {{
+ * apps: !Array<!KioskApp>,
+ * disableBailout: boolean,
+ * hasAutoLaunchApp: boolean
+ * }}
+ */
+let KioskAppSettings;
+
+cr.define('extensions', function() {
+
+ /** @interface */
+ class KioskBrowserProxy {
+ /** @param {string} appId */
+ addKioskApp(appId) {}
+
+ /** @param {string} appId */
+ disableKioskAutoLaunch(appId) {}
+
+ /** @param {string} appId */
+ enableKioskAutoLaunch(appId) {}
+
+ /** @return {!Promise<!KioskAppSettings>} */
+ getKioskAppSettings() {}
+
+ /** @return {!Promise<!KioskSettings>} */
+ initializeKioskAppSettings() {}
+
+ /** @param {string} appId */
+ removeKioskApp(appId) {}
+
+ /** @param {boolean} disableBailout */
+ setDisableBailoutShortcut(disableBailout) {}
+ }
+
+ /** @implements {extensions.KioskBrowserProxy} */
+ class KioskBrowserProxyImpl {
+ /** @override */
+ initializeKioskAppSettings() {
+ return cr.sendWithPromise('initializeKioskAppSettings');
+ }
+
+ /** @override */
+ getKioskAppSettings() {
+ return cr.sendWithPromise('getKioskAppSettings');
+ }
+
+ /** @override */
+ addKioskApp(appId) {
+ chrome.send('addKioskApp', [appId]);
+ }
+
+ /** @override */
+ disableKioskAutoLaunch(appId) {
+ chrome.send('disableKioskAutoLaunch', [appId]);
+ }
+
+ /** @override */
+ enableKioskAutoLaunch(appId) {
+ chrome.send('enableKioskAutoLaunch', [appId]);
+ }
+
+ /** @override */
+ removeKioskApp(appId) {
+ chrome.send('removeKioskApp', [appId]);
+ }
+
+ /** @override */
+ setDisableBailoutShortcut(disableBailout) {
+ chrome.send('setDisableBailoutShortcut', [disableBailout]);
+ }
+ }
+
+ cr.addSingletonGetter(KioskBrowserProxyImpl);
+
+ return {
+ KioskBrowserProxy: KioskBrowserProxy,
+ KioskBrowserProxyImpl: KioskBrowserProxyImpl,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.html b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.html
new file mode 100644
index 00000000000..51100a4ec56
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.html
@@ -0,0 +1,144 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.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/util.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-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="kiosk_browser_proxy.html">
+
+<dom-module id="extensions-kiosk-dialog">
+ <template>
+ <style include="cr-shared-style paper-button-style cr-icons">
+ #add-kiosk-app {
+ --paper-input-container-input: {
+ font-size: inherit;
+ };
+ align-items: center;
+ display: flex;
+ margin-bottom: 10px;
+ margin-top: 20px;
+ width: 350px;
+ }
+
+ #add-kiosk-app paper-input {
+ flex: 1;
+ }
+
+ #add-kiosk-app paper-button {
+ -webkit-margin-start: 10px;
+ }
+
+ paper-button {
+ color: var(--google-blue-500);
+ }
+
+ #kiosk-apps-list {
+ border: 1px solid var(--paper-grey-300);
+ padding: 10px;
+ }
+
+ .list-item {
+ align-items: center;
+ border-bottom: 1px solid var(--paper-grey-300);
+ display: flex;
+ justify-content: space-between;
+ padding: 5px;
+ }
+
+ .list-item:last-of-type {
+ border-bottom: none;
+ }
+
+ .list-item:hover {
+ background-color: var(--paper-grey-300);
+ }
+
+ .item-icon {
+ vertical-align: middle;
+ width: 25px;
+ }
+
+ .item-controls {
+ visibility: hidden;
+ }
+
+ .list-item:hover .item-controls {
+ visibility: visible;
+ }
+ </style>
+ <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"
+ ignore-enter-key>
+ <div slot="title">$i18n{manageKioskApp}</div>
+ <div slot="body">
+ <div id="kiosk-apps-list">
+ <template is="dom-repeat" items="[[apps_]]">
+ <div class="list-item">
+ <div class="item-name">
+ <img class="item-icon" src="[[item.iconURL]]">
+ [[item.name]]
+ <span hidden="[[!item.autoLaunch]]">
+ $i18n{kioskAutoLaunch}
+ </span>
+ </div>
+ <div class="item-controls">
+ <paper-button hidden="[[!canEditAutoLaunch_]]"
+ on-tap="onAutoLaunchButtonTap_">
+ [[getAutoLaunchButtonLabel_(item.autoLaunch,
+ '$i18nPolymer{kioskDisableAutoLaunch}',
+ '$i18nPolymer{kioskEnableAutoLaunch}')]]
+ </paper-button>
+ <button is="paper-icon-button-light" class="icon-delete-gray"
+ on-tap="onDeleteAppTap_"></button>
+ </div>
+ </div>
+ </template>
+ </div>
+ <div id="add-kiosk-app">
+ <paper-input id="add-input" label="$i18n{kioskAddApp}"
+ placeholder="$i18n{kioskAddAppHint}" value="{{addAppInput_}}"
+ always-float-label invalid="[[errorAppId_]]"
+ error-message="[[getErrorMessage_(
+ '$i18nPolymer{kioskInvalidApp}', errorAppId_)]]"
+ on-keydown="clearInputInvalid_">
+ </paper-input>
+ <paper-button id="add-button" on-tap="onAddAppTap_"
+ disabled="[[!addAppInput_]]">
+ $i18n{add}
+ </paper-button>
+ </div>
+ <paper-checkbox disabled="[[!canEditBailout_]]"
+ on-pointerdown="onBailoutTap_" checked="[[bailoutDisabled_]]"
+ hidden="[[!canEditAutoLaunch_]]">
+ $i18n{kioskDisableBailout}
+ </paper-checkbox>
+ </div>
+ <div slot="button-container">
+ <paper-button class="action-button" on-tap="onDoneTap_">
+ $i18n{done}
+ </paper-button>
+ </div>
+ </dialog>
+ <dialog is="cr-dialog" id="confirm-dialog" close-text="$i18n{close}"
+ ignore-enter-key on-close="stopPropagation_">
+ <div slot="title">$i18n{kioskDisableBailoutWarningTitle}</div>
+ <div slot="body">$i18n{kioskDisableBailoutWarningBody}</div>
+ <div slot="button-container">
+ <paper-button class="cancel-button" on-tap="onBailoutDialogCancelTap_">
+ $i18n{cancel}
+ </paper-button>
+ <paper-button class="action-button" on-tap="onBailoutDialogConfirmTap_">
+ $i18n{confirm}
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="kiosk_dialog.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.js b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.js
new file mode 100644
index 00000000000..254c2c14d81
--- /dev/null
+++ b/chromium/chrome/browser/resources/md_extensions/kiosk_dialog.js
@@ -0,0 +1,185 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('extensions', function() {
+ 'use strict';
+
+ const KioskDialog = Polymer({
+ is: 'extensions-kiosk-dialog',
+ behaviors: [WebUIListenerBehavior],
+ properties: {
+ /** @private {?string} */
+ addAppInput_: {
+ type: String,
+ value: null,
+ },
+
+ /** @private {!Array<!KioskApp>} */
+ apps_: Array,
+
+ /** @private */
+ bailoutDisabled_: Boolean,
+
+ /** @private */
+ canEditAutoLaunch_: Boolean,
+
+ /** @private */
+ canEditBailout_: Boolean,
+
+ /** @private {?string} */
+ errorAppId_: String,
+ },
+
+ /** @private {?extensions.KioskBrowserProxy} */
+ kioskBrowserProxy_: null,
+
+ /** @override */
+ ready: function() {
+ this.kioskBrowserProxy_ = extensions.KioskBrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ this.kioskBrowserProxy_.initializeKioskAppSettings()
+ .then(params => {
+ this.canEditAutoLaunch_ = params.autoLaunchEnabled;
+ return this.kioskBrowserProxy_.getKioskAppSettings();
+ })
+ .then(this.setSettings_.bind(this));
+
+ this.addWebUIListener(
+ 'kiosk-app-settings-changed', this.setSettings_.bind(this));
+ this.addWebUIListener('kiosk-app-updated', this.updateApp_.bind(this));
+ this.addWebUIListener('kiosk-app-error', this.showError_.bind(this));
+
+ this.$.dialog.showModal();
+ },
+
+ /**
+ * @param {!KioskAppSettings} settings
+ * @private
+ */
+ setSettings_: function(settings) {
+ this.apps_ = settings.apps;
+ this.bailoutDisabled_ = settings.disableBailout;
+ this.canEditBailout_ = settings.hasAutoLaunchApp;
+ },
+
+ /**
+ * @param {!KioskApp} app
+ * @private
+ */
+ updateApp_: function(app) {
+ const index = this.apps_.findIndex(a => a.id == app.id);
+ assert(index < this.apps_.length);
+ this.set('apps_.' + index, app);
+ },
+
+ /**
+ * @param {string} appId
+ * @private
+ */
+ showError_: function(appId) {
+ this.errorAppId_ = appId;
+ },
+
+ /**
+ * @param {string} errorMessage
+ * @return {string}
+ * @private
+ */
+ getErrorMessage_: function(errorMessage) {
+ return this.errorAppId_ + ' ' + errorMessage;
+ },
+
+ /** @private */
+ onAddAppTap_: function() {
+ assert(this.addAppInput_);
+ this.kioskBrowserProxy_.addKioskApp(this.addAppInput_);
+ this.addAppInput_ = null;
+ },
+
+ /** @private */
+ clearInputInvalid_: function() {
+ this.errorAppId_ = null;
+ },
+
+ /**
+ * @param {{model: {item: !KioskApp}}} event
+ * @private
+ */
+ onAutoLaunchButtonTap_: function(event) {
+ const app = event.model.item;
+ if (app.autoLaunch) { // If the app is originally set to
+ // auto-launch.
+ this.kioskBrowserProxy_.disableKioskAutoLaunch(app.id);
+ } else {
+ this.kioskBrowserProxy_.enableKioskAutoLaunch(app.id);
+ }
+ },
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ onBailoutTap_: function(event) {
+ event.preventDefault();
+ if (this.bailoutDisabled_) {
+ this.kioskBrowserProxy_.setDisableBailoutShortcut(false);
+ this.bailoutDisabled_ = false;
+ this.$['confirm-dialog'].close();
+ } else {
+ this.$['confirm-dialog'].showModal();
+ }
+ },
+
+ /** @private */
+ onBailoutDialogCancelTap_: function() {
+ this.$['confirm-dialog'].cancel();
+ },
+
+ /** @private */
+ onBailoutDialogConfirmTap_: function() {
+ this.kioskBrowserProxy_.setDisableBailoutShortcut(true);
+ this.bailoutDisabled_ = true;
+ this.$['confirm-dialog'].close();
+ },
+
+ /** @private */
+ onDoneTap_: function() {
+ this.$.dialog.close();
+ },
+
+ /**
+ * @param {{model: {item: !KioskApp}}} event
+ * @private
+ */
+ onDeleteAppTap_: function(event) {
+ this.kioskBrowserProxy_.removeKioskApp(event.model.item.id);
+ },
+
+ /**
+ * @param {boolean} autoLaunched
+ * @param {string} disableStr
+ * @param {string} enableStr
+ * @return {string}
+ * @private
+ */
+ getAutoLaunchButtonLabel_: function(autoLaunched, disableStr, enableStr) {
+ return autoLaunched ? disableStr : enableStr;
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ stopPropagation_: function(e) {
+ e.stopPropagation();
+ },
+ });
+
+ return {
+ KioskDialog: KioskDialog,
+ };
+});
diff --git a/chromium/chrome/browser/resources/md_extensions/load_error.html b/chromium/chrome/browser/resources/md_extensions/load_error.html
index 1f3212d870a..0d0f1237a5c 100644
--- a/chromium/chrome/browser/resources/md_extensions/load_error.html
+++ b/chromium/chrome/browser/resources/md_extensions/load_error.html
@@ -6,7 +6,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/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://extensions/code_section.html">
+<link rel="import" href="code_section.html">
<dom-module id="extensions-load-error">
<template>
@@ -47,5 +47,5 @@
</div>
</dialog>
</template>
- <script src="chrome://extensions/load_error.js"></script>
+ <script src="load_error.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/load_error.js b/chromium/chrome/browser/resources/md_extensions/load_error.js
index 5d1cc8e98dc..67391a189ff 100644
--- a/chromium/chrome/browser/resources/md_extensions/load_error.js
+++ b/chromium/chrome/browser/resources/md_extensions/load_error.js
@@ -6,15 +6,13 @@ cr.define('extensions', function() {
'use strict';
/** @interface */
- function LoadErrorDelegate() {}
-
- LoadErrorDelegate.prototype = {
+ class LoadErrorDelegate {
/**
* Attempts to load the previously-attempted unpacked extension.
* @param {string} retryId
*/
- retryLoadUnpacked: assertNotReached,
- };
+ retryLoadUnpacked(retryId) {}
+ }
const LoadError = Polymer({
is: 'extensions-load-error',
diff --git a/chromium/chrome/browser/resources/md_extensions/manager.html b/chromium/chrome/browser/resources/md_extensions/manager.html
index 6b401d1dafc..c38263894b1 100644
--- a/chromium/chrome/browser/resources/md_extensions/manager.html
+++ b/chromium/chrome/browser/resources/md_extensions/manager.html
@@ -7,44 +7,43 @@
<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/promise_resolver.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
-<link rel="import" href="chrome://extensions/detail_view.html">
-<link rel="import" href="chrome://extensions/drop_overlay.html">
-<link rel="import" href="chrome://extensions/error_page.html">
-<link rel="import" href="chrome://extensions/item_list.html">
-<link rel="import" href="chrome://extensions/item_util.html">
-<link rel="import" href="chrome://extensions/keyboard_shortcuts.html">
-<link rel="import" href="chrome://extensions/load_error.html">
-<link rel="import" href="chrome://extensions/navigation_helper.html">
-<link rel="import" href="chrome://extensions/options_dialog.html">
-<link rel="import" href="chrome://extensions/pack_dialog.html">
-<link rel="import" href="chrome://extensions/service.html">
-<link rel="import" href="chrome://extensions/sidebar.html">
-<link rel="import" href="chrome://extensions/toolbar.html">
-<link rel="import" href="chrome://extensions/view_manager.html">
+<link rel="import" href="detail_view.html">
+<link rel="import" href="drop_overlay.html">
+<link rel="import" href="error_page.html">
+<link rel="import" href="item_list.html">
+<link rel="import" href="item_util.html">
+<link rel="import" href="keyboard_shortcuts.html">
+<link rel="import" href="load_error.html">
+<link rel="import" href="navigation_helper.html">
+<link rel="import" href="options_dialog.html">
+<link rel="import" href="pack_dialog.html">
+<link rel="import" href="service.html">
+<link rel="import" href="sidebar.html">
+<link rel="import" href="toolbar.html">
+<link rel="import" href="view_manager.html">
<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
+<if expr="chromeos">
+<link rel="import" href="kiosk_browser_proxy.html">
+<link rel="import" href="kiosk_dialog.html">
+</if>
+
<dom-module id="extensions-manager">
<template>
<style include="cr-hidden-style">
:host {
+ display: flex;
+ flex-direction: column;
height: 100%;
}
- #panel {
- --paper-header-panel-standard-container: {
- display: flex;
- };
- }
-
extensions-sidebar {
flex-basis: 256px;
}
#viewManager {
- flex-grow: 1;
- overflow-y: auto;
+ flex: 1;
+ position: relative;
}
extensions-item {
@@ -56,41 +55,52 @@
}
</style>
<extensions-drop-overlay></extensions-drop-overlay>
- <paper-header-panel id="panel">
- <extensions-toolbar class="paper-header" in-dev-mode="[[inDevMode]]"
- on-pack-tap="onPackTap_" delegate="[[delegate]]"
- on-cr-toolbar-menu-tap="onMenuButtonTap_"
- on-search-changed="onFilterChanged_">
- </extensions-toolbar>
- <dialog id="drawer" is="cr-drawer" heading="$i18n{toolbarTitle}">
- <div class="drawer-content">
- <extensions-sidebar id="sidebar"></extensions-sidebar>
- </div>
- </dialog>
- <extensions-view-manager id="viewManager">
- <extensions-item-list id="items-list"
- items="[[itemsList_]]"
- delegate="[[delegate]]" in-dev-mode="[[inDevMode]]"
- filter="[[filter]]" hidden$="[[!didInitPage_]]" slot="view">
- </extensions-item-list>
- <extensions-detail-view id="details-view" delegate="[[delegate]]"
- in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]"
- slot="view">
- </extensions-detail-view>
- <extensions-keyboard-shortcuts id="keyboard-shortcuts"
- items="[[extensions]]" slot="view">
- </extensions-keyboard-shortcuts>
- <extensions-error-page id="error-page"
- data="[[errorPageItem_]]" delegate="[[delegate]]" slot="view">
- </extensions-error-page>
- </extensions-view-manager>
- <extensions-options-dialog id="options-dialog">
- </extensions-options-dialog>
- <extensions-pack-dialog id="pack-dialog" delegate="[[delegate]]">
- </extensions-pack-dialog>
- <extensions-load-error id="load-error" delegate="[[delegate]]">
- </extensions-load-error>
- </paper-header-panel>
+ <extensions-toolbar is-guest="[[isGuest_]]" in-dev-mode="[[inDevMode]]"
+ on-pack-tap="onPackTap_" delegate="[[delegate]]"
+ on-cr-toolbar-menu-tap="onMenuButtonTap_"
+ on-search-changed="onFilterChanged_"
+<if expr="chromeos">
+ on-kiosk-tap="onKioskTap_"
+ kiosk-enabled="[[kioskEnabled_]]"
+</if>
+ >
+ </extensions-toolbar>
+ <dialog id="drawer" is="cr-drawer" heading="$i18n{toolbarTitle}"
+ align="$i18n{textdirection}">
+ <div class="drawer-content">
+ <extensions-sidebar id="sidebar"></extensions-sidebar>
+ </div>
+ </dialog>
+ <extensions-view-manager id="viewManager" role="main">
+ <extensions-item-list id="items-list" items="[[itemsList_]]"
+ delegate="[[delegate]]" in-dev-mode="[[inDevMode]]"
+ filter="[[filter]]" hidden$="[[!didInitPage_]]" slot="view"
+ is-guest="[[isGuest_]]">
+ </extensions-item-list>
+ <extensions-detail-view id="details-view" delegate="[[delegate]]"
+ in-dev-mode="[[inDevMode]]" data="[[detailViewItem_]]"
+ slot="view">
+ </extensions-detail-view>
+ <extensions-keyboard-shortcuts id="keyboard-shortcuts"
+ items="[[extensions]]" slot="view">
+ </extensions-keyboard-shortcuts>
+ <extensions-error-page id="error-page"
+ data="[[errorPageItem_]]" delegate="[[delegate]]" slot="view">
+ </extensions-error-page>
+ </extensions-view-manager>
+ <extensions-options-dialog id="options-dialog">
+ </extensions-options-dialog>
+ <extensions-pack-dialog id="pack-dialog" delegate="[[delegate]]">
+ </extensions-pack-dialog>
+ <extensions-load-error id="load-error" delegate="[[delegate]]">
+ </extensions-load-error>
+<if expr="chromeos">
+ <template is="dom-if" if="[[showKioskDialog_]]" restamp>
+ <extensions-kiosk-dialog id="kiosk-dialog"
+ on-close="onKioskDialogClose_">
+ </extensions-kiosk-dialog>
+ </template>
+</if>
</template>
- <script src="chrome://extensions/manager.js"></script>
-</dom-module> \ No newline at end of file
+ <script src="manager.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/manager.js b/chromium/chrome/browser/resources/md_extensions/manager.js
index 9ac31f6fd5a..eb197cabeb3 100644
--- a/chromium/chrome/browser/resources/md_extensions/manager.js
+++ b/chromium/chrome/browser/resources/md_extensions/manager.js
@@ -35,9 +35,6 @@ cr.define('extensions', function() {
behaviors: [I18nBehavior],
properties: {
- /** @type {extensions.Sidebar} */
- sidebar: Object,
-
/** @type {extensions.Toolbar} */
toolbar: Object,
@@ -45,6 +42,13 @@ cr.define('extensions', function() {
// passed to different elements as different types.
delegate: Object,
+ isGuest_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('isGuest');
+ },
+ },
+
inDevMode: {
type: Boolean,
value: false,
@@ -104,6 +108,20 @@ cr.define('extensions', function() {
type: Boolean,
value: false,
},
+
+ // <if expr="chromeos">
+ /** @private */
+ kioskEnabled_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private */
+ showKioskDialog_: {
+ type: Boolean,
+ value: false,
+ },
+ // </if>
},
/**
@@ -113,19 +131,46 @@ cr.define('extensions', function() {
*/
currentPage_: null,
+ /**
+ * The ID of the listner on |extensions.navigation|. Stored so that the
+ * listener can be removed when this element is detached (happens in tests).
+ * @private {?number}
+ */
+ navigationListener_: null,
+
+ /** @override */
created: function() {
this.readyPromiseResolver = new PromiseResolver();
},
+ /** @override */
ready: function() {
this.toolbar =
/** @type {extensions.Toolbar} */ (this.$$('extensions-toolbar'));
this.readyPromiseResolver.resolve();
- extensions.navigation.onRouteChanged(newPage => {
+
+ // <if expr="chromeos">
+ extensions.KioskBrowserProxyImpl.getInstance()
+ .initializeKioskAppSettings()
+ .then(params => {
+ this.kioskEnabled_ = params.kioskEnabled;
+ });
+ // </if>
+ },
+
+ /** @override */
+ attached: function() {
+ this.navigationListener_ = extensions.navigation.addListener(newPage => {
this.changePage_(newPage);
});
},
+ /** @override */
+ detached: function() {
+ assert(extensions.navigation.removeListener(this.navigationListener_));
+ this.navigationListener_ = null;
+ },
+
get keyboardShortcuts() {
return this.$['keyboard-shortcuts'];
},
@@ -165,7 +210,19 @@ cr.define('extensions', function() {
/** @private */
onMenuButtonTap_: function() {
- this.$.drawer.toggle();
+ this.$.drawer.openDrawer();
+
+ // Sidebar needs manager to inform it of what to highlight since it
+ // has no access to item-specific page.
+ let page = extensions.navigation.getCurrentPage();
+ if (page.extensionId) {
+ // Find out what type of item we're looking at, and replace page info
+ // with that list type.
+ const data = assert(this.getData_(page.extensionId));
+ page = {page: Page.LIST, type: extensions.getItemListType(data)};
+ }
+
+ this.$.sidebar.updateSelected(page);
},
/**
@@ -288,7 +345,7 @@ cr.define('extensions', function() {
*/
changePage_: function(newPage) {
this.$.drawer.closeDrawer();
- if (this.optionsDialog.open)
+ if (this.optionsDialog && this.optionsDialog.open)
this.optionsDialog.close();
const fromPage = this.currentPage_ ? this.currentPage_.page : null;
@@ -298,7 +355,7 @@ cr.define('extensions', function() {
data = assert(this.getData_(newPage.extensionId));
if (newPage.hasOwnProperty('type'))
- this.listType_ = newPage.type;
+ this.listType_ = /** @type {extensions.ShowingType} */ (newPage.type);
if (toPage == Page.DETAILS)
this.detailViewItem_ = assert(data);
@@ -327,6 +384,17 @@ cr.define('extensions', function() {
this.$['pack-dialog'].show();
},
+ // <if expr="chromeos">
+ /** @private */
+ onKioskTap_: function() {
+ this.showKioskDialog_ = true;
+ },
+
+ onKioskDialogClose_: function() {
+ this.showKioskDialog_ = false;
+ },
+ // </if>
+
/**
* @param {!extensions.ShowingType} listType
* @private
diff --git a/chromium/chrome/browser/resources/md_extensions/navigation_helper.html b/chromium/chrome/browser/resources/md_extensions/navigation_helper.html
index 15666da1184..2521c5d5f3f 100644
--- a/chromium/chrome/browser/resources/md_extensions/navigation_helper.html
+++ b/chromium/chrome/browser/resources/md_extensions/navigation_helper.html
@@ -1,3 +1,4 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
-<script src="chrome://extensions/navigation_helper.js"></script>
+<link rel="import" href="strings.html">
+<script src="navigation_helper.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/navigation_helper.js b/chromium/chrome/browser/resources/md_extensions/navigation_helper.js
index 768b9f1aef0..9437730ea02 100644
--- a/chromium/chrome/browser/resources/md_extensions/navigation_helper.js
+++ b/chromium/chrome/browser/resources/md_extensions/navigation_helper.js
@@ -29,27 +29,52 @@ extensions.ShowingType = {
/** @typedef {{page: Page,
extensionId: (string|undefined),
- subpage: (!Dialog|undefined)}} */
+ subpage: (!Dialog|undefined),
+ type: (!extensions.ShowingType|undefined)}} */
let PageState;
cr.define('extensions', function() {
'use strict';
/**
+ * Regular expression that captures the leading slash, the content and the
+ * trailing slash in three different groups.
+ * @const {!RegExp}
+ */
+ const CANONICAL_PATH_REGEX = /(^\/)([\/-\w]+)(\/$)/;
+
+ /**
* A helper object to manage in-page navigations. Since the extensions page
* needs to support different urls for different subpages (like the details
* page), we use this object to manage the history and url conversions.
*/
class NavigationHelper {
constructor() {
- /** @private {!Array<function(!PageState)>} */
- this.listeners_ = [];
+ // Redirect if route not supported.
+ let validPathnames = ['/'];
+ if (!loadTimeData.getBoolean('isGuest')) {
+ validPathnames.push('/shortcuts', '/apps');
+ }
+ if (!validPathnames.includes(this.currentPath_)) {
+ window.history.replaceState(undefined, '', '/');
+ }
+
+ /** @private {number} */
+ this.nextListenerId_ = 1;
+
+ /** @private {!Map<number, function(!PageState)>} */
+ this.listeners_ = new Map();
window.addEventListener('popstate', () => {
this.notifyRouteChanged_(this.getCurrentPage());
});
}
+ /** @private */
+ get currentPath_() {
+ return location.pathname.replace(CANONICAL_PATH_REGEX, '$1$2');
+ }
+
/**
* @return {!PageState} The page that should be displayed for the current
* URL.
@@ -66,10 +91,10 @@ cr.define('extensions', function() {
if (id)
return {page: Page.ERRORS, extensionId: id};
- if (location.pathname == '/shortcuts')
+ if (this.currentPath_ == '/shortcuts')
return {page: Page.SHORTCUTS};
- if (location.pathname == '/apps')
+ if (this.currentPath_ == '/apps')
return {page: Page.LIST, type: extensions.ShowingType.APPS};
return {page: Page.LIST, type: extensions.ShowingType.EXTENSIONS};
@@ -78,9 +103,22 @@ cr.define('extensions', function() {
/**
* Function to add subscribers.
* @param {!function(!PageState)} listener
+ * @return {number} A numerical ID to be used for removing the listener.
*/
- onRouteChanged(listener) {
- this.listeners_.push(listener);
+ addListener(listener) {
+ const nextListenerId = this.nextListenerId_++;
+ this.listeners_.set(nextListenerId, listener);
+ return nextListenerId;
+ }
+
+ /**
+ * Remove a previously registered listener.
+ * @param {number} id
+ * @return {boolean} Whether a listener with the given ID was actually found
+ * and removed.
+ */
+ removeListener(id) {
+ return this.listeners_.delete(id);
}
/**
@@ -88,9 +126,9 @@ cr.define('extensions', function() {
* @private
*/
notifyRouteChanged_(newPage) {
- for (const listener of this.listeners_) {
+ this.listeners_.forEach((listener, id) => {
listener(newPage);
- }
+ });
}
/**
@@ -117,7 +155,7 @@ cr.define('extensions', function() {
let path;
switch (entry.page) {
case Page.LIST:
- if (entry.type && entry.type == extensions.ShowingType.APPS)
+ if (entry.type == extensions.ShowingType.APPS)
path = '/apps';
else
path = '/';
@@ -157,6 +195,8 @@ cr.define('extensions', function() {
const navigation = new NavigationHelper();
return {
+ // Constructor exposed for testing purposes.
+ NavigationHelper: NavigationHelper,
navigation: navigation,
};
});
diff --git a/chromium/chrome/browser/resources/md_extensions/options_dialog.html b/chromium/chrome/browser/resources/md_extensions/options_dialog.html
index e7029bf8c76..8dd57e9fd69 100644
--- a/chromium/chrome/browser/resources/md_extensions/options_dialog.html
+++ b/chromium/chrome/browser/resources/md_extensions/options_dialog.html
@@ -3,7 +3,7 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://extensions/navigation_helper.html">
+<link rel="import" href="navigation_helper.html">
<dom-module id="extensions-options-dialog">
<template>
@@ -40,5 +40,5 @@
</div>
</dialog>
</template>
- <script src="chrome://extensions/options_dialog.js"></script>
+ <script src="options_dialog.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/pack_dialog.html b/chromium/chrome/browser/resources/md_extensions/pack_dialog.html
index c793c6364c8..2e11adbdf66 100644
--- a/chromium/chrome/browser/resources/md_extensions/pack_dialog.html
+++ b/chromium/chrome/browser/resources/md_extensions/pack_dialog.html
@@ -2,6 +2,7 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_input_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
@@ -12,13 +13,10 @@
<dom-module id="extensions-pack-dialog">
<template>
- <style include="cr-shared-style paper-button-style">
+ <style include="cr-shared-style paper-button-style paper-input-style">
.file-input {
align-items: center;
display: flex;
- --paper-input-container-input: {
- font-size: inherit;
- };
}
.file-input paper-input {
@@ -67,5 +65,5 @@
</extensions-pack-dialog-alert>
</template>
</template>
- <script src="chrome://extensions/pack_dialog.js"></script>
+ <script src="pack_dialog.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/pack_dialog.js b/chromium/chrome/browser/resources/md_extensions/pack_dialog.js
index 2f8ac643de5..de6f9b3b2e7 100644
--- a/chromium/chrome/browser/resources/md_extensions/pack_dialog.js
+++ b/chromium/chrome/browser/resources/md_extensions/pack_dialog.js
@@ -6,32 +6,31 @@ cr.define('extensions', function() {
'use strict';
/** @interface */
- function PackDialogDelegate() {}
-
- PackDialogDelegate.prototype = {
+ class PackDialogDelegate {
/**
* Opens a file browser for the user to select the root directory.
* @return {Promise<string>} A promise that is resolved with the path the
* user selected.
*/
- choosePackRootDirectory: assertNotReached,
+ choosePackRootDirectory() {}
/**
* Opens a file browser for the user to select the private key file.
* @return {Promise<string>} A promise that is resolved with the path the
* user selected.
*/
- choosePrivateKeyPath: assertNotReached,
+ choosePrivateKeyPath() {}
/**
* Packs the extension into a .crx.
* @param {string} rootPath
* @param {string} keyPath
* @param {number=} flag
- * @param {function(chrome.developerPrivate.PackDirectoryResponse)=} callback
+ * @param {function(chrome.developerPrivate.PackDirectoryResponse)=}
+ * callback
*/
- packExtension: assertNotReached,
- };
+ packExtension(rootPath, keyPath, flag, callback) {}
+ }
const PackDialog = Polymer({
is: 'extensions-pack-dialog',
diff --git a/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html b/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html
index 81810d8bcad..11db084bd02 100644
--- a/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html
+++ b/chromium/chrome/browser/resources/md_extensions/pack_dialog_alert.html
@@ -29,5 +29,5 @@
</div>
</dialog>
</template>
- <script src="chrome://extensions/pack_dialog_alert.js"></script>
+ <script src="pack_dialog_alert.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/service.html b/chromium/chrome/browser/resources/md_extensions/service.html
index dd8617e16f9..91b8058c5a1 100644
--- a/chromium/chrome/browser/resources/md_extensions/service.html
+++ b/chromium/chrome/browser/resources/md_extensions/service.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://extensions/service.html">
-<link rel="import" href="chrome://extensions/item.html">
-<link rel="import" href="chrome://extensions/navigation_helper.html">
-<script src="chrome://extensions/service.js"></script>
+<link rel="import" href="service.html">
+<link rel="import" href="strings.html">
+<link rel="import" href="item.html">
+<link rel="import" href="navigation_helper.html">
+<script src="service.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/service.js b/chromium/chrome/browser/resources/md_extensions/service.js
index a7c09cb72bf..912dd3e9f54 100644
--- a/chromium/chrome/browser/resources/md_extensions/service.js
+++ b/chromium/chrome/browser/resources/md_extensions/service.js
@@ -29,6 +29,14 @@ cr.define('extensions', function() {
this.manager_ = manager;
this.manager_.set('delegate', this);
+ // Skip any setup or backend requests if we're in guest-mode.
+ // TODO(scottchen): there might be a better place to do this once manager
+ // and service become less coupled.
+ if (loadTimeData.getBoolean('isGuest')) {
+ this.manager_.initPage();
+ return;
+ }
+
const keyboardShortcuts = this.manager_.keyboardShortcuts;
keyboardShortcuts.addEventListener(
'shortcut-updated', this.onExtensionCommandUpdated_.bind(this));
@@ -317,6 +325,11 @@ cr.define('extensions', function() {
});
});
}
+
+ /** @override */
+ openDevTools(args) {
+ chrome.developerPrivate.openDevTools(args);
+ }
}
cr.addSingletonGetter(Service);
diff --git a/chromium/chrome/browser/resources/md_extensions/shortcut_input.html b/chromium/chrome/browser/resources/md_extensions/shortcut_input.html
index 5535af64475..faf98ef6f44 100644
--- a/chromium/chrome/browser/resources/md_extensions/shortcut_input.html
+++ b/chromium/chrome/browser/resources/md_extensions/shortcut_input.html
@@ -2,16 +2,18 @@
<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_input_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.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/i18n_behavior.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-light.html">
-<link rel="import" href="chrome://extensions/shortcut_util.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="shortcut_util.html">
<dom-module id="extensions-shortcut-input">
<template>
- <style include="cr-icons cr-hidden-style">
+ <style include="cr-icons cr-hidden-style paper-input-style">
#main {
position: relative;
width: 200px;
@@ -19,13 +21,10 @@
#input {
--paper-input-container: {
- margin-bottom: 12px;
+ margin-bottom: 0px;
+ margin-top: 2px; /* Offset underline spacing. */
padding: 0;
- };
- --paper-input-container-color: var(--paper-grey-400);
- --paper-input-container-focus-color: var(--google-blue-500);
- --paper-input-container-input: {
- font-size: inherit;
+ @apply(--cr-primary-text);
};
}
@@ -38,7 +37,8 @@
</style>
<div id="main">
<paper-input id="input" placeholder="$i18n{shortcutTypeAShortcut}"
- value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]">
+ value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]"
+ no-label-float>
</paper-input>
<button id="clear" is="paper-icon-button-light"
class="icon-clear no-overlap" on-tap="onClearTap_"
@@ -46,5 +46,5 @@
</button>
</div>
</template>
- <script src="chrome://extensions/shortcut_input.js"></script>
+ <script src="shortcut_input.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/shortcut_input.js b/chromium/chrome/browser/resources/md_extensions/shortcut_input.js
index f2a834ece85..a6abd7b3e75 100644
--- a/chromium/chrome/browser/resources/md_extensions/shortcut_input.js
+++ b/chromium/chrome/browser/resources/md_extensions/shortcut_input.js
@@ -143,9 +143,9 @@ cr.define('extensions', function() {
* @private
*/
computeText_: function() {
- if (this.capturing_)
- return this.pendingShortcut_;
- return this.shortcut;
+ let shortcutString =
+ this.capturing_ ? this.pendingShortcut_ : this.shortcut;
+ return shortcutString.split('+').join(' + ');
},
/**
diff --git a/chromium/chrome/browser/resources/extensions/shortcut_util.html b/chromium/chrome/browser/resources/md_extensions/shortcut_util.html
index 6a187de26c9..e44359faac7 100644
--- a/chromium/chrome/browser/resources/extensions/shortcut_util.html
+++ b/chromium/chrome/browser/resources/md_extensions/shortcut_util.html
@@ -1,3 +1,3 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
-<script src="chrome://extensions/shortcut_util.js"></script>
+<script src="shortcut_util.js"></script>
diff --git a/chromium/chrome/browser/resources/extensions/shortcut_util.js b/chromium/chrome/browser/resources/md_extensions/shortcut_util.js
index 7467307ea94..75f235cedbb 100644
--- a/chromium/chrome/browser/resources/extensions/shortcut_util.js
+++ b/chromium/chrome/browser/resources/md_extensions/shortcut_util.js
@@ -5,10 +5,8 @@
cr.define('extensions', function() {
'use strict';
- /**
- * @enum {number}
- */
- var Key = {
+ /** @enum {number} */
+ const Key = {
Comma: 188,
Del: 46,
Down: 40,
@@ -34,10 +32,7 @@ cr.define('extensions', function() {
* Enum for whether we require modifiers of a keycode.
* @enum {number}
*/
- var ModifierPolicy = {
- NOT_ALLOWED: 0,
- REQUIRED: 1
- };
+ const ModifierPolicy = {NOT_ALLOWED: 0, REQUIRED: 1};
/**
* Gets the ModifierPolicy. Currently only "MediaNextTrack", "MediaPrevTrack",
@@ -67,11 +62,10 @@ cr.define('extensions', function() {
*/
function hasModifier(e, countShiftAsModifier) {
return e.ctrlKey || e.altKey ||
- // Meta key is only relevant on Mac and CrOS, where we treat Command
- // and Search (respectively) as modifiers.
- (cr.isMac && e.metaKey) ||
- (cr.isChromeOS && e.metaKey) ||
- (countShiftAsModifier && e.shiftKey);
+ // Meta key is only relevant on Mac and CrOS, where we treat Command
+ // and Search (respectively) as modifiers.
+ (cr.isMac && e.metaKey) || (cr.isChromeOS && e.metaKey) ||
+ (countShiftAsModifier && e.shiftKey);
}
/**
@@ -82,12 +76,12 @@ cr.define('extensions', function() {
function isValidKeyCode(keyCode) {
if (keyCode == Key.Escape)
return false;
- for (var k in Key) {
+ for (let k in Key) {
if (Key[k] == keyCode)
return true;
}
return (keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) ||
- (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0));
+ (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0));
}
/**
@@ -97,7 +91,7 @@ cr.define('extensions', function() {
* @return {string} The keystroke as a string.
*/
function keystrokeToString(e) {
- var output = [];
+ let output = [];
// TODO(devlin): Should this be i18n'd?
if (cr.isMac && e.metaKey)
output.push('Command');
@@ -110,7 +104,7 @@ cr.define('extensions', function() {
if (e.shiftKey)
output.push('Shift');
- var keyCode = e.keyCode;
+ let keyCode = e.keyCode;
if (isValidKeyCode(keyCode)) {
if ((keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) ||
(keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0))) {
@@ -118,41 +112,59 @@ cr.define('extensions', function() {
} else {
switch (keyCode) {
case Key.Comma:
- output.push('Comma'); break;
+ output.push('Comma');
+ break;
case Key.Del:
- output.push('Delete'); break;
+ output.push('Delete');
+ break;
case Key.Down:
- output.push('Down'); break;
+ output.push('Down');
+ break;
case Key.End:
- output.push('End'); break;
+ output.push('End');
+ break;
case Key.Home:
- output.push('Home'); break;
+ output.push('Home');
+ break;
case Key.Ins:
- output.push('Insert'); break;
+ output.push('Insert');
+ break;
case Key.Left:
- output.push('Left'); break;
+ output.push('Left');
+ break;
case Key.MediaNextTrack:
- output.push('MediaNextTrack'); break;
+ output.push('MediaNextTrack');
+ break;
case Key.MediaPlayPause:
- output.push('MediaPlayPause'); break;
+ output.push('MediaPlayPause');
+ break;
case Key.MediaPrevTrack:
- output.push('MediaPrevTrack'); break;
+ output.push('MediaPrevTrack');
+ break;
case Key.MediaStop:
- output.push('MediaStop'); break;
+ output.push('MediaStop');
+ break;
case Key.PageDown:
- output.push('PageDown'); break;
+ output.push('PageDown');
+ break;
case Key.PageUp:
- output.push('PageUp'); break;
+ output.push('PageUp');
+ break;
case Key.Period:
- output.push('Period'); break;
+ output.push('Period');
+ break;
case Key.Right:
- output.push('Right'); break;
+ output.push('Right');
+ break;
case Key.Space:
- output.push('Space'); break;
+ output.push('Space');
+ break;
case Key.Tab:
- output.push('Tab'); break;
+ output.push('Tab');
+ break;
case Key.Up:
- output.push('Up'); break;
+ output.push('Up');
+ break;
}
}
}
diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.html b/chromium/chrome/browser/resources/md_extensions/sidebar.html
index 030c5c10243..bd1887dd6fd 100644
--- a/chromium/chrome/browser/resources/md_extensions/sidebar.html
+++ b/chromium/chrome/browser/resources/md_extensions/sidebar.html
@@ -50,7 +50,7 @@
width: 15px;
}
</style>
- <paper-menu id="section-menu" selected="0">
+ <paper-menu id="section-menu" selected="{{selected_}}">
<paper-item class="section-item" id="sections-extensions"
on-tap="onExtensionsTap_">
<span>$i18n{sidebarExtensions}</span>
@@ -70,5 +70,5 @@
<button class="open-in-new" is="paper-icon-button-light"></button>
</a>
</template>
- <script src="chrome://extensions/sidebar.js"></script>
+ <script src="sidebar.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/sidebar.js b/chromium/chrome/browser/resources/md_extensions/sidebar.js
index c81d9193804..a2fea0dfc20 100644
--- a/chromium/chrome/browser/resources/md_extensions/sidebar.js
+++ b/chromium/chrome/browser/resources/md_extensions/sidebar.js
@@ -5,7 +5,17 @@ cr.define('extensions', function() {
const Sidebar = Polymer({
is: 'extensions-sidebar',
- behaviors: [I18nBehavior],
+ properties: {
+ /** @private {number} */
+ selected_: {
+ type: Number,
+ value: -1,
+ },
+ },
+
+ hostAttributes: {
+ role: 'navigation',
+ },
/** @private */
onExtensionsTap_: function() {
@@ -23,6 +33,30 @@ cr.define('extensions', function() {
onKeyboardShortcutsTap_: function() {
extensions.navigation.navigateTo({page: Page.SHORTCUTS});
},
+
+ /**
+ * @param {!PageState} state
+ */
+ updateSelected: function(state) {
+ let selected;
+
+ switch (state.page) {
+ case Page.LIST:
+ if (state.type == extensions.ShowingType.APPS)
+ selected = 1;
+ else
+ selected = 0;
+ break;
+ case Page.SHORTCUTS:
+ selected = 2;
+ break;
+ default:
+ selected = -1;
+ break;
+ }
+
+ this.selected_ = selected;
+ },
});
return {Sidebar: Sidebar};
diff --git a/chromium/chrome/browser/resources/md_extensions/strings.html b/chromium/chrome/browser/resources/md_extensions/strings.html
index ada163e717b..cdc7c9b2a5b 100644
--- a/chromium/chrome/browser/resources/md_extensions/strings.html
+++ b/chromium/chrome/browser/resources/md_extensions/strings.html
@@ -1,2 +1,2 @@
<link rel="import" href="chrome://resources/html/load_time_data.html">
-<script src="chrome://extensions/strings.js"></script>
+<script src="strings.js"></script>
diff --git a/chromium/chrome/browser/resources/md_extensions/toolbar.html b/chromium/chrome/browser/resources/md_extensions/toolbar.html
index 20d8d952a80..c57b165e06f 100644
--- a/chromium/chrome/browser/resources/md_extensions/toolbar.html
+++ b/chromium/chrome/browser/resources/md_extensions/toolbar.html
@@ -1,19 +1,18 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.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/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
-<link rel="import" href="chrome://extensions/icons.html">
+<link rel="import" href="icons.html">
<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
<dom-module id="extensions-toolbar">
<template>
- <style include="cr-hidden-style paper-button-style paper-toggle-style">
+ <style include="cr-hidden-style paper-button-style">
:host {
--toolbar-width: 580px;
--toolbar-color: var(--md-toolbar-color);
@@ -25,15 +24,11 @@
}
/* This toggle needs special styling because it's on blue background. */
- cr-toolbar paper-toggle-button {
- --paper-toggle-button-checked-bar: {
- @apply(--cr-toggle-bar-size);
- opacity: 0.5;
- };
- --paper-toggle-button-checked-bar-color: white;
- --paper-toggle-button-checked-button-color: white;
- --paper-toggle-button-checked-ink-color: white;
- --paper-toggle-button-unchecked-ink-color: white;
+ cr-toolbar cr-toggle {
+ --cr-toggle-checked-bar-color: white;
+ --cr-toggle-checked-button-color: white;
+ --cr-toggle-checked-ink-color: white;
+ --cr-toggle-unchecked-ink-color: white;
}
.dev-controls {
@@ -66,16 +61,16 @@
-webkit-margin-end: 16px;
}
</style>
- <cr-toolbar class="paper-header"
- page-name="$i18n{toolbarTitle}"
+ <cr-toolbar page-name="$i18n{toolbarTitle}"
search-prompt="$i18n{search}"
clear-label="$i18n{clearSearch}"
- show-menu>
- <div class="more-actions">
- <span>$i18n{toolbarDevMode}</span>
- <paper-toggle-button id="dev-mode" on-change="onDevModeChange_"
- checked="[[inDevMode]]">
- </paper-toggle-button>
+ menu-label="$i18n{mainMenu}"
+ show-menu="[[!isGuest]]" show-search="[[!isGuest]]">
+ <div class="more-actions" hidden$="[[isGuest]]">
+ <span id="devModeLabel">$i18n{toolbarDevMode}</span>
+ <cr-toggle id="dev-mode" on-change="onDevModeChange_"
+ checked="[[inDevMode]]" aria-labelledby="devModeLabel">
+ </cr-toggle>
</div>
</cr-toolbar>
<div class="dev-controls" hidden$="[[!inDevMode]]">
@@ -89,8 +84,14 @@
<paper-button id="update-now" on-tap="onUpdateNowTap_">
$i18n{toolbarUpdateNow}
</paper-button>
+<if expr="chromeos">
+ <paper-button id="kiosk-extensions" on-tap="onKioskTap_"
+ hidden$="[[!kioskEnabled]]">
+ $i18n{manageKioskApp}
+ </paper-button>
+</if>
</div>
</div>
</template>
- <script src="chrome://extensions/toolbar.js"></script>
+ <script src="toolbar.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/md_extensions/toolbar.js b/chromium/chrome/browser/resources/md_extensions/toolbar.js
index f7e5051491f..f973f10ed3e 100644
--- a/chromium/chrome/browser/resources/md_extensions/toolbar.js
+++ b/chromium/chrome/browser/resources/md_extensions/toolbar.js
@@ -6,21 +6,19 @@ cr.exportPath('extensions');
cr.define('extensions', function() {
/** @interface */
- const ToolbarDelegate = function() {};
-
- ToolbarDelegate.prototype = {
+ class ToolbarDelegate {
/**
* Toggles whether or not the profile is in developer mode.
* @param {boolean} inDevMode
*/
- setProfileInDevMode: assertNotReached,
+ setProfileInDevMode(inDevMode) {}
/** Opens the dialog to load unpacked extensions. */
- loadUnpacked: assertNotReached,
+ loadUnpacked() {}
/** Updates all extensions. */
- updateAllExtensions: assertNotReached,
- };
+ updateAllExtensions() {}
+ }
const Toolbar = Polymer({
is: 'extensions-toolbar',
@@ -35,6 +33,16 @@ cr.define('extensions', function() {
type: Boolean,
value: false,
},
+
+ isGuest: Boolean,
+
+ // <if expr="chromeos">
+ kioskEnabled: Boolean,
+ // </if>
+ },
+
+ hostAttributes: {
+ role: 'banner',
},
/** @private */
@@ -52,6 +60,13 @@ cr.define('extensions', function() {
this.fire('pack-tap');
},
+ // <if expr="chromeos">
+ /** @private */
+ onKioskTap_: function() {
+ this.fire('kiosk-tap');
+ },
+ // </if>
+
/** @private */
onUpdateNowTap_: function() {
this.delegate.updateAllExtensions();
diff --git a/chromium/chrome/browser/resources/md_extensions/view_manager.html b/chromium/chrome/browser/resources/md_extensions/view_manager.html
index 75a6207af57..8b2bf6f82ac 100644
--- a/chromium/chrome/browser/resources/md_extensions/view_manager.html
+++ b/chromium/chrome/browser/resources/md_extensions/view_manager.html
@@ -22,5 +22,5 @@
</style>
<slot name="view"></slot>
</template>
- <script src="chrome://extensions/view_manager.js"></script>
-</dom-module> \ No newline at end of file
+ <script src="view_manager.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/md_feedback/OWNERS b/chromium/chrome/browser/resources/md_feedback/OWNERS
deleted file mode 100644
index 02b5b4649de..00000000000
--- a/chromium/chrome/browser/resources/md_feedback/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-apacible@chromium.org
diff --git a/chromium/chrome/browser/resources/md_feedback/compiled_resources2.gyp b/chromium/chrome/browser/resources/md_feedback/compiled_resources2.gyp
deleted file mode 100644
index a3b6ac3db1f..00000000000
--- a/chromium/chrome/browser/resources/md_feedback/compiled_resources2.gyp
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
- 'targets': [
- {
- 'target_name': 'feedback',
- 'dependencies': [
- '<(EXTERNS_GYP):chrome_send',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
- ],
- 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'feedback_container',
- 'dependencies': [
- '<(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/md_feedback/feedback.html b/chromium/chrome/browser/resources/md_feedback/feedback.html
deleted file mode 100644
index 665dca7b500..00000000000
--- a/chromium/chrome/browser/resources/md_feedback/feedback.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE HTML>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
-<head>
- <meta charset="utf-8">
-
- <link rel="import" href="chrome://resources/html/cr.html">
- <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="import" href="chrome://resources/html/load_time_data.html">
- <link rel="import" href="chrome://resources/html/util.html">
- <script src="chrome://feedback/strings.js"></script>
- <script src="chrome://feedback/feedback.js"></script>
- <link rel="import" href="feedback_container.html">
-</head>
-<body>
- <feedback-container id="container"></feedback-container>
-</body>
-</html> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/md_feedback/feedback.js b/chromium/chrome/browser/resources/md_feedback/feedback.js
deleted file mode 100644
index 895f9933525..00000000000
--- a/chromium/chrome/browser/resources/md_feedback/feedback.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var Feedback = {};
-
-/**
- * API invoked by the browser MdFeedbackWebUIMessageHandler to communicate
- * with this UI.
- */
-Feedback.UI = class {
- /**
- * Populates the feedback form with data.
- *
- * @param {{email: (string|undefined),
- * url: (string|undefined)}} data
- * Parameters in data:
- * email - user's email, if available.
- * url - url of the tab the user was on before triggering feedback.
- */
- static setData(data) {
- $('container').email = data['email'];
- $('container').url = data['url'];
- }
-};
-
-/** API invoked by this UI to communicate with the browser WebUI message
- * handler.
- */
-Feedback.BrowserApi = class {
- /**
- * Requests data to initialize the WebUI with.
- * The data will be returned via Feedback.UI.setData.
- */
- static requestData() {
- chrome.send('requestData');
- }
-};
-
-window.addEventListener('DOMContentLoaded', function() {
- Feedback.BrowserApi.requestData();
-});
diff --git a/chromium/chrome/browser/resources/md_feedback/feedback_container.html b/chromium/chrome/browser/resources/md_feedback/feedback_container.html
deleted file mode 100644
index 2e88d7f6a8d..00000000000
--- a/chromium/chrome/browser/resources/md_feedback/feedback_container.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<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-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-input/paper-textarea.html">
-<dom-module id="feedback-container">
- <template>
- <style>
- #additional-info {
- margin-top: 10px;
- }
-
- #buttons {
- display: -webkit-flex;
- justify-content: flex-end;
- }
-
- #header {
- font-size: 1.25em;
- margin: 12px 0;
- }
-
- paper-button {
- cursor: pointer;
- text-align: center;
- }
-
- paper-checkbox {
- --paper-checkbox-size: 14px;
- }
-
- paper-input,
- paper-textarea {
- --paper-input-container-input: {
- font-size: 1.0em;
- line-height: 1.0em;
- };
- --paper-input-container-label: {
- font-size: 1.0em;
- line-height: 1.0em;
- };
- }
-
- paper-input-container {
- padding: 0;
- }
-
- #submit-button {
- color: var(--paper-blue-700);
- }
- </style>
- <div id="header">
- <span>$i18n{headingText}</span>
- </div>
- <hr>
- <paper-textarea label="$i18n{openEndedLabel}"></paper-textarea>
- <span id="additional-info">$i18n{additionalInfoLabel}</span>
- <paper-input label="$i18n{urlLabel}" value="[[url]]"></paper-input>
- <paper-input label="$i18n{emailLabel}" value="[[email]]"></paper-input>
- <div>
- <paper-checkbox>$i18n{includeScreenshotLabel}</paper-checkbox>
- </div>
- <div>
- <paper-checkbox>$i18n{sendSystemInfoLabel}</paper-checkbox>
- </div>
- <p id="privacyNote"></p>
- <div id="buttons">
- <paper-button>$i18n{cancelButton}</paper-button>
- <paper-button id="submit-button">$i18n{sendReportButton}</paper-button>
- </div>
- </template>
- <script src="feedback_container.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/md_feedback/feedback_container.js b/chromium/chrome/browser/resources/md_feedback/feedback_container.js
deleted file mode 100644
index 05f7dceeb68..00000000000
--- a/chromium/chrome/browser/resources/md_feedback/feedback_container.js
+++ /dev/null
@@ -1,36 +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.
-
-// This Polymer element is used as a container for all the feedback
-// elements. Based on a number of factors, it determines which elements
-// to show and what will be submitted to the feedback servers.
-Polymer({
- is: 'feedback-container',
-
- properties: {
- /**
- * The user's email, if available.
- * @type {string|undefined}
- */
- email: {
- type: String,
- },
-
- /**
- * The URL of the page the user was on before sending feedback.
- * @type {string|undefined}
- */
- url: {
- type: String,
- },
- },
-
- ready: function() {
- // Retrieves the feedback privacy note text, if it exists. On non-official
- // branded builds, the string is not defined.
- this.$.privacyNote.innerHTML = loadTimeData.valueExists('privacyNote') ?
- loadTimeData.getString('privacyNote') :
- '';
- },
-});
diff --git a/chromium/chrome/browser/resources/md_history/BUILD.gn b/chromium/chrome/browser/resources/md_history/BUILD.gn
index 2625f114634..4930d084a37 100644
--- a/chromium/chrome/browser/resources/md_history/BUILD.gn
+++ b/chromium/chrome/browser/resources/md_history/BUILD.gn
@@ -1,6 +1,6 @@
-import("../vulcanize.gni")
+import("../optimize_webui.gni")
-vulcanize("build") {
+optimize_webui("build") {
host = "history"
html_in_files = [
"app.html",
diff --git a/chromium/chrome/browser/resources/md_history/app.html b/chromium/chrome/browser/resources/md_history/app.html
index 36b380fed20..ddd7280cc46 100644
--- a/chromium/chrome/browser/resources/md_history/app.html
+++ b/chromium/chrome/browser/resources/md_history/app.html
@@ -49,19 +49,11 @@
}
#drop-shadow {
- box-shadow: inset 0 5px 6px -3px rgba(0, 0, 0, 0.4);
- height: 6px;
- left: 0;
- opacity: 0;
- pointer-events: none;
- position: absolute;
- right: 0;
- top: 0;
- transition: opacity 500ms;
+ @apply(--cr-container-shadow);
}
:host([toolbar-shadow_]) #drop-shadow {
- opacity: 1;
+ opacity: var(--cr-container-shadow-max-opacity);
}
</style>
<history-query-manager query-state="{{queryState_}}"
@@ -79,12 +71,12 @@
querying="[[queryState_.querying]]"
search-term="[[queryState_.searchTerm]]"
show-menu-promo="[[showMenuPromo_]]"
- show-sync-notice="[[showSyncNotice_(hasSyncedResults, selectedPage_)]]"
spinner-active="[[shouldShowSpinner_(queryState_.querying,
queryState_.incremental,
queryState_.searchTerm)]]">
</history-toolbar>
+ <div id="drop-shadow"></div>
<div id="main-container">
<history-side-bar id="content-side-bar" selected-page="{{selectedPage_}}"
show-footer="[[showSidebarFooter]]"
@@ -109,11 +101,11 @@
</history-synced-device-manager>
</template>
</iron-pages>
- <div id="drop-shadow"></div>
</div>
<template is="cr-lazy-render" id="drawer">
- <dialog is="cr-drawer" heading="$i18n{title}" swipe-open>
+ <dialog is="cr-drawer" heading="$i18n{title}" align="$i18n{textdirection}"
+ swipe-open>
<history-side-bar id="drawer-side-bar" class="drawer-content"
selected-page="{{selectedPage_}}"
show-footer="[[showSidebarFooter]]">
diff --git a/chromium/chrome/browser/resources/md_history/app.js b/chromium/chrome/browser/resources/md_history/app.js
index de2d100abbf..0c25e14061a 100644
--- a/chromium/chrome/browser/resources/md_history/app.js
+++ b/chromium/chrome/browser/resources/md_history/app.js
@@ -76,8 +76,6 @@ Polymer({
// Used to display notices for profile sign-in status.
showSidebarFooter: Boolean,
-
- hasSyncedResults: Boolean,
},
listeners: {
@@ -155,7 +153,6 @@ Polymer({
/** @private */
onCrToolbarMenuTap_: function() {
var drawer = /** @type {!CrDrawerElement} */ (this.$.drawer.get());
- drawer.align = document.documentElement.dir == 'ltr' ? 'left' : 'right';
drawer.toggle();
this.showMenuPromo_ = false;
},
@@ -279,16 +276,6 @@ Polymer({
return querying && !incremental && searchTerm != '';
},
- /**
- * @param {boolean} hasSyncedResults
- * @param {string} selectedPage
- * @return {boolean} Whether the (i) synced results notice should be shown.
- * @private
- */
- showSyncNotice_: function(hasSyncedResults, selectedPage) {
- return hasSyncedResults && selectedPage != 'syncedTabs';
- },
-
/** @private */
selectedPageChanged_: function() {
this.unselectAll();
diff --git a/chromium/chrome/browser/resources/md_history/externs.js b/chromium/chrome/browser/resources/md_history/externs.js
index 590c127b8e3..8f7d7c26978 100644
--- a/chromium/chrome/browser/resources/md_history/externs.js
+++ b/chromium/chrome/browser/resources/md_history/externs.js
@@ -34,7 +34,6 @@ var HistoryEntry;
* chrome/browser/ui/webui/browsing_history_handler.cc:
* BrowsingHistoryHandler::QueryComplete()
* @typedef {{finished: boolean,
- * hasSyncedResults: boolean,
* term: string}}
*/
var HistoryQuery;
diff --git a/chromium/chrome/browser/resources/md_history/history.js b/chromium/chrome/browser/resources/md_history/history.js
index e6c5ff04fea..c9571285a68 100644
--- a/chromium/chrome/browser/resources/md_history/history.js
+++ b/chromium/chrome/browser/resources/md_history/history.js
@@ -52,16 +52,13 @@ function historyResult(info, results) {
/**
* Called by the history backend after receiving results and after discovering
* the existence of other forms of browsing history.
- * @param {boolean} hasSyncedResults Whether there are synced results.
* @param {boolean} includeOtherFormsOfBrowsingHistory Whether to include
* a sentence about the existence of other forms of browsing history.
*/
-function showNotification(
- hasSyncedResults, includeOtherFormsOfBrowsingHistory) {
+function showNotification(includeOtherFormsOfBrowsingHistory) {
waitForAppUpgrade().then(function() {
var app = /** @type {HistoryAppElement} */ ($('history-app'));
app.showSidebarFooter = includeOtherFormsOfBrowsingHistory;
- app.hasSyncedResults = hasSyncedResults;
});
}
diff --git a/chromium/chrome/browser/resources/md_history/history_toolbar.html b/chromium/chrome/browser/resources/md_history/history_toolbar.html
index 2a69ab5a559..12fd39cba14 100644
--- a/chromium/chrome/browser/resources/md_history/history_toolbar.html
+++ b/chromium/chrome/browser/resources/md_history/history_toolbar.html
@@ -37,43 +37,6 @@
cr-toolbar-selection-overlay {
--selection-overlay-max-width: var(--card-max-width);
}
-
- /* Info button and dropdown. */
-
- #info-button {
- /* Additional styles for unresolved <button>. */
- background: none;
- border: none;
- color: inherit;
- height: 32px;
- margin: 6px;
- outline: none;
- padding: 0;
- width: 32px;
- }
-
- #info-button-icon {
- height: 20px;
- width: 20px;
- }
-
- #sync-notice {
- @apply(--shadow-elevation-2dp);
- background-color: white;
- border-radius: 2px;
- color: var(--primary-text-color);
- overflow: hidden;
- padding: 12px 20px;
- position: absolute;
- right: 24px;
- top: 46px;
- z-index: 1;
- }
-
- :host-context([dir=rtl]) #sync-notice {
- left: 24px;
- right: auto;
- }
</style>
<cr-toolbar id="main-toolbar"
page-name="$i18n{title}"
@@ -87,20 +50,7 @@
menu-promo="$i18n{menuPromo}"
close-menu-promo="$i18n{closeMenuPromo}"
on-search-changed="onSearchChanged_">
- <div class="more-actions">
- <template is="dom-if" if="[[showSyncNotice]]">
- <button is="paper-icon-button-light" id="info-button"
- on-click="onInfoButtonTap_"
- aria-label="$i18n{hasSyncedResultsDescription}">
- <iron-icon icon="history:info-outline" id="info-button-icon">
- </iron-icon>
- </button>
- </template>
- </div>
</cr-toolbar>
- <div id="sync-notice" hidden="[[!syncNoticeVisible_]]">
- $i18nRaw{hasSyncedResults}
- </div>
<template is="dom-if" if="[[itemsSelected_]]">
<cr-toolbar-selection-overlay delete-label="$i18n{delete}"
cancel-label="$i18n{cancel}"
diff --git a/chromium/chrome/browser/resources/md_history/history_toolbar.js b/chromium/chrome/browser/resources/md_history/history_toolbar.js
index 62da493f7ab..7b70d8ea149 100644
--- a/chromium/chrome/browser/resources/md_history/history_toolbar.js
+++ b/chromium/chrome/browser/resources/md_history/history_toolbar.js
@@ -41,19 +41,6 @@ Polymer({
reflectToAttribute: true,
},
- // Show an (i) button on the right of the toolbar to display a notice about
- // synced history.
- showSyncNotice: {
- type: Boolean,
- observer: 'showSyncNoticeChanged_',
- },
-
- // Sync notice is currently visible.
- syncNoticeVisible_: {
- type: Boolean,
- value: false,
- },
-
hasMoreResults: Boolean,
querying: Boolean,
@@ -65,27 +52,6 @@ Polymer({
showMenuPromo: Boolean,
},
- /**
- * True if the document currently has listeners to dismiss the sync notice,
- * which are added when the notice is first opened.
- * @private{boolean}
- */
- hasDismissListeners_: false,
-
- /** @private{?function(!Event)} */
- boundOnDocumentClick_: null,
-
- /** @private{?function(!Event)} */
- boundOnDocumentKeydown_: null,
-
- /** @override */
- detached: function() {
- if (this.hasDismissListeners_) {
- document.removeEventListener('click', this.boundOnDocumentClick_);
- document.removeEventListener('keydown', this.boundOnDocumentKeydown_);
- }
- },
-
/** @return {CrToolbarSearchFieldElement} */
get searchField() {
return /** @type {CrToolbarElement} */ (this.$['main-toolbar'])
@@ -125,12 +91,6 @@ Polymer({
}
},
- /** @private */
- showSyncNoticeChanged_: function() {
- if (!this.showSyncNotice)
- this.syncNoticeVisible_ = false;
- },
-
/**
* @param {!CustomEvent} event
* @private
@@ -139,43 +99,6 @@ Polymer({
this.fire('change-query', {search: event.detail});
},
- /**
- * @param {!MouseEvent} e
- * @private
- */
- onInfoButtonTap_: function(e) {
- this.syncNoticeVisible_ = !this.syncNoticeVisible_;
- e.stopPropagation();
-
- if (this.hasDismissListeners_)
- return;
-
- this.boundOnDocumentClick_ = this.onDocumentClick_.bind(this);
- this.boundOnDocumentKeydown_ = this.onDocumentKeydown_.bind(this);
- document.addEventListener('click', this.boundOnDocumentClick_);
- document.addEventListener('keydown', this.boundOnDocumentKeydown_);
-
- this.hasDismissListeners_ = true;
- },
-
- /**
- * @param {!Event} e
- * @private
- */
- onDocumentClick_: function(e) {
- if (e.path.indexOf(this.$['sync-notice']) == -1)
- this.syncNoticeVisible_ = false;
- },
-
- /**
- * @param {!Event} e
- * @private
- */
- onDocumentKeydown_: function(e) {
- if (e.key == 'Escape')
- this.syncNoticeVisible_ = false;
- },
-
/** @private */
numberOfItemsSelected_: function(count) {
return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
diff --git a/chromium/chrome/browser/resources/md_history/icons.html b/chromium/chrome/browser/resources/md_history/icons.html
index 7f0f09a9dfe..2714b83b21f 100644
--- a/chromium/chrome/browser/resources/md_history/icons.html
+++ b/chromium/chrome/browser/resources/md_history/icons.html
@@ -9,7 +9,6 @@
See http://goo.gl/Y1OdAq for instructions on adding additional icons.
-->
<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="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="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>
</defs>
</svg>
diff --git a/chromium/chrome/browser/resources/md_history/shared_style.html b/chromium/chrome/browser/resources/md_history/shared_style.html
index d428ea27f5d..32534a40cca 100644
--- a/chromium/chrome/browser/resources/md_history/shared_style.html
+++ b/chromium/chrome/browser/resources/md_history/shared_style.html
@@ -35,7 +35,6 @@
}
.website-icon {
- -webkit-margin-end: 16px;
background-repeat: no-repeat;
background-size: 16px;
height: 16px;
@@ -43,6 +42,7 @@
}
.website-title {
+ -webkit-margin-start: 16px;
color: var(--primary-text-color);
overflow: hidden;
text-decoration: none;
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 81925027a00..7fb1411e47a 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
@@ -2565,9 +2565,9 @@ Polymer({
firstRunFlowHeight - issueHeight - searchHeight + searchPadding -
sinkListPadding;
- // Limit the height of the dialog to five items, including search.
+ // Limit the height of the dialog to ten items, including search.
var sinkItemHeight = 41;
- var maxSinkItems = hasSearch ? 4 : 5;
+ var maxSinkItems = hasSearch ? 9 : 10;
this.sinkListMaxHeight_ =
Math.min(sinkItemHeight * maxSinkItems, this.sinkListMaxHeight_);
if (sinkList)
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.css b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.css
index c684eb52a1a..3b9b0631cc1 100644
--- a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.css
+++ b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.css
@@ -23,7 +23,7 @@
width: 90%;
}
-:host-context([dir='rtl']) #play-pause-volume-controls {
+:host-context([dir='rtl']) #play-pause-volume-hangouts-controls {
transform: scaleX(-1);
}
@@ -40,7 +40,7 @@
margin: 0 8px;
}
-#play-pause-volume-controls {
+#play-pause-volume-hangouts-controls {
display: block;
margin-top: 13px;
overflow: hidden;
@@ -86,3 +86,26 @@
overflow: hidden;
padding: 0.3em 0;
}
+
+#hangouts-local-present-controls {
+ -webkit-font-smoothing: antialiased;
+ -webkit-tap-highlight-color: transparent;
+ cursor: pointer;
+ display: inline-block;
+ float: right;
+ font-family: 'Roboto', 'Noto', sans-serif;
+ padding-top: 10.5px;
+ white-space: nowrap;
+}
+
+#hangouts-local-present-checkbox {
+ --paper-checkbox-checked-color: #1976D2;
+ --paper-checkbox-vertical-align: top;
+};
+
+#hangouts-local-present-checkbox-subtitle {
+ display: block;
+ font-size: 0.8em;
+ margin-top: 2px;
+ width: 249px;
+}
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.html b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.html
index 5df138f4510..7a7ac5df9d9 100644
--- a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.html
+++ b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.html
@@ -1,6 +1,7 @@
<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-icons/av-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-slider/paper-slider.html">
<dom-module id="route-controls">
<link rel="import" type="css" href="../../media_router_common.css">
@@ -36,7 +37,7 @@
</span>
</div>
</div>
- <div id="play-pause-volume-controls">
+ <div id="play-pause-volume-hangouts-controls">
<span id="button-holder" dir="ltr">
<paper-icon-button
id="route-play-pause-button"
@@ -53,11 +54,10 @@
title="[[getMuteUnmuteTitle_(routeStatus)]]"
on-click="onMuteUnmute_"></paper-icon-button>
</span>
- <span id="volume-holder">
+ <span id="volume-holder" hidden="[[!routeStatus.canSetVolume]]">
<paper-slider
aria-valuetext$="[[getVolumeSliderValueText_(displayedVolume_)]]"
id="route-volume-slider"
- hidden="[[!routeStatus.canSetVolume]]"
disabled="[[!routeStatus.canSetVolume]]"
on-change="onVolumeChangeComplete_"
on-immediate-value-change="onVolumeChangeByDragging_"
@@ -65,6 +65,21 @@
value="[[displayedVolume_]]"
min="0" max="1" step="0.01"></paper-slider>
</span>
+ <div id="hangouts-local-present-controls"
+ hidden="[[!routeStatus.hangoutsExtraData]]">
+ <paper-checkbox
+ checked="[[hangoutsLocalPresent_]]"
+ id="hangouts-local-present-checkbox"
+ on-change="onHangoutsLocalPresentChange_"
+ tabindex="0">
+ <span id='hangouts-local-present-checkbox-title'>
+ [[i18n('hangoutsLocalPresentTitle')]]
+ </span>
+ <span id="hangouts-local-present-checkbox-subtitle">
+ [[i18n('hangoutsLocalPresentSubtitle')]]
+ </span>
+ </paper-checkbox>
+ </div>
</div>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.js b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.js
index 2ca16a7c75b..00ec83a1893 100644
--- a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.js
+++ b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls.js
@@ -40,6 +40,16 @@ Polymer({
},
/**
+ * True if the Hangouts route is currently using local present mode.
+ * Valid for Hangouts routes only.
+ * @private {boolean}
+ */
+ hangoutsLocalPresent_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
* The timestamp for when the initial media status was loaded.
* @private {number}
*/
@@ -97,6 +107,15 @@ Polymer({
},
/**
+ * The route currently associated with this controller.
+ * @type {?media_router.Route|undefined}
+ */
+ route: {
+ type: Object,
+ observer: 'onRouteUpdated_',
+ },
+
+ /**
* The timestamp for when the route details view was opened.
* @type {number}
*/
@@ -284,6 +303,15 @@ Polymer({
},
/**
+ * Called when the "smooth motion" box for Hangouts is changed by the user.
+ * @param {!{target: !PaperCheckboxElement}} e
+ * @private
+ */
+ onHangoutsLocalPresentChange_: function(e) {
+ media_router.browserApi.setHangoutsLocalPresent(e.target.checked);
+ },
+
+ /**
* Called when the user toggles the mute status of the media. Sends a mute or
* unmute command to the browser.
* @private
@@ -332,14 +360,17 @@ Polymer({
this.timeIncrementsTimeoutId_ =
setTimeout(() => this.maybeIncrementCurrentTime_(), 1000);
}
+ this.hangoutsLocalPresent_ = !!newRouteStatus.hangoutsExtraData &&
+ newRouteStatus.hangoutsExtraData.localPresent;
},
/**
* Called when the route is updated. Updates the description shown if it has
* not been provided by status updates.
* @param {?media_router.Route} route
+ * @private
*/
- onRouteUpdated: function(route) {
+ onRouteUpdated_: function(route) {
if (!route) {
this.stopIncrementingCurrentTime_();
}
diff --git a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls_interface.js b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls_interface.js
index 93aefe5db75..53e5a481271 100644
--- a/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls_interface.js
+++ b/chromium/chrome/browser/resources/media_router/elements/route_controls/route_controls_interface.js
@@ -18,10 +18,3 @@ RouteControlsInterface.prototype.routeStatus;
* Resets the route controls. Called when the route details view is closed.
*/
RouteControlsInterface.prototype.reset = function() {};
-
-/**
- * Called when the route is updated. Updates the description shown if it has
- * not been provided by status updates.
- * @param {!media_router.Route} route
- */
-RouteControlsInterface.prototype.onRouteUpdated = function(route) {};
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 bf90749150e..6bc2093cb04 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
@@ -20,7 +20,8 @@
</template>
<template is="dom-if" if="[[shouldShowWebUiControls_(controllerType_)]]">
<route-controls id="route-controls"
- route-details-open-time="[[openTime_]]"></route-controls>
+ route-details-open-time="[[openTime_]]"
+ route="[[route]]"></route-controls>
</template>
<div id="route-action-buttons" class="layout">
<paper-button flat class="route-button button"
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 946193590b8..b260d818c80 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
@@ -232,8 +232,6 @@ Polymer({
onRouteChange_: function(newRoute) {
if (this.controllerType_ !== media_router.ControllerType.WEBUI) {
this.updateActivityStatus_();
- } else if (this.$$('route-controls')) {
- this.$$('route-controls').onRouteUpdated(newRoute);
}
},
diff --git a/chromium/chrome/browser/resources/media_router/media_router_browser_api.js b/chromium/chrome/browser/resources/media_router/media_router_browser_api.js
index ac132fdb0c8..fe5e3b12e0e 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_browser_api.js
+++ b/chromium/chrome/browser/resources/media_router/media_router_browser_api.js
@@ -275,6 +275,10 @@ cr.define('media_router.browserApi', function() {
chrome.send('seekCurrentMedia', [{time: time}]);
}
+ /**
+ * Sends a command to open a file dialog and allow the user to choose a local
+ * media file.
+ */
function selectLocalMediaFile() {
chrome.send('selectLocalMediaFile');
}
@@ -299,6 +303,15 @@ cr.define('media_router.browserApi', function() {
chrome.send('setCurrentMediaVolume', [{volume: volume}]);
}
+ /**
+ * Sets the local present mode of the Hangouts associated with the current
+ * route.
+ * @param {boolean} localPresent
+ */
+ function setHangoutsLocalPresent(localPresent) {
+ chrome.send('hangouts.setLocalPresent', [localPresent]);
+ }
+
return {
acknowledgeFirstRunFlow: acknowledgeFirstRunFlow,
actOnIssue: actOnIssue,
@@ -331,5 +344,6 @@ cr.define('media_router.browserApi', function() {
selectLocalMediaFile: selectLocalMediaFile,
setCurrentMediaMute: setCurrentMediaMute,
setCurrentMediaVolume: setCurrentMediaVolume,
+ setHangoutsLocalPresent: setHangoutsLocalPresent
};
});
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 8d147a31f49..d8252460856 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_data.js
+++ b/chromium/chrome/browser/resources/media_router/media_router_data.js
@@ -250,6 +250,8 @@ cr.define('media_router', function() {
* @param {number} duration The route's duration in seconds.
* @param {number} currentTime The route's current position in seconds.
* Must not be greater than |duration|.
+ * @param {!{localPresent: boolean}=} hangoutsExtraData Only set for Hangouts
+ * routes.
* @constructor
* @struct
*/
@@ -257,7 +259,8 @@ cr.define('media_router', function() {
title = '', description = '', canPlayPause = false, canMute = false,
canSetVolume = false, canSeek = false,
playState = media_router.PlayState.PLAYING, isPaused = false,
- isMuted = false, volume = 0, duration = 0, currentTime = 0) {
+ isMuted = false, volume = 0, duration = 0, currentTime = 0,
+ hangoutsExtraData = undefined) {
/** @type {string} */
this.title = title;
@@ -291,6 +294,9 @@ cr.define('media_router', function() {
/** @type {number} */
this.currentTime = currentTime;
+
+ /** @type {!{localPresent: boolean}|undefined} */
+ this.hangoutsExtraData = hangoutsExtraData;
};
/**
diff --git a/chromium/chrome/browser/resources/memory_internals.js b/chromium/chrome/browser/resources/memory_internals.js
index ce94b5adf9e..9c2d8ff79b6 100644
--- a/chromium/chrome/browser/resources/memory_internals.js
+++ b/chromium/chrome/browser/resources/memory_internals.js
@@ -59,19 +59,19 @@ function returnProcessList(data) {
for (let proc of processes) {
let procId = proc[0];
- let save_button = document.createElement('button');
- save_button.innerText = '\u21e9 Save dump';
- save_button.onclick = () => dumpProcess(procId);
+ let saveButton = document.createElement('button');
+ saveButton.innerText = '\u21e9 Save dump';
+ saveButton.onclick = () => dumpProcess(procId);
- let report_button = document.createElement('button');
- report_button.innerText = '\uD83D\uDC1E Report';
- report_button.onclick = () => reportProcess(procId);
+ let reportButton = document.createElement('button');
+ reportButton.innerText = '\uD83D\uDC1E Report';
+ reportButton.onclick = () => reportProcess(procId);
let procIdText = document.createTextNode(procId.toString());
let description = document.createTextNode(proc[1]);
addListRow(
- table, 'td', [save_button, report_button, procIdText, description]);
+ table, 'td', [saveButton, reportButton, procIdText, description]);
}
proclist.appendChild(table);
diff --git a/chromium/chrome/browser/resources/net_internals/bandwidth_view.html b/chromium/chrome/browser/resources/net_internals/bandwidth_view.html
index 01e804e558e..b64fa64f257 100644
--- a/chromium/chrome/browser/resources/net_internals/bandwidth_view.html
+++ b/chromium/chrome/browser/resources/net_internals/bandwidth_view.html
@@ -22,22 +22,6 @@ table.borderless-table,
</ul>
<a href="#proxy">View current proxy configuration</a>
- <h4>Recent events</h4>
- <div id=data-reduction-proxy-view-events-content>
- <table class="styled-table">
- <thead>
- <tr>
- <th>Time</th>
- <th>Action</th>
- </tr>
- <tr>
- <th colspan=2>Details</th>
- </tr>
- </thead>
- <tbody id=data-reduction-proxy-view-events-tbody>
- </tbody>
- </table>
- </div>
<h4>Bandwidth Savings</h4>
<table class="styled-table" id="bandwidth-stats-table">
<thead>
@@ -55,4 +39,20 @@ table.borderless-table,
</tr>
</tbody>
</table>
+ <h4>Recent events</h4>
+ <div id=data-reduction-proxy-view-events-content>
+ <table class="styled-table">
+ <thead>
+ <tr>
+ <th>Time</th>
+ <th>Action</th>
+ </tr>
+ <tr>
+ <th colspan=2>Details</th>
+ </tr>
+ </thead>
+ <tbody id=data-reduction-proxy-view-events-tbody>
+ </tbody>
+ </table>
+ </div>
</div>
diff --git a/chromium/chrome/browser/resources/net_internals/browser_bridge.js b/chromium/chrome/browser/resources/net_internals/browser_bridge.js
index 74b6b7f5817..3068a34fe22 100644
--- a/chromium/chrome/browser/resources/net_internals/browser_bridge.js
+++ b/chromium/chrome/browser/resources/net_internals/browser_bridge.js
@@ -53,7 +53,6 @@ var BrowserBridge = (function() {
this.addNetInfoPollableDataHelper(
'altSvcMappings', 'onAltSvcMappingsChanged');
this.addNetInfoPollableDataHelper('quicInfo', 'onQuicInfoChanged');
- this.addNetInfoPollableDataHelper('sdchInfo', 'onSdchInfoChanged');
this.addNetInfoPollableDataHelper(
'httpCacheInfo', 'onHttpCacheInfoChanged');
@@ -640,17 +639,6 @@ var BrowserBridge = (function() {
},
/**
- * Adds a listener of SDCH information. |observer| will be called
- * back when data is received, through:
- *
- * observer.onSdchInfoChanged(sdchInfo)
- */
- addSdchInfoObserver: function(observer, ignoreWhenUnchanged) {
- this.pollableDataHelpers_.sdchInfo.addObserver(
- observer, ignoreWhenUnchanged);
- },
-
- /**
* If |force| is true, calls all startUpdate functions. Otherwise, just
* runs updates with active observers.
*/
diff --git a/chromium/chrome/browser/resources/net_internals/events_view.css b/chromium/chrome/browser/resources/net_internals/events_view.css
index 1183bfb787f..4358a73c9ae 100644
--- a/chromium/chrome/browser/resources/net_internals/events_view.css
+++ b/chromium/chrome/browser/resources/net_internals/events_view.css
@@ -90,14 +90,6 @@
color: rgb(112, 112, 0);
}
-#events-view-source-list-tbody .source-filestream {
- color: rgb(112, 0, 112);
-}
-
-#events-view-source-list-tbody .source-ipv6-probe-job {
- color: rgb(235, 0, 0);
-}
-
#events-view-source-list-tbody .source-none {
color: rgb(235, 0, 0);
}
diff --git a/chromium/chrome/browser/resources/net_internals/index.html b/chromium/chrome/browser/resources/net_internals/index.html
index 3fc6f089d81..fec412dbf6e 100644
--- a/chromium/chrome/browser/resources/net_internals/index.html
+++ b/chromium/chrome/browser/resources/net_internals/index.html
@@ -44,7 +44,6 @@ found in the LICENSE file.
<include src="domain_security_policy_view.html">
<include src="events_view.html">
<include src="timeline_view.html">
- <include src="sdch_view.html">
<include src="chromeos_view.html">
</div>
diff --git a/chromium/chrome/browser/resources/net_internals/index.js b/chromium/chrome/browser/resources/net_internals/index.js
index 8fcb840e658..fdb47b9c72e 100644
--- a/chromium/chrome/browser/resources/net_internals/index.js
+++ b/chromium/chrome/browser/resources/net_internals/index.js
@@ -45,7 +45,6 @@
// <include src="prerender_view.js">
// <include src="chromeos_view.js">
// <include src="bandwidth_view.js">
-// <include src="sdch_view.js">
document.addEventListener('DOMContentLoaded', function() {
MainView.getInstance(); // from main.js
diff --git a/chromium/chrome/browser/resources/net_internals/log_view_painter.js b/chromium/chrome/browser/resources/net_internals/log_view_painter.js
index 6210fab747b..edb063bed16 100644
--- a/chromium/chrome/browser/resources/net_internals/log_view_painter.js
+++ b/chromium/chrome/browser/resources/net_internals/log_view_painter.js
@@ -356,12 +356,6 @@ function defaultWriteParameter(key, value, out) {
return;
}
- if (key == 'sdch_problem_code' && typeof value == 'number') {
- var valueStr = value + ' (' + sdchProblemCodeToString(value) + ')';
- out.writeArrowKeyValue(key, valueStr);
- return;
- }
-
// Otherwise just default to JSON formatting of the value.
out.writeArrowKeyValue(key, JSON.stringify(value));
}
diff --git a/chromium/chrome/browser/resources/net_internals/main.js b/chromium/chrome/browser/resources/net_internals/main.js
index 3036cfb71b1..6b286ea8b9a 100644
--- a/chromium/chrome/browser/resources/net_internals/main.js
+++ b/chromium/chrome/browser/resources/net_internals/main.js
@@ -20,7 +20,6 @@ var LoadFlag = null;
var CertStatusFlag = null;
var LoadState = null;
var AddressFamily = null;
-var SdchProblemCode = null;
var DataReductionProxyBypassEventType = null;
/**
@@ -189,7 +188,6 @@ var MainView = (function() {
addTab(AltSvcView);
addTab(SpdyView);
addTab(QuicView);
- addTab(SdchView);
addTab(HttpCacheView);
addTab(ModulesView);
addTab(DomainSecurityPolicyView);
@@ -322,7 +320,6 @@ ConstantsObserver.prototype.onReceivedConstants = function(receivedConstants) {
QuicRstStreamError = Constants.quicRstStreamError;
AddressFamily = Constants.addressFamily;
LoadState = Constants.loadState;
- SdchProblemCode = Constants.sdchProblemCode;
DataReductionProxyBypassEventType =
Constants.dataReductionProxyBypassEventType;
DataReductionProxyBypassActionType =
@@ -401,15 +398,3 @@ function addressFamilyToString(family) {
// Strip that prefix since it is redundant and only clutters the output.
return str.replace(/^ADDRESS_FAMILY_/, '');
}
-
-/**
- * Returns the name for sdchProblemCode.
- *
- * Example: sdchProblemCodeToString(5) should return
- * "DECODE_BODY_ERROR".
- * @param {number} sdchProblemCode The SDCH problem code.
- * @return {string} The name of the given problem code.
- */
-function sdchProblemCodeToString(sdchProblemCode) {
- return getKeyWithValue(SdchProblemCode, sdchProblemCode);
-}
diff --git a/chromium/chrome/browser/resources/net_internals/quic_view.html b/chromium/chrome/browser/resources/net_internals/quic_view.html
index bfbe3540272..670a10ecd79 100644
--- a/chromium/chrome/browser/resources/net_internals/quic_view.html
+++ b/chromium/chrome/browser/resources/net_internals/quic_view.html
@@ -72,9 +72,6 @@
</span>
</td>
</tr><tr>
- <td>Close Sessions on IP Change</td>
- <td><span jscontent="!!$this.close_sessions_on_ip_change"></span></td>
- </tr><tr>
<td>Disable Bidirectional Streams</td>
<td><span jscontent="!!$this.disable_bidirectional_streams"></span></td>
</tr><tr>
diff --git a/chromium/chrome/browser/resources/net_internals/sdch_view.html b/chromium/chrome/browser/resources/net_internals/sdch_view.html
deleted file mode 100644
index 0288d968943..00000000000
--- a/chromium/chrome/browser/resources/net_internals/sdch_view.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<div id=sdch-view-tab-content class=content-box>
- <ul style="margin-top:0">
- <li>SDCH Enabled:
- <span jscontent="!!sdch_enabled" id=sdch-view-sdch-enabled></span>
- </li>
- </ul>
-
- <p>SDCH Errors:
- <a href="#events&q=type:URL_REQUEST%20SDCH_DECODING_ERROR"
- style="padding-right:2em">Decoding</a>
- <a href="#events&q=type:URL_REQUEST%20SDCH_DICTIONARY_ERROR">Dictionary</a>
- </p>
-
- <p>
- <a href="#events&q=type:URL_REQUEST%20SDCH_DICTIONARY_FETCH">
- SDCH Dictionary Fetches
- </a>
- </p>
-
- <p>
- <a href="#events&q=type:URL_REQUEST%20Avail-Dictionary">
- SDCH Requests
- </a>
- </p>
-
- <h4>
- Dictionaries loaded: <span jscontent="dictionaries.length"></span>
- </h4>
- <table class="styled-table">
- <thead>
- <tr>
- <th>Domain</th>
- <th>Path</th>
- <th>Ports</th>
- <th>Server Hash</th>
- <th>Client Hash</th>
- <th>Url</th>
- </tr>
- </thead>
- <tbody id=sdch-view-dictionaries-body>
- <tr jsselect="dictionaries">
- <td jscontent="domain"></td>
- <td jscontent="path"></td>
- <td jscontent="$this.ports ? $this.ports.join(', ') : ''"></td>
- <td jscontent="server_hash"></td>
- <td jscontent="client_hash"></td>
- <td jscontent="url"></td>
- </tr>
- </tbody>
- </table>
-
- <h4>Blacklisted domains</h4>
- <table class="styled-table">
- <thead>
- <tr>
- <th>Domain</th>
- <th>Reason</th>
- <th>Tries to back off</th>
- </tr>
- </thead>
- <tbody id=sdch-view-blacklist-body>
- <tr jsselect="blacklisted">
- <td jscontent="domain"></td>
- <td jscontent="sdchProblemCodeToString(reason)"></td>
- <td jscontent="tries"></td>
- </tr>
- </tbody>
- </table>
-</div>
diff --git a/chromium/chrome/browser/resources/net_internals/sdch_view.js b/chromium/chrome/browser/resources/net_internals/sdch_view.js
deleted file mode 100644
index 6f5191e4c79..00000000000
--- a/chromium/chrome/browser/resources/net_internals/sdch_view.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(rdsmith) Note that SDCH has been disabled in Chrome as of M59.
-// This code is being retained for examining dumps generated before that
-// milestone. It's probably fine to remove it in M64 or later.
-
-/**
- * This view displays information related to SDCH.
- *
- * Shows loaded dictionaries, blacklisted domains and SDCH errors.
- */
-var SdchView = (function() {
- 'use strict';
-
- // We inherit from DivView.
- var superClass = DivView;
-
- /**
- * @constructor
- */
- function SdchView() {
- assertFirstConstructorCall(SdchView);
-
- // Call superclass's constructor.
- superClass.call(this, SdchView.MAIN_BOX_ID);
-
- // Register to receive changes to the SDCH info.
- g_browser.addSdchInfoObserver(this, false);
- }
-
- SdchView.TAB_ID = 'tab-handle-sdch';
- SdchView.TAB_NAME = 'SDCH';
- SdchView.TAB_HASH = '#sdch';
-
- // IDs for special HTML elements in sdch_view.html
- SdchView.MAIN_BOX_ID = 'sdch-view-tab-content';
- SdchView.SDCH_ENABLED_SPAN_ID = 'sdch-view-sdch-enabled';
- SdchView.SECURE_SCHEME_SUPPORT_SPAN_ID = 'sdch-view-secure-scheme-support';
- SdchView.BLACKLIST_TBODY_ID = 'sdch-view-blacklist-body';
- SdchView.DICTIONARIES_TBODY_ID = 'sdch-view-dictionaries-body';
-
- cr.addSingletonGetter(SdchView);
-
- SdchView.prototype = {
- // Inherit the superclass's methods.
- __proto__: superClass.prototype,
-
- onLoadLogFinish: function(data) {
- return this.onSdchInfoChanged(data.sdchInfo);
- },
-
- onSdchInfoChanged: function(sdchInfo) {
- if (!sdchInfo || typeof(sdchInfo.sdch_enabled) === 'undefined')
- return false;
- var input = new JsEvalContext(sdchInfo);
- jstProcess(input, $(SdchView.MAIN_BOX_ID));
- return true;
- },
- };
-
- return SdchView;
-})();
diff --git a/chromium/chrome/browser/resources/net_internals/source_entry.js b/chromium/chrome/browser/resources/net_internals/source_entry.js
index 126750c8cfe..bb1db6fcd08 100644
--- a/chromium/chrome/browser/resources/net_internals/source_entry.js
+++ b/chromium/chrome/browser/resources/net_internals/source_entry.js
@@ -159,16 +159,6 @@ var SourceEntry = (function() {
break;
}
break;
- case EventSourceType.FILESTREAM:
- this.description_ = e.params.file_name;
- break;
- case EventSourceType.IPV6_PROBE_JOB:
- if (e.type == EventType.IPV6_PROBE_RUNNING &&
- e.phase == EventPhase.PHASE_END) {
- this.description_ = e.params.ipv6_supported ? 'IPv6 Supported' :
- 'IPv6 Not Supported';
- }
- break;
}
if (this.description_ == undefined)
diff --git a/chromium/chrome/browser/resources/ntp4/md_incognito_tab.css b/chromium/chrome/browser/resources/ntp4/md_incognito_tab.css
index 2bbea6b536b..3b52699d588 100644
--- a/chromium/chrome/browser/resources/ntp4/md_incognito_tab.css
+++ b/chromium/chrome/browser/resources/ntp4/md_incognito_tab.css
@@ -139,7 +139,6 @@ html[dir=rtl] .bulletpoints + .bulletpoints {
/* On narrow screens, align everything to the left. */
@media (max-width: 720px) {
.content {
- -webkit-margin-start: 0;
max-width: 600px !important; /* must override the rule set by JS which
* is only valid for width > 720px cases. */
text-align: start;
diff --git a/chromium/chrome/browser/resources/ntp4/new_tab.js b/chromium/chrome/browser/resources/ntp4/new_tab.js
index cecee13c5a3..bcf8a7b028b 100644
--- a/chromium/chrome/browser/resources/ntp4/new_tab.js
+++ b/chromium/chrome/browser/resources/ntp4/new_tab.js
@@ -57,12 +57,10 @@ cr.define('ntp', function() {
function NewTabView() {
var pageSwitcherStart;
var pageSwitcherEnd;
- if (loadTimeData.getValue('showApps')) {
- pageSwitcherStart = /** @type {!ntp.PageSwitcher} */ (
- getRequiredElement('page-switcher-start'));
- pageSwitcherEnd = /** @type {!ntp.PageSwitcher} */ (
- getRequiredElement('page-switcher-end'));
- }
+ pageSwitcherStart = /** @type {!ntp.PageSwitcher} */ (
+ getRequiredElement('page-switcher-start'));
+ pageSwitcherEnd = /** @type {!ntp.PageSwitcher} */ (
+ getRequiredElement('page-switcher-end'));
this.initialize(
getRequiredElement('page-list'), getRequiredElement('dot-list'),
getRequiredElement('card-slider-frame'), getRequiredElement('trash'),
@@ -77,18 +75,15 @@ cr.define('ntp', function() {
* Invoked at startup once the DOM is available to initialize the app.
*/
function onLoad() {
- sectionsToWaitFor = 0;
- if (loadTimeData.getBoolean('showApps')) {
- sectionsToWaitFor++;
- if (loadTimeData.getBoolean('showAppLauncherPromo')) {
- $('app-launcher-promo-close-button')
- .addEventListener('click', function() {
- chrome.send('stopShowingAppLauncherPromo');
- });
- $('apps-promo-learn-more').addEventListener('click', function() {
- chrome.send('onLearnMore');
- });
- }
+ sectionsToWaitFor = 1;
+ if (loadTimeData.getBoolean('showAppLauncherPromo')) {
+ $('app-launcher-promo-close-button')
+ .addEventListener('click', function() {
+ chrome.send('stopShowingAppLauncherPromo');
+ });
+ $('apps-promo-learn-more').addEventListener('click', function() {
+ chrome.send('onLearnMore');
+ });
}
measureNavDots();
diff --git a/chromium/chrome/browser/resources/ntp4/page_list_view.js b/chromium/chrome/browser/resources/ntp4/page_list_view.js
index 470dbab409f..89bb392b521 100644
--- a/chromium/chrome/browser/resources/ntp4/page_list_view.js
+++ b/chromium/chrome/browser/resources/ntp4/page_list_view.js
@@ -162,9 +162,6 @@ cr.define('ntp', function() {
this.shownPageIndex = loadTimeData.getInteger('shown_page_index');
- // TODO(dbeam): remove showApps and everything that says if (apps).
- assert(loadTimeData.getBoolean('showApps'));
-
// Request data on the apps so we can fill them in.
// Note that this is kicked off asynchronously. 'getAppsCallback' will
// be invoked at some point after this function returns.
@@ -261,8 +258,6 @@ cr.define('ntp', function() {
* position indices.
*/
appMoved: function(appData) {
- assert(loadTimeData.getBoolean('showApps'));
-
var app = /** @type {ntp.App} */ ($(appData.id));
assert(app, 'trying to move an app that doesn\'t exist');
app.remove(false);
@@ -280,8 +275,6 @@ cr.define('ntp', function() {
* @param {boolean} fromPage True if the removal was from the current page.
*/
appRemoved: function(appData, isUninstall, fromPage) {
- assert(loadTimeData.getBoolean('showApps'));
-
var app = /** @type {ntp.App} */ ($(appData.id));
assert(app, 'trying to remove an app that doesn\'t exist');
@@ -316,8 +309,6 @@ cr.define('ntp', function() {
* An object with all the data on available applications.
*/
getAppsCallback: function(data) {
- assert(loadTimeData.getBoolean('showApps'));
-
var startTime = Date.now();
// Remember this to select the correct card when done rebuilding.
@@ -423,8 +414,6 @@ cr.define('ntp', function() {
* be highlighted.
*/
appAdded: function(appData, opt_highlight) {
- assert(loadTimeData.getBoolean('showApps'));
-
if (appData.id == this.highlightAppId) {
opt_highlight = true;
this.highlightAppId = null;
@@ -459,8 +448,6 @@ cr.define('ntp', function() {
* applications.
*/
appsPrefChangedCallback: function(data) {
- assert(loadTimeData.getBoolean('showApps'));
-
for (var i = 0; i < data.apps.length; ++i) {
$(data.apps[i].id).appData = data.apps[i];
}
@@ -500,10 +487,8 @@ cr.define('ntp', function() {
0, Math.min(this.cardSlider.currentCard, this.tilePages.length - 1));
this.cardSlider.setCards(
Array.prototype.slice.call(this.tilePages), pageNo);
- if (loadTimeData.getBoolean('showApps')) {
- this.cardSlider.selectCardByValue(this.appsPages[Math.min(
- this.shownPageIndex, this.appsPages.length - 1)]);
- }
+ this.cardSlider.selectCardByValue(this.appsPages[Math.min(
+ this.shownPageIndex, this.appsPages.length - 1)]);
},
/**
@@ -511,12 +496,10 @@ cr.define('ntp', function() {
* of a moving or insert tile.
*/
enterRearrangeMode: function() {
- if (loadTimeData.getBoolean('showApps')) {
- var tempPage = new ntp.AppsPage();
- tempPage.classList.add('temporary');
- var pageName = loadTimeData.getString('appDefaultPageName');
- this.appendTilePage(tempPage, pageName, true);
- }
+ var tempPage = new ntp.AppsPage();
+ tempPage.classList.add('temporary');
+ var pageName = loadTimeData.getString('appDefaultPageName');
+ this.appendTilePage(tempPage, pageName, true);
if (ntp.getCurrentlyDraggingTile().firstChild.canBeRemoved()) {
$('footer').classList.add('showing-trash-mode');
diff --git a/chromium/chrome/browser/resources/offline_pages/offline_internals.html b/chromium/chrome/browser/resources/offline_pages/offline_internals.html
index 6aae5794445..2590edbda99 100644
--- a/chromium/chrome/browser/resources/offline_pages/offline_internals.html
+++ b/chromium/chrome/browser/resources/offline_pages/offline_internals.html
@@ -112,6 +112,10 @@
<button id="cancel-nwake">Cancel NWake</button>
</div>
<div>
+ <!-- This button is used by UI automation testing !-->
+ <button id="show-notification">Show Notification</button>
+ </div>
+ <div>
<input id="generate-urls" type="text"
placeholder="http://www.url1.com, http://www.url2.com, ...">
<button id="generate-page-bundle">Generate Page Bundle</button>
diff --git a/chromium/chrome/browser/resources/offline_pages/offline_internals.js b/chromium/chrome/browser/resources/offline_pages/offline_internals.js
index dc5894047d6..2605b0b781a 100644
--- a/chromium/chrome/browser/resources/offline_pages/offline_internals.js
+++ b/chromium/chrome/browser/resources/offline_pages/offline_internals.js
@@ -160,6 +160,16 @@ cr.define('offlineInternals', function() {
}
/**
+ * Error callback for prefetch actions.
+ * @param {*} error The error that resulted from the prefetch call.
+ */
+ function prefetchResultError(error) {
+ var errorText = error && error.message ? error.message : error;
+
+ $('prefetch-actions-info').textContent = 'Error: ' + errorText;
+ }
+
+ /**
* Downloads all the stored page and request queue information into a file.
* TODO(chili): Create a CSV writer that can abstract out the line joining.
*/
@@ -295,18 +305,27 @@ cr.define('offlineInternals', function() {
}
};
$('schedule-nwake').onclick = function() {
- browserProxy.scheduleNwake().then(setPrefetchResult);
+ browserProxy.scheduleNwake()
+ .then(setPrefetchResult)
+ .catch(prefetchResultError);
};
$('cancel-nwake').onclick = function() {
- browserProxy.cancelNwake().then(setPrefetchResult);
+ browserProxy.cancelNwake()
+ .then(setPrefetchResult)
+ .catch(prefetchResultError);
+ };
+ $('show-notification').onclick = function() {
+ browserProxy.showPrefetchNotification().then(setPrefetchResult);
};
$('generate-page-bundle').onclick = function() {
browserProxy.generatePageBundle($('generate-urls').value)
- .then(setPrefetchResult);
+ .then(setPrefetchResult)
+ .catch(prefetchResultError);
};
$('get-operation').onclick = function() {
browserProxy.getOperation($('operation-name').value)
- .then(setPrefetchResult);
+ .then(setPrefetchResult)
+ .catch(prefetchResultError);
};
$('download-archive').onclick = function() {
browserProxy.downloadArchive($('download-name').value);
diff --git a/chromium/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js b/chromium/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
index 14777fc803d..b30b277609c 100644
--- a/chromium/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
+++ b/chromium/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
@@ -123,18 +123,28 @@ cr.define('offlineInternals', function() {
getNetworkStatus: function() {},
/**
- * Schedules the default NWake task.
- * @return {!Promise} A promise firing when the task has been scheduled.
+ * Schedules the default NWake task. The returned Promise will reject if
+ * there is an error while scheduling.
+ * @return {!Promise<string>} A promise firing when the task has been
+ * scheduled.
*/
scheduleNwake: function() {},
/**
* Cancels NWake task.
- * @return {!Promise} A promise firing when the task has been cancelled.
+ * @return {!Promise} A promise firing when the task has been cancelled. The
+ * returned Promise will reject if there is an error.
*/
cancelNwake: function() {},
/**
+ * Shows the prefetching notification with an example origin.
+ * @return {!Promise<string>} A promise firing when the notification has
+ * been shown.
+ */
+ showPrefetchNotification: function() {},
+
+ /**
* Sends and processes a request to generate page bundle.
* @param {string} urls A list of comma-separated URLs.
* @return {!Promise<string>} A string describing the result.
@@ -229,6 +239,11 @@ cr.define('offlineInternals', function() {
},
/** @override */
+ showPrefetchNotification: function() {
+ return cr.sendWithPromise('showPrefetchNotification');
+ },
+
+ /** @override */
generatePageBundle: function(urls) {
return cr.sendWithPromise('generatePageBundle', urls);
},
diff --git a/chromium/chrome/browser/resources/vulcanize.gni b/chromium/chrome/browser/resources/optimize_webui.gni
index 5555d35f712..e3eb6834391 100644
--- a/chromium/chrome/browser/resources/vulcanize.gni
+++ b/chromium/chrome/browser/resources/optimize_webui.gni
@@ -25,15 +25,15 @@ template("node") {
}
}
-template("vulcanize") {
+template("optimize_webui") {
node(target_name) {
- script = "//chrome/browser/resources/vulcanize_gn.py"
+ script = "//chrome/browser/resources/optimize_webui.py"
inputs = [
"//chrome/browser/resources/unpack_pak.py",
]
- # This depfile is generated by vulcanize_gn.py
+ # This depfile is generated by optimize_webui.py
depfile = "${target_gen_dir}/${target_name}.d"
outputs = []
@@ -110,7 +110,7 @@ template("unpak") {
]
outputs = [
- "$target_gen_dir/${invoker.out_folder}",
+ "$target_gen_dir/${invoker.out_folder}/unpack.stamp",
]
deps = invoker.deps
diff --git a/chromium/chrome/browser/resources/vulcanize_gn.py b/chromium/chrome/browser/resources/optimize_webui.py
index f5c48c88d7e..b06fe52fe1c 100755
--- a/chromium/chrome/browser/resources/vulcanize_gn.py
+++ b/chromium/chrome/browser/resources/optimize_webui.py
@@ -127,7 +127,7 @@ def _update_dep_file(in_folder, args, manifest):
f.write(deps_file_header + ': ' + ' '.join(deps))
-def _vulcanize(in_folder, args):
+def _optimize(in_folder, args):
in_path = os.path.normpath(os.path.join(_CWD, in_folder))
out_path = os.path.join(_CWD, args.out_folder)
manifest_out_path = _request_list_path(out_path, args.host)
@@ -232,9 +232,9 @@ def main(argv):
args.input = os.path.normpath(args.input)
args.out_folder = os.path.normpath(args.out_folder)
- manifest_out_path = _vulcanize(args.input, args)
+ manifest_out_path = _optimize(args.input, args)
- # Prior call to _vulcanize() generated an output manifest file, containing
+ # Prior call to _optimize() generated an output manifest file, containing
# information about all files that were bundled. Grab it from there.
manifest = json.loads(open(manifest_out_path, 'r').read())
diff --git a/chromium/chrome/browser/resources/vulcanize_gn_test.py b/chromium/chrome/browser/resources/optimize_webui_test.py
index 9af9495993d..d8d819b4751 100755
--- a/chromium/chrome/browser/resources/vulcanize_gn_test.py
+++ b/chromium/chrome/browser/resources/optimize_webui_test.py
@@ -3,17 +3,17 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import optimize_webui
import os
import shutil
import tempfile
import unittest
-import vulcanize_gn
_HERE_DIR = os.path.dirname(__file__)
-class VulcanizeGnTest(unittest.TestCase):
+class OptimizeWebUiTest(unittest.TestCase):
def setUp(self):
self._out_folder = None
self._tmp_dirs = []
@@ -39,11 +39,11 @@ class VulcanizeGnTest(unittest.TestCase):
assert self._out_folder
return open(os.path.join(self._out_folder, file_name), 'r').read()
- def _run_vulcanize(self, depfile, html_in_file, html_out_file, js_out_file):
- # TODO(dbeam): make it possible to _run_vulcanize twice? Is that useful?
+ def _run_optimize(self, depfile, html_in_file, html_out_file, js_out_file):
+ # TODO(dbeam): make it possible to _run_optimize twice? Is that useful?
assert not self._out_folder
self._out_folder = self._create_tmp_dir()
- vulcanize_gn.main([
+ optimize_webui.main([
'--depfile', os.path.join(self._out_folder,'depfile.d'),
'--html_in_file', html_in_file,
'--html_out_file', html_out_file,
@@ -54,7 +54,7 @@ class VulcanizeGnTest(unittest.TestCase):
])
- def testSimpleVulcanize(self):
+ def testSimpleOptimize(self):
self._write_file_to_src_dir('element.html', '<div>got here!</div>')
self._write_file_to_src_dir('element.js', "alert('yay');")
self._write_file_to_src_dir('ui.html', '''
@@ -62,10 +62,10 @@ class VulcanizeGnTest(unittest.TestCase):
<script src="element.js"></script>
''')
- self._run_vulcanize(depfile='depfile.d',
- html_in_file='ui.html',
- html_out_file='fast.html',
- js_out_file='fast.js')
+ self._run_optimize(depfile='depfile.d',
+ html_in_file='ui.html',
+ html_out_file='fast.html',
+ js_out_file='fast.js')
fast_html = self._read_out_file('fast.html')
self.assertFalse('element.html' in fast_html)
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js
index 1e7164a333f..de21ff24b32 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark/viewer-bookmark.js
@@ -2,6 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/**
+ * The |title| is the text label displayed for the bookmark.
+ *
+ * The bookmark may point at a location in the PDF or a URI.
+ * If it points at a location, |page| indicates which 0-based page it leads to.
+ * Optionally, |y| is the y position in that page, in pixel coordinates.
+ * If it points at an URI, |uri| is the target for that bookmark.
+ *
+ * |children| is an array of the |Bookmark|s that are below this in a table of
+ * contents tree
+ * structure.
+ * @typedef {{
+ * title: string,
+ * page: number,
+ * y: number,
+ * uri: string,
+ * children: !Array<!Bookmark>
+ * }}
+ */
+var Bookmark;
+
(function() {
/** Amount that each level of bookmarks is indented by (px). */
var BOOKMARK_INDENT = 20;
@@ -10,12 +31,7 @@ Polymer({
is: 'viewer-bookmark',
properties: {
- /**
- * A bookmark object, each containing a:
- * - title
- * - page (optional)
- * - children (an array of bookmarks)
- */
+ /** @type {Bookmark} */
bookmark: {type: Object, observer: 'bookmarkChanged_'},
depth: {type: Number, observer: 'depthChanged'},
@@ -48,10 +64,17 @@ Polymer({
},
onClick: function() {
- if (this.bookmark.hasOwnProperty('page'))
- this.fire('change-page', {page: this.bookmark.page});
- else if (this.bookmark.hasOwnProperty('uri'))
+ if (this.bookmark.hasOwnProperty('page')) {
+ if (this.bookmark.hasOwnProperty('y')) {
+ this.fire(
+ 'change-page-and-y',
+ {page: this.bookmark.page, y: this.bookmark.y});
+ } else {
+ this.fire('change-page', {page: this.bookmark.page});
+ }
+ } else if (this.bookmark.hasOwnProperty('uri')) {
this.fire('navigate', {uri: this.bookmark.uri, newtab: true});
+ }
},
onEnter_: function(e) {
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 bc6553aab56..9ca3d05e7c8 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
@@ -5,7 +5,6 @@
<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">
@@ -22,8 +21,8 @@
/* We introduce a wrapper aligner element to help with laying out the main
* toolbar content without changing the bottom-aligned progress bar. */
#aligner {
- @apply(--layout-horizontal);
- @apply(--layout-center);
+ align-items: center;
+ display: flex;
padding: 0 8px;
width: 100%;
}
@@ -68,11 +67,23 @@
width: 100%;
}
- paper-toolbar {
- --paper-toolbar-background: rgb(50, 54, 57);
- --paper-toolbar-height: 48px;
+ #toolbar {
@apply(--shadow-elevation-2dp);
+ background-color: rgb(50, 54, 57);
color: rgb(241, 241, 241);
+ display: flex;
+ height: 48px;
+ padding: 0 16px;
+ }
+
+ #progress-container {
+ bottom: 0;
+ left: 0;
+ margin: 0;
+ position: absolute;
+ right: 0;
+ top: auto;
+ width: auto;
}
.invisible {
@@ -103,8 +114,8 @@
}
}
</style>
- <paper-toolbar>
- <div id="aligner" class="middle">
+ <div id="toolbar">
+ <div id="aligner">
<span id="title" title="{{docTitle}}">
<span>{{docTitle}}</span>
</span>
@@ -145,10 +156,10 @@
</viewer-toolbar-dropdown>
</div>
</div>
- <div class="bottom fit">
+ <div id="progress-container">
<paper-progress id="progress" value="{{loadProgress}}"></paper-progress>
</div>
- </paper-toolbar>
+ </div>
</template>
<script src="viewer-pdf-toolbar.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/pdf/pdf.js b/chromium/chrome/browser/resources/pdf/pdf.js
index ffc2a4907c9..acb36ab187d 100644
--- a/chromium/chrome/browser/resources/pdf/pdf.js
+++ b/chromium/chrome/browser/resources/pdf/pdf.js
@@ -103,6 +103,7 @@ function PDFViewer(browserApi) {
this.isPrintPreview_ = location.origin === 'chrome://print';
this.isPrintPreviewLoaded_ = false;
+ this.isUserInitiatedEvent_ = true;
// Parse open pdf parameters.
this.paramsParser_ =
@@ -139,7 +140,8 @@ function PDFViewer(browserApi) {
this.viewport_ = new Viewport(
window, this.sizer_, this.viewportChanged_.bind(this),
this.beforeZoom_.bind(this), this.afterZoom_.bind(this),
- getScrollbarWidth(), defaultZoom, topToolbarHeight);
+ this.setUserInitiated_.bind(this), getScrollbarWidth(), defaultZoom,
+ topToolbarHeight);
// Create the plugin object dynamically so we can set its src. The plugin
// element is sized to fill the entire window and is set to be fixed
@@ -220,6 +222,10 @@ function PDFViewer(browserApi) {
this.viewport_.goToPage(e.detail.page);
});
+ document.body.addEventListener('change-page-and-y', e => {
+ this.viewport_.goToPageAndY(e.detail.page, e.detail.y);
+ });
+
document.body.addEventListener('navigate', e => {
var disposition = e.detail.newtab ?
Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB :
@@ -575,7 +581,9 @@ PDFViewer.prototype = {
switch (message.data.type.toString()) {
case 'documentDimensions':
this.documentDimensions_ = message.data;
+ this.isUserInitiatedEvent_ = false;
this.viewport_.setDocumentDimensions(this.documentDimensions_);
+ this.isUserInitiatedEvent_ = true;
// If we received the document dimensions, the password was good so we
// can dismiss the password screen.
if (this.passwordScreen_.active)
@@ -675,6 +683,7 @@ PDFViewer.prototype = {
var pinchPhase = this.viewport_.pinchPhase;
this.plugin_.postMessage({
type: 'viewport',
+ userInitiated: true,
zoom: zoom,
xOffset: position.x,
yOffset: position.y,
@@ -697,6 +706,7 @@ PDFViewer.prototype = {
this.plugin_.postMessage({
type: 'viewport',
+ userInitiated: this.isUserInitiatedEvent_,
zoom: zoom,
xOffset: position.x,
yOffset: position.y,
@@ -710,6 +720,19 @@ PDFViewer.prototype = {
},
/**
+ * @param {boolean} userInitiated The value to set |isUserInitiatedEvent_|
+ * to.
+ * @private
+ * A callback that sets |isUserInitiatedEvent_| to |userInitiated|.
+ */
+ setUserInitiated_: function(userInitiated) {
+ if (this.isUserInitiatedEvent_ == userInitiated) {
+ throw 'Trying to set user initiated to current value.';
+ }
+ this.isUserInitiatedEvent_ = userInitiated;
+ },
+
+ /**
* @private
* A callback that's called when an update to a pinch zoom is detected.
* @param {!Object} e the pinch event.
@@ -850,7 +873,9 @@ PDFViewer.prototype = {
this.loadState_ = LoadState.LOADING;
if (!this.inPrintPreviewMode_) {
this.inPrintPreviewMode_ = true;
+ this.isUserInitiatedEvent_ = false;
this.zoomToolbar_.forceFitToPage();
+ this.isUserInitiatedEvent_ = true;
}
// Stash the scroll location so that it can be restored when the new
diff --git a/chromium/chrome/browser/resources/pdf/viewport.js b/chromium/chrome/browser/resources/pdf/viewport.js
index 358922c606b..e82551d1080 100644
--- a/chromium/chrome/browser/resources/pdf/viewport.js
+++ b/chromium/chrome/browser/resources/pdf/viewport.js
@@ -51,6 +51,8 @@ function frameToPluginCoordinate(coordinateInFrame) {
* @param {Function} viewportChangedCallback is run when the viewport changes
* @param {Function} beforeZoomCallback is run before a change in zoom
* @param {Function} afterZoomCallback is run after a change in zoom
+ * @param {Function} setUserInitiatedCallback is run to indicate whether a zoom
+ * event is user initiated.
* @param {number} scrollbarWidth the width of scrollbars on the page
* @param {number} defaultZoom The default zoom level.
* @param {number} topToolbarHeight The number of pixels that should initially
@@ -58,12 +60,14 @@ function frameToPluginCoordinate(coordinateInFrame) {
*/
function Viewport(
window, sizer, viewportChangedCallback, beforeZoomCallback,
- afterZoomCallback, scrollbarWidth, defaultZoom, topToolbarHeight) {
+ afterZoomCallback, setUserInitiatedCallback, scrollbarWidth, defaultZoom,
+ topToolbarHeight) {
this.window_ = window;
this.sizer_ = sizer;
this.viewportChangedCallback_ = viewportChangedCallback;
this.beforeZoomCallback_ = beforeZoomCallback;
this.afterZoomCallback_ = afterZoomCallback;
+ this.setUserInitiatedCallback_ = setUserInitiatedCallback;
this.allowedToChangeZoom_ = false;
this.internalZoom_ = 1;
this.zoomManager_ = new InactiveZoomManager(this, 1);
@@ -80,7 +84,7 @@ function Viewport(
this.firstPinchCenterInFrame_ = null;
window.addEventListener('scroll', this.updateViewport_.bind(this));
- window.addEventListener('resize', this.resize_.bind(this));
+ window.addEventListener('resize', this.resizeWrapper_.bind(this));
}
/**
@@ -223,6 +227,16 @@ Viewport.prototype = {
/**
* @private
+ * Called when the browser window size changes.
+ */
+ resizeWrapper_: function() {
+ this.setUserInitiatedCallback_(false);
+ this.resize_();
+ this.setUserInitiatedCallback_(true);
+ },
+
+ /**
+ * @private
* Called when the viewport size changes.
*/
resize_: function() {
@@ -305,6 +319,7 @@ Viewport.prototype = {
/**
* @private
+ * @param {function} f Function to wrap
* Used to wrap a function that might perform zooming on the viewport. This is
* required so that we can notify the plugin that zooming is in progress
* so that while zooming is taking place it can stop reacting to scroll events
@@ -721,6 +736,15 @@ Viewport.prototype = {
* @param {number} page the index of the page to go to. zero-based.
*/
goToPage: function(page) {
+ this.goToPageAndY(page, 0);
+ },
+
+ /**
+ * Go to the given y position in the given page index.
+ * @param {number} page the index of the page to go to. zero-based.
+ * @param {number} y the y position in the page to go to.
+ */
+ goToPageAndY: function(page, y) {
this.mightZoom_(() => {
if (this.pageDimensions_.length === 0)
return;
@@ -737,7 +761,7 @@ Viewport.prototype = {
toolbarOffset = this.topToolbarHeight_;
this.position = {
x: dimensions.x * this.zoom,
- y: dimensions.y * this.zoom - toolbarOffset
+ y: (dimensions.y + y) * this.zoom - toolbarOffset
};
this.updateViewport_();
});
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
index f337af402a5..ebd071c247c 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": 25,
+ "x-version": 24,
"google-talk": {
"mime_types": [
],
@@ -80,9 +80,9 @@
],
"versions": [
{
- "version": "27.0.0.170",
+ "version": "26.0.0.126",
"status": "up_to_date",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-32.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-17.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 fc04e3f285e..efd1b4f3612 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": 31,
+ "x-version": 30,
"google-talk": {
"mime_types": [
],
@@ -115,9 +115,9 @@
],
"versions": [
{
- "version": "27.0.0.170",
+ "version": "26.0.0.126",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-32.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-17.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 7dc26f683ac..00786d2f197 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": 40,
+ "x-version": 39,
"google-talk": {
"mime_types": [
],
@@ -137,9 +137,9 @@
],
"versions": [
{
- "version": "27.0.0.170",
+ "version": "26.0.0.126",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-32.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb17-17.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/policy.html b/chromium/chrome/browser/resources/policy.html
index 480bdc9d88c..804f44a891e 100644
--- a/chromium/chrome/browser/resources/policy.html
+++ b/chromium/chrome/browser/resources/policy.html
@@ -6,7 +6,7 @@
<title i18n-content="title"></title>
<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
-<link rel="stylesheet" href="uber/uber_shared.css">
+<link rel="stylesheet" href="uber_shared.css">
<link rel="stylesheet" href="chrome://policy/policy.css">
<script src="chrome://resources/js/action_link.js"></script>
@@ -113,7 +113,9 @@
<div class="source elide"></div>
</td>
<td class="name-column">
- <div class="name elide"></div>
+ <div class="name elide">
+ <a class="name-link" target="_blank"></a>
+ </div>
</td>
<td class="value-column">
<div class="value-container">
diff --git a/chromium/chrome/browser/resources/policy_android.css b/chromium/chrome/browser/resources/policy_android.css
index 7bb0e2ac53b..999e02323da 100644
--- a/chromium/chrome/browser/resources/policy_android.css
+++ b/chromium/chrome/browser/resources/policy_android.css
@@ -167,6 +167,12 @@ div.name {
width: 15%;
}
+.no-help-link .name-link {
+ color: inherit;
+ pointer-events: none;
+ text-decoration: none;
+}
+
div.elide,
span.value {
overflow: hidden;
diff --git a/chromium/chrome/browser/resources/policy_base.js b/chromium/chrome/browser/resources/policy_base.js
index 8994b97bea4..8ab679951be 100644
--- a/chromium/chrome/browser/resources/policy_base.js
+++ b/chromium/chrome/browser/resources/policy_base.js
@@ -128,7 +128,15 @@ cr.define('policy', function() {
this.unset = !value;
// Populate the name column.
- this.querySelector('.name').textContent = name;
+ this.querySelector('.name-link').textContent = name;
+ this.querySelector('.name-link').href =
+ 'https://chromium.org/administrators/policy-list-3#' + name;
+ this.querySelector('.name-link').title =
+ loadTimeData.getStringF('policyLearnMore', name);
+
+ if (unknown) {
+ this.classList.add('no-help-link');
+ }
// Populate the remaining columns with policy scope, level and value if a
// value has been set. Otherwise, leave them blank.
@@ -174,6 +182,25 @@ cr.define('policy', function() {
}
},
+ /*
+ * Get value width of the value container.
+ * @param {Object} valueContainer Container for the value.
+ * @private
+ */
+ getValueWidth_: function(valueContainer) {
+ return valueContainer.querySelector('.value').offsetWidth;
+ },
+
+ /*
+ * Update the value width for the value container if necessary.
+ * @param {Object} valueContainer Container for the value.
+ * @private
+ */
+ updateValueWidth_: function(valueContainer) {
+ if (valueContainer.valueWidth == undefined) {
+ valueContainer.valueWidth = this.getValueWidth_(valueContainer);
+ }
+ },
/**
* Check the table columns for overflow. Most columns are automatically
* elided when overflow occurs. The only action required is to add a tooltip
@@ -193,15 +220,12 @@ cr.define('policy', function() {
// This is required to be able to check whether the contents would still
// overflow the column once it has been hidden and replaced by a link.
var valueContainer = this.querySelector('.value-container');
- if (valueContainer.valueWidth == undefined) {
- valueContainer.valueWidth =
- valueContainer.querySelector('.value').offsetWidth;
- }
+ this.updateValueWidth_(valueContainer);
// Determine whether the contents of the value column overflows. The
// visibility of the contents, replacement link and additional row
// containing the complete value that depend on this are handled by CSS.
- if (valueContainer.offsetWidth < valueContainer.valueWidth)
+ if (valueContainer.offsetWidth <= valueContainer.valueWidth)
this.classList.add('has-overflowed-value');
else
this.classList.remove('has-overflowed-value');
@@ -479,6 +503,9 @@ cr.define('policy', function() {
appendNewTable: function(id, label_title, label_content) {
var newSection =
this.createPolicyTableSection(id, label_title, label_content);
+ if (id != 'chrome') {
+ newSection.classList.add('no-help-link');
+ }
this.mainSection.appendChild(newSection);
return this.policyTables[id];
},
@@ -521,6 +548,8 @@ cr.define('policy', function() {
return section;
},
+ tableHeadings: ['Scope', 'Level', 'Source', 'Name', 'Value', 'Status'],
+
/**
* Creates a new table for displaying policies.
* @return {Element} The newly created table.
@@ -529,13 +558,12 @@ cr.define('policy', function() {
var newTable = window.document.createElement('table');
var tableHead = window.document.createElement('thead');
var tableRow = window.document.createElement('tr');
- var tableHeadings =
- ['Scope', 'Level', 'Source', 'Name', 'Value', 'Status'];
- for (var i = 0; i < tableHeadings.length; i++) {
+ for (var i = 0; i < this.tableHeadings.length; i++) {
var tableHeader = window.document.createElement('th');
- tableHeader.classList.add(tableHeadings[i].toLowerCase() + '-column');
+ tableHeader.classList.add(
+ this.tableHeadings[i].toLowerCase() + '-column');
tableHeader.textContent =
- loadTimeData.getString('header' + tableHeadings[i]);
+ loadTimeData.getString('header' + this.tableHeadings[i]);
tableRow.appendChild(tableHeader);
}
tableHead.appendChild(tableRow);
diff --git a/chromium/chrome/browser/resources/policy_common.css b/chromium/chrome/browser/resources/policy_common.css
index b455641d75a..937c38ea798 100644
--- a/chromium/chrome/browser/resources/policy_common.css
+++ b/chromium/chrome/browser/resources/policy_common.css
@@ -105,6 +105,12 @@ th {
font-weight: normal;
}
+.no-help-link .name-link {
+ color: inherit;
+ pointer-events: none;
+ text-decoration: none;
+}
+
div.elide,
span.value {
overflow: hidden;
diff --git a/chromium/chrome/browser/resources/policy_tool.css b/chromium/chrome/browser/resources/policy_tool.css
new file mode 100644
index 00000000000..7361ccbd141
--- /dev/null
+++ b/chromium/chrome/browser/resources/policy_tool.css
@@ -0,0 +1,41 @@
+/* Copyright (c) 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+@import 'policy_common.css';
+
+.edit-button {
+ float: right;
+ margin: 0;
+ padding: 0;
+}
+
+tbody:not(.value-editing-on) .value-edit-form {
+ display: none;
+}
+
+tbody.value-editing-on .save-button {
+ display: block;
+ float: right;
+}
+
+tbody.value-editing-on .edit-button,
+tbody.value-editing-on .value {
+ display: none;
+}
+
+#invalid-session-name-error {
+ color: red;
+}
+
+#invalid-session-name-error:not(hidden) {
+ display: block;
+}
+
+#session-list {
+ background: white;
+}
+
+#saving span {
+ font-weight: bold;
+}
diff --git a/chromium/chrome/browser/resources/policy_tool.html b/chromium/chrome/browser/resources/policy_tool.html
new file mode 100644
index 00000000000..8af70271184
--- /dev/null
+++ b/chromium/chrome/browser/resources/policy_tool.html
@@ -0,0 +1,100 @@
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<title>$i18n{title}</title>
+
+<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
+<link rel="stylesheet" href="uber_shared.css">
+<link rel="stylesheet" href="chrome://policy-tool/policy_tool.css">
+
+<script src="chrome://resources/js/action_link.js"></script>
+<script src="chrome://resources/js/cr.js"></script>
+<script src="chrome://resources/js/cr/ui.js"></script>
+<script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
+<script src="chrome://resources/js/load_time_data.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+</head>
+
+<body>
+ <div id="filter-overlay" class="page">
+ <header>
+ <input id="filter" class="search-field-container" type="search"
+ placeholder="$i18n{filterPlaceholder}"
+ aria-label="$i18n{filterPlaceholder}" incremental>
+ </input>
+ </header>
+ </div>
+ <div class="page">
+ <header>
+ <h1>$i18n{title}</h1>
+ </header>
+ <section class="reload-show-unset-section">
+ <form id="session-choice">
+ <input id="session-name-field" type="text" autocomplete="off"
+ placeholder="$i18n{sessionNamePlaceholder}">
+ <input type="submit" id="load-session-button"
+ value="$i18n{loadSession}">
+ </form>
+ <div id="saving" hidden>
+ <span>$i18n{errorSavingDisabled}</span>
+ </div>
+ <div id="show-unset-container" class="show-unset-checkbox">
+ <label>
+ <input id="show-unset" type="checkbox"></input>
+ <span>$i18n{showUnset}</span>
+ </label>
+ </div>
+ <span id="invalid-session-name-error" hidden>
+ $i18n{errorInvalidSessionName}
+ </span>
+ </section>
+ <section id="sessions">
+ <select size="4" id="session-list">
+ </select>
+ </section>
+ <section id="main-section" class="empty">
+ <!-- This is where policy tables get dynamically added. -->
+ </section>
+ <section id="disable-editing-error" hidden>
+ <span>$i18n{errorFileCorrupted}</span>
+ <button id="enable-editing">$i18n{enableEditing}</button>
+ </section>
+ </div>
+ <div hidden>
+ <table>
+ <tbody id="policy-template">
+ <tr>
+ <td class="name-column">
+ <div class="name elide"></div>
+ </td>
+ <td class="value-column">
+ <div class="value-container">
+ <span class="value"></span>
+ <a is="action-link" class="toggle-expanded-value"></a>
+ <button class="edit-button">$i18n{edit}</button>
+ <form class="value-edit-form">
+ <input class="value-edit-field" type="text">
+ <input type="submit" class="save-button"
+ value="$i18n{save}">
+ </form>
+ </div>
+ </td>
+ <td class="status-column">
+ <div class="status elide"></div>
+ </td>
+ </tr>
+ <tr class="expanded-value-container">
+ <td class="expanded-value" colspan=3></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</body>
+
+<script src="chrome://policy-tool/strings.js"></script>
+<script src="chrome://resources/js/i18n_template.js"></script>
+<script src="chrome://policy-tool/policy_base.js"></script>
+<script src="chrome://policy-tool/policy_tool.js"></script>
+</html>
diff --git a/chromium/chrome/browser/resources/policy_tool.js b/chromium/chrome/browser/resources/policy_tool.js
new file mode 100644
index 00000000000..871322846d4
--- /dev/null
+++ b/chromium/chrome/browser/resources/policy_tool.js
@@ -0,0 +1,273 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Sets the list of current sessions.
+ * @param {!Array<string>} sessions List of session names.
+ */
+policy.Page.setSessionsList = function(sessions) {
+ var list = $('session-list');
+
+ // Clear the sessions list.
+ list.innerHTML = '';
+
+ // Set the new sessions list.
+ for (var i = 0; i < sessions.length; ++i) {
+ var option = document.createElement('OPTION');
+ option.value = sessions[i];
+ option.textContent = sessions[i];
+ list.appendChild(option);
+ }
+};
+
+// Override some methods of policy.Page.
+
+/**
+ * Shows error message when the session name is invalid.
+ */
+policy.Page.showInvalidSessionNameError = function() {
+ $('invalid-session-name-error').hidden = false;
+};
+
+/**
+ * Disables editing policy values by hiding the main section and shows an
+ * error message instead.
+ */
+policy.Page.disableEditing = function() {
+ $('disable-editing-error').hidden = false;
+ $('main-section').hidden = true;
+};
+
+/**
+ * Disables saving to disk by hiding the 'load session' form and showing an
+ * error message instead.
+ */
+policy.Page.disableSaving = function() {
+ $('saving').hidden = false;
+ $('session-choice').hidden = true;
+};
+
+/** @override */
+policy.Page.setPolicyValues = function(values) {
+ var page = this.getInstance();
+ page.enableEditing();
+ var table = page.policyTables['chrome'];
+ table.setPolicyValues(values.chromePolicies || {});
+ if (values.hasOwnProperty('extensionPolicies')) {
+ for (var extensionId in values.extensionPolicies) {
+ table = page.policyTables['extension-' + extensionId];
+ if (table) {
+ table.setPolicyValues(values.extensionPolicies[extensionId]);
+ }
+ }
+ } else {
+ for (var extension in page.policyTables) {
+ if (extension == 'chrome') {
+ continue;
+ }
+ table = page.policyTables[extension];
+ table.setPolicyValues({});
+ }
+ }
+};
+
+/** @override */
+policy.Page.prototype.initialize = function() {
+ cr.ui.FocusOutlineManager.forDocument(document);
+
+ this.mainSection = $('main-section');
+ this.policyTables = {};
+
+ // Place the initial focus on the session choice input field.
+ $('session-name-field').select();
+
+ $('filter').onsearch = (event) => {
+ for (policyTable in this.policyTables) {
+ this.policyTables[policyTable].setFilterPattern($('filter').value);
+ }
+ };
+
+ $('session-choice').onsubmit = () => {
+ $('invalid-session-name-error').hidden = true;
+ var session = $('session-name-field').value;
+ chrome.send('loadSession', [session]);
+ $('session-name-field').value = '';
+ // Return false in order to prevent the browser from reloading the whole
+ // page.
+ return false;
+ };
+
+ $('show-unset').onchange = () => {
+ for (policyTable in this.policyTables) {
+ this.policyTables[policyTable].filter();
+ }
+ };
+
+ $('enable-editing').onclick = () => {
+ this.enableEditing();
+ chrome.send('resetSession');
+ };
+ // Notify the browser that the page has loaded, causing it to send the
+ // list of all known policies and the values from the default session.
+ chrome.send('initialized');
+};
+
+policy.Page.prototype.enableEditing = function() {
+ $('main-section').hidden = false;
+ $('disable-editing-error').hidden = true;
+};
+
+/**
+ * Extracts current policy values to send to backend for saving.
+ * @return {Object} The dictionary containing policy values.
+ */
+policy.Page.prototype.getDictionary = function() {
+ var result = {chromePolicies: {}, extensionPolicies: {}};
+ for (var id in this.policyTables) {
+ if (id == 'chrome') {
+ result.chromePolicies = this.policyTables[id].getDictionary();
+ } else {
+ const PREFIX_LENGTH = 'extension-'.length;
+ var extensionId = id.substr(PREFIX_LENGTH);
+ result.extensionPolicies[extensionId] =
+ this.policyTables[id].getDictionary();
+ }
+ }
+ return result;
+};
+
+// Specify necessary columns.
+policy.Page.prototype.tableHeadings = ['Name', 'Value', 'Status'];
+
+// Override policy.Policy methods.
+
+/** @override */
+policy.Policy.prototype.decorate = function() {
+ this.updateToggleExpandedValueText_();
+ this.querySelector('.edit-button')
+ .addEventListener('click', this.onValueEditing_.bind(this));
+ this.querySelector('.value-edit-form').onsubmit =
+ this.submitEditedValue_.bind(this);
+ this.querySelector('.toggle-expanded-value')
+ .addEventListener('click', this.toggleExpandedValue_.bind(this));
+};
+
+/** @override */
+policy.Policy.prototype.initialize = function(name, value, unknown) {
+ this.name = name;
+ this.unset = !value;
+ this.unknown = unknown;
+ this.querySelector('.name').textContent = name;
+ if (value) {
+ this.setValue_(value.value);
+ }
+ this.setStatus_(value);
+};
+
+/**
+ * Set the status column.
+ * @param {Object} value Dictionary with information about the policy value.
+ * @private
+ */
+policy.Policy.prototype.setStatus_ = function(value) {
+ var status;
+ if (this.unknown) {
+ status = loadTimeData.getString('unknown');
+ } else if (!value) {
+ status = loadTimeData.getString('unset');
+ } else if (value.error) {
+ status = value.error;
+ } else {
+ status = loadTimeData.getString('ok');
+ }
+ this.querySelector('.status').textContent = status;
+};
+
+/**
+ * Set the policy value.
+ * @param {Object|string|integer|boolean} value Policy value.
+ * @private
+ */
+policy.Policy.prototype.setValue_ = function(value) {
+ this.value = value;
+ if (!value) {
+ value = '';
+ } else if (typeof value != 'string') {
+ value = JSON.stringify(value);
+ }
+ this.unset = !value;
+ this.querySelector('.value').textContent = value;
+ this.querySelector('.expanded-value').textContent = value;
+ this.querySelector('.value-edit-field').value = value;
+};
+
+/** @override */
+policy.Policy.prototype.getValueWidth_ = function(valueContainer) {
+ return valueContainer.querySelector('.value').offsetWidth +
+ valueContainer.querySelector('.edit-button').offsetWidth;
+};
+
+/**
+ * Start editing value.
+ * @private
+ */
+policy.Policy.prototype.onValueEditing_ = function() {
+ this.classList.add('value-editing-on');
+ this.classList.remove('has-overflowed-value');
+ this.querySelector('.value-edit-field').select();
+};
+
+/**
+ * Update the policy to its new edited value.
+ * @private
+ */
+policy.Policy.prototype.submitEditedValue_ = function() {
+ var newValue = this.querySelector('.value-edit-field').value;
+ this.setValue_(newValue);
+ this.setStatus_(newValue);
+ this.classList.remove('value-editing-on');
+ this.querySelector('.value-container').valueWidth = undefined;
+ this.checkOverflow();
+ var showUnset = $('show-unset').checked;
+ this.hidden = this.unset && !showUnset ||
+ this.name.toLowerCase().indexOf(this.parentNode.filterPattern_) == -1;
+ chrome.send('updateSession', [policy.Page.getInstance().getDictionary()]);
+ return false;
+};
+
+// Override policy.PolicyTable methods.
+
+/**
+ * Get policy values stored in this table.
+ * @returns {Object} Dictionary with policy values.
+ */
+policy.PolicyTable.prototype.getDictionary = function() {
+ var result = {};
+ var policies = this.getElementsByTagName('tbody');
+ for (var i = 0; i < policies.length; i++) {
+ var policy = policies[i];
+ if (policy.unset) {
+ continue;
+ }
+ result[policy.name] = {value: policy.value};
+ }
+ return result;
+};
+
+// Add error showing function.
+
+/**
+ * Shows an error message to the user.
+ * @param {String} message_name Identifier for the error message.
+ */
+policy.showErrorMessage = function(message_name) {
+ // TODO(urusant): improve error showing.
+ alert(loadTimeData.getString(message_name));
+ console.log(loadTimeData.getString(message_name));
+};
+
+// Call the main inttialization function when the page finishes loading.
+document.addEventListener(
+ 'DOMContentLoaded',
+ policy.Page.getInstance().initialize.bind(policy.Page.getInstance()));
diff --git a/chromium/chrome/browser/resources/print_preview/data/app_state.js b/chromium/chrome/browser/resources/print_preview/data/app_state.js
index 06541447351..6e14236ee9c 100644
--- a/chromium/chrome/browser/resources/print_preview/data/app_state.js
+++ b/chromium/chrome/browser/resources/print_preview/data/app_state.js
@@ -26,149 +26,113 @@ print_preview.AppStateField = {
VENDOR_OPTIONS: 'vendorOptions'
};
+
/**
- * Object used to represent a recent destination in the app state.
- * @constructor
- * @struct
+ * @typedef {{id: string,
+ * origin: print_preview.DestinationOrigin,
+ * account: string,
+ * capabilities: ?print_preview.Cdd,
+ * displayName: string,
+ * extensionId: string,
+ * extensionName: string}}
*/
-function RecentDestination(destination) {
- /**
- * ID of the RecentDestination.
- * @type {string}
- */
- this.id = destination.id;
-
- /**
- * Origin of the RecentDestination.
- * @type {string}
- */
- this.origin = destination.origin;
-
- /**
- * Account the RecentDestination is registered for.
- * @type {string}
- */
- this.account = destination.account || '';
-
- /**
- * CDD of the RecentDestination.
- * @type {print_preview.Cdd}
- */
- this.capabilities = destination.capabilities;
-
- /**
- * Name of the RecentDestination.
- * @type {string}
- */
- this.name = destination.name || '';
-
- /**
- * Extension ID associated with the RecentDestination.
- * @type {string}
- */
- this.extensionId = destination.extension_id || '';
+print_preview.AppStateRecentDestination;
- /**
- * Extension name associated with the RecentDestination.
- * @type {string}
- */
- this.extensionName = destination.extension_name || '';
+/**
+ * Creates a |AppStateRecentDestination| to represent |destination| in the app
+ * state.
+ * @param {!print_preview.Destination} destination The destination to store.
+ * @return {!print_preview.AppStateRecentDestination}
+ */
+function makeRecentDestination(destination) {
+ return {
+ id: destination.id_,
+ origin: destination.origin_,
+ account: destination.account_ || '',
+ capabilities: destination.capabilities,
+ displayName: destination.displayName_ || '',
+ extensionId: destination.extensionId_ || '',
+ extensionName: destination.extensionName_ || '',
+ };
}
cr.define('print_preview', function() {
'use strict';
-
- /**
- * Object used to get and persist the print preview application state.
- * @constructor
- */
- function AppState() {
- /**
- * Internal representation of application state.
- * @private {Object}
- */
- this.state_ = {};
- this.state_[print_preview.AppStateField.VERSION] = AppState.VERSION_;
- this.state_[print_preview.AppStateField.RECENT_DESTINATIONS] = [];
-
+ class AppState {
/**
- * Whether the app state has been initialized. The app state will ignore all
- * writes until it has been initialized.
- * @private {boolean}
+ * Object used to get and persist the print preview application state.
*/
- this.isInitialized_ = false;
+ constructor() {
+ /**
+ * Internal representation of application state.
+ * @private {!Object}
+ */
+ this.state_ = {};
+ this.state_[print_preview.AppStateField.VERSION] = AppState.VERSION_;
+ this.state_[print_preview.AppStateField.RECENT_DESTINATIONS] = [];
- /**
- * Native Layer object to use for sending app state to C++ handler.
- * @private {!print_preview.NativeLayer}
- */
- this.nativeLayer_ = print_preview.NativeLayer.getInstance();
- }
-
- /**
- * Number of recent print destinations to store across browser sessions.
- * @const {number}
- */
- AppState.NUM_DESTINATIONS_ = 3;
+ /**
+ * Whether the app state has been initialized. The app state will ignore
+ * all writes until it has been initialized.
+ * @private {boolean}
+ */
+ this.isInitialized_ = false;
- /**
- * Current version of the app state. This value helps to understand how to
- * parse earlier versions of the app state.
- * @type {number}
- * @const
- * @private
- */
- AppState.VERSION_ = 2;
+ /**
+ * Native Layer object to use for sending app state to C++ handler.
+ * @private {!print_preview.NativeLayer}
+ */
+ this.nativeLayer_ = print_preview.NativeLayer.getInstance();
+ }
- AppState.prototype = {
/**
- * @return {?RecentDestination} The most recent destination,
- * which is currently the selected destination.
+ * @return {?print_preview.AppStateRecentDestination} The most recent
+ * destination, which is currently the selected destination.
*/
get selectedDestination() {
return (this.state_[print_preview.AppStateField.RECENT_DESTINATIONS]
.length > 0) ?
this.state_[print_preview.AppStateField.RECENT_DESTINATIONS][0] :
null;
- },
+ }
/**
* @return {boolean} Whether the selected destination is valid.
*/
- isSelectedDestinationValid: function() {
- return !!this.selectedDestination && !!this.selectedDestination.id &&
- !!this.selectedDestination.origin;
- },
+ isSelectedDestinationValid() {
+ var selected = this.selectedDestination;
+ return !!selected && !!selected.id && !!selected.origin;
+ }
/**
- * @return {?Array<!RecentDestination>} The
+ * @return {?Array<!print_preview.AppStateRecentDestination>} The
* AppState.NUM_DESTINATIONS_ most recent destinations.
*/
get recentDestinations() {
return this.state_[print_preview.AppStateField.RECENT_DESTINATIONS];
- },
+ }
/**
* @param {!print_preview.AppStateField} field App state field to check if
* set.
* @return {boolean} Whether a field has been set in the app state.
*/
- hasField: function(field) {
+ hasField(field) {
return this.state_.hasOwnProperty(field);
- },
+ }
/**
* @param {!print_preview.AppStateField} field App state field to get.
* @return {?} Value of the app state field.
*/
- getField: function(field) {
+ getField(field) {
if (field == print_preview.AppStateField.CUSTOM_MARGINS) {
return this.state_[field] ?
print_preview.Margins.parse(this.state_[field]) :
null;
}
return this.state_[field];
- },
+ }
/**
* Initializes the app state from a serialized string returned by the native
@@ -176,12 +140,13 @@ cr.define('print_preview', function() {
* @param {?string} serializedAppStateStr Serialized string representation
* of the app state.
*/
- init: function(serializedAppStateStr) {
+ init(serializedAppStateStr) {
if (serializedAppStateStr) {
try {
var state = JSON.parse(serializedAppStateStr);
- if (state[print_preview.AppStateField.VERSION] == AppState.VERSION_) {
- this.state_ = /** @type {Object} */ (state);
+ if (!!state &&
+ state[print_preview.AppStateField.VERSION] == AppState.VERSION_) {
+ this.state_ = /** @type {!Object} */ (state);
}
} catch (e) {
console.error('Unable to parse state: ' + e);
@@ -209,21 +174,21 @@ cr.define('print_preview', function() {
this.state_[print_preview.AppStateField.RECENT_DESTINATIONS].length =
AppState.NUM_DESTINATIONS_;
}
- },
+ }
/**
* Sets to initialized state. Now object will accept persist requests.
*/
- setInitialized: function() {
+ setInitialized() {
this.isInitialized_ = true;
- },
+ }
/**
* Persists the given value for the given field.
* @param {!print_preview.AppStateField} field Field to persist.
* @param {?} value Value of field to persist.
*/
- persistField: function(field, value) {
+ persistField(field, value) {
if (!this.isInitialized_)
return;
if (field == print_preview.AppStateField.CUSTOM_MARGINS) {
@@ -232,19 +197,19 @@ cr.define('print_preview', function() {
this.state_[field] = value;
}
this.persist_();
- },
+ }
/**
* Persists the selected destination.
* @param {!print_preview.Destination} dest Destination to persist.
*/
- persistSelectedDestination: function(dest) {
+ persistSelectedDestination(dest) {
if (!this.isInitialized_)
return;
// Determine if this destination is already in the recent destinations,
// and where in the array it is located.
- var newDestination = new RecentDestination(dest);
+ var newDestination = makeRecentDestination(dest);
var indexFound =
this.state_[print_preview.AppStateField.RECENT_DESTINATIONS]
.findIndex(function(recent) {
@@ -275,16 +240,33 @@ cr.define('print_preview', function() {
0, 0, newDestination);
this.persist_();
- },
+ }
/**
* Calls into the native layer to persist the application state.
* @private
*/
- persist_: function() {
+ persist_() {
this.nativeLayer_.saveAppState(JSON.stringify(this.state_));
}
- };
+ }
+
+ /**
+ * Number of recent print destinations to store across browser sessions.
+ * @const {number}
+ * @private
+ */
+ AppState.NUM_DESTINATIONS_ = 3;
- return {AppState: AppState};
+ /**
+ * Current version of the app state. This value helps to understand how to
+ * parse earlier versions of the app state.
+ * @const {number}
+ * @private
+ */
+ AppState.VERSION_ = 2;
+
+ return {
+ AppState: AppState,
+ };
});
diff --git a/chromium/chrome/browser/resources/print_preview/data/capabilities_holder.js b/chromium/chrome/browser/resources/print_preview/data/capabilities_holder.js
index 1201ae2d3ac..edb8094ca7e 100644
--- a/chromium/chrome/browser/resources/print_preview/data/capabilities_holder.js
+++ b/chromium/chrome/browser/resources/print_preview/data/capabilities_holder.js
@@ -5,33 +5,29 @@
cr.define('print_preview', function() {
'use strict';
- /**
- * Mutable reference to a CDD object.
- * @constructor
- */
- function CapabilitiesHolder() {
- /**
- * Reference to the capabilities object.
- * @type {?print_preview.Cdd}
- * @private
- */
- this.capabilities_ = null;
- }
+ /* Mutable reference to a CDD object. */
+ class CapabilitiesHolder {
+ constructor() {
+ /**
+ * Reference to the capabilities object.
+ * @private {?print_preview.Cdd}
+ */
+ this.capabilities_ = null;
+ }
- CapabilitiesHolder.prototype = {
/** @return {?print_preview.Cdd} The instance held by the holder. */
- get: function() {
+ get() {
return this.capabilities_;
- },
+ }
/**
* @param {!print_preview.Cdd} capabilities New instance to put into the
* holder.
*/
- set: function(capabilities) {
+ set(capabilities) {
this.capabilities_ = capabilities;
}
- };
+ }
// Export
return {CapabilitiesHolder: CapabilitiesHolder};
diff --git a/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js b/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js
index b336f743504..f4dff0458ad 100644
--- a/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js
+++ b/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js
@@ -5,39 +5,38 @@
cr.define('print_preview', function() {
'use strict';
- /**
- * Immutable two dimensional point in space. The units of the dimensions are
- * undefined.
- * @param {number} x X-dimension of the point.
- * @param {number} y Y-dimension of the point.
- * @constructor
- */
- function Coordinate2d(x, y) {
+ class Coordinate2d {
/**
- * X-dimension of the point.
- * @type {number}
- * @private
+ * Immutable two dimensional point in space. The units of the dimensions are
+ * undefined.
+ * @param {number} x X-dimension of the point.
+ * @param {number} y Y-dimension of the point.
*/
- this.x_ = x;
+ constructor(x, y) {
+ /**
+ * X-dimension of the point.
+ * @type {number}
+ * @private
+ */
+ this.x_ = x;
- /**
- * Y-dimension of the point.
- * @type {number}
- * @private
- */
- this.y_ = y;
- }
+ /**
+ * Y-dimension of the point.
+ * @type {number}
+ * @private
+ */
+ this.y_ = y;
+ }
- Coordinate2d.prototype = {
/** @return {number} X-dimension of the point. */
get x() {
return this.x_;
- },
+ }
/** @return {number} Y-dimension of the point. */
get y() {
return this.y_;
- },
+ }
/**
* @param {number} x Amount to translate in the X dimension.
@@ -45,27 +44,27 @@ cr.define('print_preview', function() {
* @return {!print_preview.Coordinate2d} A new two-dimensional point
* translated along the X and Y dimensions.
*/
- translate: function(x, y) {
+ translate(x, y) {
return new Coordinate2d(this.x_ + x, this.y_ + y);
- },
+ }
/**
* @param {number} factor Amount to scale the X and Y dimensions.
* @return {!print_preview.Coordinate2d} A new two-dimensional point scaled
* by the given factor.
*/
- scale: function(factor) {
+ scale(factor) {
return new Coordinate2d(this.x_ * factor, this.y_ * factor);
- },
+ }
/**
* @param {print_preview.Coordinate2d} other The point to compare against.
* @return {boolean} Whether another point is equal to this one.
*/
- equals: function(other) {
+ equals(other) {
return other != null && this.x_ == other.x_ && this.y_ == other.y_;
}
- };
+ }
// Export
return {Coordinate2d: Coordinate2d};
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination.js b/chromium/chrome/browser/resources/print_preview/data/destination.js
index 24e93cb4e8a..e98026cea19 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination.js
@@ -96,226 +96,192 @@ print_preview.Cdd;
cr.define('print_preview', function() {
'use strict';
- /**
- * Print destination data object that holds data for both local and cloud
- * destinations.
- * @param {string} id ID of the destination.
- * @param {!print_preview.DestinationType} type Type of the destination.
- * @param {!print_preview.DestinationOrigin} origin Origin of the
- * destination.
- * @param {string} displayName Display name of the destination.
- * @param {boolean} isRecent Whether the destination has been used recently.
- * @param {!print_preview.DestinationConnectionStatus} connectionStatus
- * Connection status of the print destination.
- * @param {{tags: (Array<string>|undefined),
- * isOwned: (boolean|undefined),
- * isEnterprisePrinter: (boolean|undefined),
- * account: (string|undefined),
- * lastAccessTime: (number|undefined),
- * cloudID: (string|undefined),
- * provisionalType:
- * (print_preview.DestinationProvisionalType|undefined),
- * extensionId: (string|undefined),
- * extensionName: (string|undefined),
- * description: (string|undefined)}=} opt_params Optional parameters
- * for the destination.
- * @constructor
- */
- function Destination(
- id, type, origin, displayName, isRecent, connectionStatus, opt_params) {
- /**
- * ID of the destination.
- * @private {string}
- */
- this.id_ = id;
-
- /**
- * Type of the destination.
- * @private {!print_preview.DestinationType}
- */
- this.type_ = type;
-
- /**
- * Origin of the destination.
- * @private {!print_preview.DestinationOrigin}
- */
- this.origin_ = origin;
-
- /**
- * Display name of the destination.
- * @private {string}
- */
- this.displayName_ = displayName || '';
-
- /**
- * Whether the destination has been used recently.
- * @private {boolean}
- */
- this.isRecent_ = isRecent;
-
- /**
- * Tags associated with the destination.
- * @private {!Array<string>}
- */
- this.tags_ = (opt_params && opt_params.tags) || [];
-
- /**
- * Print capabilities of the destination.
- * @private {?print_preview.Cdd}
- */
- this.capabilities_ = null;
-
- /**
- * Whether the destination is owned by the user.
- * @private {boolean}
- */
- this.isOwned_ = (opt_params && opt_params.isOwned) || false;
-
- /**
- * Whether the destination is an enterprise policy controlled printer.
- * @private {boolean}
- */
- this.isEnterprisePrinter_ =
- (opt_params && opt_params.isEnterprisePrinter) || false;
-
- /**
- * Account this destination is registered for, if known.
- * @private {string}
- */
- this.account_ = (opt_params && opt_params.account) || '';
-
- /**
- * Cache of destination location fetched from tags.
- * @private {?string}
- */
- this.location_ = null;
-
- /**
- * Printer description.
- * @private {string}
- */
- this.description_ = (opt_params && opt_params.description) || '';
-
- /**
- * Connection status of the destination.
- * @private {!print_preview.DestinationConnectionStatus}
- */
- this.connectionStatus_ = connectionStatus;
-
- /**
- * Number of milliseconds since the epoch when the printer was last
- * accessed.
- * @private {number}
- */
- this.lastAccessTime_ =
- (opt_params && opt_params.lastAccessTime) || Date.now();
-
- /**
- * Cloud ID for Privet printers.
- * @private {string}
- */
- this.cloudID_ = (opt_params && opt_params.cloudID) || '';
-
+ class Destination {
/**
- * Extension ID for extension managed printers.
- * @private {string}
- */
- this.extensionId_ = (opt_params && opt_params.extensionId) || '';
-
- /**
- * Extension name for extension managed printers.
- * @private {string}
- */
- this.extensionName_ = (opt_params && opt_params.extensionName) || '';
-
- /**
- * Different from {@code print_preview.DestinationProvisionalType.NONE} if
- * the destination is provisional. Provisional destinations cannot be
- * selected as they are, but have to be resolved first (i.e. extra steps
- * have to be taken to get actual destination properties, which should
- * replace the provisional ones). Provisional destination resolvment flow
- * will be started when the user attempts to select the destination in
- * search UI.
- * @private {print_preview.DestinationProvisionalType}
- */
- this.provisionalType_ = (opt_params && opt_params.provisionalType) ||
- print_preview.DestinationProvisionalType.NONE;
-
- assert(
- this.provisionalType_ !=
- print_preview.DestinationProvisionalType.NEEDS_USB_PERMISSION ||
- this.isExtension,
- 'Provisional USB destination only supprted with extension origin.');
- }
-
- /**
- * Prefix of the location destination tag.
- * @type {!Array<string>}
- * @const
- */
- Destination.LOCATION_TAG_PREFIXES =
- ['__cp__location=', '__cp__printer-location='];
+ * Print destination data object that holds data for both local and cloud
+ * destinations.
+ * @param {string} id ID of the destination.
+ * @param {!print_preview.DestinationType} type Type of the destination.
+ * @param {!print_preview.DestinationOrigin} origin Origin of the
+ * destination.
+ * @param {string} displayName Display name of the destination.
+ * @param {boolean} isRecent Whether the destination has been used recently.
+ * @param {!print_preview.DestinationConnectionStatus} connectionStatus
+ * Connection status of the print destination.
+ * @param {{tags: (Array<string>|undefined),
+ * isOwned: (boolean|undefined),
+ * isEnterprisePrinter: (boolean|undefined),
+ * account: (string|undefined),
+ * lastAccessTime: (number|undefined),
+ * cloudID: (string|undefined),
+ * provisionalType:
+ * (print_preview.DestinationProvisionalType|undefined),
+ * extensionId: (string|undefined),
+ * extensionName: (string|undefined),
+ * description: (string|undefined)}=} opt_params Optional
+ * parameters for the destination.
+ */
+ constructor(
+ id, type, origin, displayName, isRecent, connectionStatus, opt_params) {
+ /**
+ * ID of the destination.
+ * @private {string}
+ */
+ this.id_ = id;
+
+ /**
+ * Type of the destination.
+ * @private {!print_preview.DestinationType}
+ */
+ this.type_ = type;
+
+ /**
+ * Origin of the destination.
+ * @private {!print_preview.DestinationOrigin}
+ */
+ this.origin_ = origin;
+
+ /**
+ * Display name of the destination.
+ * @private {string}
+ */
+ this.displayName_ = displayName || '';
+
+ /**
+ * Whether the destination has been used recently.
+ * @private {boolean}
+ */
+ this.isRecent_ = isRecent;
- /**
- * Enumeration of Google-promoted destination IDs.
- * @enum {string}
- */
- Destination.GooglePromotedId = {
- DOCS: '__google__docs',
- SAVE_AS_PDF: 'Save as PDF'
- };
+ /**
+ * Tags associated with the destination.
+ * @private {!Array<string>}
+ */
+ this.tags_ = (opt_params && opt_params.tags) || [];
+
+ /**
+ * Print capabilities of the destination.
+ * @private {?print_preview.Cdd}
+ */
+ this.capabilities_ = null;
+
+ /**
+ * Whether the destination is owned by the user.
+ * @private {boolean}
+ */
+ this.isOwned_ = (opt_params && opt_params.isOwned) || false;
+
+ /**
+ * Whether the destination is an enterprise policy controlled printer.
+ * @private {boolean}
+ */
+ this.isEnterprisePrinter_ =
+ (opt_params && opt_params.isEnterprisePrinter) || false;
+
+ /**
+ * Account this destination is registered for, if known.
+ * @private {string}
+ */
+ this.account_ = (opt_params && opt_params.account) || '';
+
+ /**
+ * Cache of destination location fetched from tags.
+ * @private {?string}
+ */
+ this.location_ = null;
+
+ /**
+ * Printer description.
+ * @private {string}
+ */
+ this.description_ = (opt_params && opt_params.description) || '';
+
+ /**
+ * Connection status of the destination.
+ * @private {!print_preview.DestinationConnectionStatus}
+ */
+ this.connectionStatus_ = connectionStatus;
+
+ /**
+ * Number of milliseconds since the epoch when the printer was last
+ * accessed.
+ * @private {number}
+ */
+ this.lastAccessTime_ =
+ (opt_params && opt_params.lastAccessTime) || Date.now();
+
+ /**
+ * Cloud ID for Privet printers.
+ * @private {string}
+ */
+ this.cloudID_ = (opt_params && opt_params.cloudID) || '';
+
+ /**
+ * Extension ID for extension managed printers.
+ * @private {string}
+ */
+ this.extensionId_ = (opt_params && opt_params.extensionId) || '';
+
+ /**
+ * Extension name for extension managed printers.
+ * @private {string}
+ */
+ this.extensionName_ = (opt_params && opt_params.extensionName) || '';
+
+ /**
+ * Different from {@code print_preview.DestinationProvisionalType.NONE} if
+ * the destination is provisional. Provisional destinations cannot be
+ * selected as they are, but have to be resolved first (i.e. extra steps
+ * have to be taken to get actual destination properties, which should
+ * replace the provisional ones). Provisional destination resolvment flow
+ * will be started when the user attempts to select the destination in
+ * search UI.
+ * @private {print_preview.DestinationProvisionalType}
+ */
+ this.provisionalType_ = (opt_params && opt_params.provisionalType) ||
+ print_preview.DestinationProvisionalType.NONE;
- /**
- * Enumeration of relative icon URLs for various types of destinations.
- * @enum {string}
- * @private
- */
- Destination.IconUrl_ = {
- CLOUD: 'images/printer.png',
- CLOUD_SHARED: 'images/printer_shared.png',
- LOCAL: 'images/printer.png',
- MOBILE: 'images/mobile.png',
- MOBILE_SHARED: 'images/mobile_shared.png',
- THIRD_PARTY: 'images/third_party.png',
- PDF: 'images/pdf.png',
- DOCS: 'images/google_doc.png',
- ENTERPRISE: 'images/business.svg'
- };
+ assert(
+ this.provisionalType_ !=
+ print_preview.DestinationProvisionalType
+ .NEEDS_USB_PERMISSION ||
+ this.isExtension,
+ 'Provisional USB destination only supprted with extension origin.');
+ }
- Destination.prototype = {
/** @return {string} ID of the destination. */
get id() {
return this.id_;
- },
+ }
/** @return {!print_preview.DestinationType} Type of the destination. */
get type() {
return this.type_;
- },
+ }
/**
* @return {!print_preview.DestinationOrigin} Origin of the destination.
*/
get origin() {
return this.origin_;
- },
+ }
/** @return {string} Display name of the destination. */
get displayName() {
return this.displayName_;
- },
+ }
/** @return {boolean} Whether the destination has been used recently. */
get isRecent() {
return this.isRecent_;
- },
+ }
/**
* @param {boolean} isRecent Whether the destination has been used recently.
*/
set isRecent(isRecent) {
this.isRecent_ = isRecent;
- },
+ }
/**
* @return {boolean} Whether the user owns the destination. Only applies to
@@ -323,14 +289,14 @@ cr.define('print_preview', function() {
*/
get isOwned() {
return this.isOwned_;
- },
+ }
/**
* @return {string} Account this destination is registered for, if known.
*/
get account() {
return this.account_;
- },
+ }
/** @return {boolean} Whether the destination is local or cloud-based. */
get isLocal() {
@@ -340,12 +306,12 @@ cr.define('print_preview', function() {
(this.origin_ == print_preview.DestinationOrigin.PRIVET &&
this.connectionStatus_ !=
print_preview.DestinationConnectionStatus.UNREGISTERED);
- },
+ }
/** @return {boolean} Whether the destination is a Privet local printer */
get isPrivet() {
return this.origin_ == print_preview.DestinationOrigin.PRIVET;
- },
+ }
/**
* @return {boolean} Whether the destination is an extension managed
@@ -353,7 +319,7 @@ cr.define('print_preview', function() {
*/
get isExtension() {
return this.origin_ == print_preview.DestinationOrigin.EXTENSION;
- },
+ }
/**
* @return {string} The location of the destination, or an empty string if
@@ -362,17 +328,17 @@ cr.define('print_preview', function() {
get location() {
if (this.location_ == null) {
this.location_ = '';
- this.tags_.some(function(tag) {
- return Destination.LOCATION_TAG_PREFIXES.some(function(prefix) {
+ this.tags_.some(tag => {
+ return Destination.LOCATION_TAG_PREFIXES.some(prefix => {
if (tag.startsWith(prefix)) {
this.location_ = tag.substring(prefix.length) || '';
return true;
}
- }, this);
- }, this);
+ });
+ });
}
return this.location_;
- },
+ }
/**
* @return {string} The description of the destination, or an empty string,
@@ -380,7 +346,7 @@ cr.define('print_preview', function() {
*/
get description() {
return this.description_;
- },
+ }
/**
* @return {string} Most relevant string to help user to identify this
@@ -391,17 +357,17 @@ cr.define('print_preview', function() {
return this.account_;
}
return this.location || this.extensionName || this.description;
- },
+ }
/** @return {!Array<string>} Tags associated with the destination. */
get tags() {
return this.tags_.slice(0);
- },
+ }
/** @return {string} Cloud ID associated with the destination */
get cloudID() {
return this.cloudID_;
- },
+ }
/**
* @return {string} Extension ID associated with the destination. Non-empty
@@ -409,7 +375,7 @@ cr.define('print_preview', function() {
*/
get extensionId() {
return this.extensionId_;
- },
+ }
/**
* @return {string} Extension name associated with the destination.
@@ -417,20 +383,21 @@ cr.define('print_preview', function() {
*/
get extensionName() {
return this.extensionName_;
- },
+ }
/** @return {?print_preview.Cdd} Print capabilities of the destination. */
get capabilities() {
return this.capabilities_;
- },
+ }
/**
- * @param {!print_preview.Cdd} capabilities Print capabilities of the
+ * @param {?print_preview.Cdd} capabilities Print capabilities of the
* destination.
*/
set capabilities(capabilities) {
- this.capabilities_ = capabilities;
- },
+ if (capabilities)
+ this.capabilities_ = capabilities;
+ }
/**
* @return {!print_preview.DestinationConnectionStatus} Connection status
@@ -438,7 +405,7 @@ cr.define('print_preview', function() {
*/
get connectionStatus() {
return this.connectionStatus_;
- },
+ }
/**
* @param {!print_preview.DestinationConnectionStatus} status Connection
@@ -446,7 +413,7 @@ cr.define('print_preview', function() {
*/
set connectionStatus(status) {
this.connectionStatus_ = status;
- },
+ }
/** @return {boolean} Whether the destination is considered offline. */
get isOffline() {
@@ -456,7 +423,7 @@ cr.define('print_preview', function() {
print_preview.DestinationConnectionStatus.DORMANT
],
this.connectionStatus_);
- },
+ }
/** @return {string} Human readable status for offline destination. */
get offlineStatusText() {
@@ -475,7 +442,7 @@ cr.define('print_preview', function() {
offlineMessageId = 'offline';
}
return loadTimeData.getString(offlineMessageId);
- },
+ }
/**
* @return {number} Number of milliseconds since the epoch when the printer
@@ -483,7 +450,7 @@ cr.define('print_preview', function() {
*/
get lastAccessTime() {
return this.lastAccessTime_;
- },
+ }
/** @return {string} Relative URL of the destination's icon. */
get iconUrl() {
@@ -497,7 +464,7 @@ cr.define('print_preview', function() {
return Destination.IconUrl_.ENTERPRISE;
}
if (this.isLocal) {
- return Destination.IconUrl_.LOCAL;
+ return Destination.IconUrl_.LOCAL_1X;
}
if (this.type_ == print_preview.DestinationType.MOBILE && this.isOwned_) {
return Destination.IconUrl_.MOBILE;
@@ -506,10 +473,30 @@ cr.define('print_preview', function() {
return Destination.IconUrl_.MOBILE_SHARED;
}
if (this.isOwned_) {
- return Destination.IconUrl_.CLOUD;
+ return Destination.IconUrl_.CLOUD_1X;
+ }
+ return Destination.IconUrl_.CLOUD_SHARED_1X;
+ }
+
+ /**
+ * @return {string} The srcset="" attribute of a destination. Generally used
+ * for a 2x (e.g. HiDPI) icon. Can be empty or of the format '<url> 2x'.
+ */
+ get srcSet() {
+ let srcSetIcon = '';
+ let iconUrl = this.iconUrl;
+ if (iconUrl == Destination.IconUrl_.LOCAL_1X) {
+ srcSetIcon = Destination.IconUrl_.LOCAL_2X;
+ } else if (iconUrl == Destination.IconUrl_.CLOUD_1X) {
+ srcSetIcon = Destination.IconUrl_.CLOUD_2X;
+ } else if (iconUrl == Destination.IconUrl_.CLOUD_SHARED_1X) {
+ srcSetIcon = Destination.IconUrl_.CLOUD_SHARED_2X;
}
- return Destination.IconUrl_.CLOUD_SHARED;
- },
+ if (srcSetIcon) {
+ srcSetIcon += ' 2x';
+ }
+ return srcSetIcon;
+ }
/**
* @return {!Array<string>} Properties (besides display name) to match
@@ -517,7 +504,7 @@ cr.define('print_preview', function() {
*/
get extraPropertiesToMatch() {
return [this.location, this.description];
- },
+ }
/**
* Matches a query against the destination.
@@ -525,13 +512,11 @@ cr.define('print_preview', function() {
* @return {boolean} {@code true} if the query matches this destination,
* {@code false} otherwise.
*/
- matches: function(query) {
+ matches(query) {
return !!this.displayName_.match(query) ||
!!this.extensionName_.match(query) ||
- this.extraPropertiesToMatch.some(function(property) {
- return property.match(query);
- });
- },
+ this.extraPropertiesToMatch.some(p => p.match(query));
+ }
/**
* Gets the destination's provisional type.
@@ -539,7 +524,7 @@ cr.define('print_preview', function() {
*/
get provisionalType() {
return this.provisionalType_;
- },
+ }
/**
* Whether the destinaion is provisional.
@@ -548,7 +533,7 @@ cr.define('print_preview', function() {
get isProvisional() {
return this.provisionalType_ !=
print_preview.DestinationProvisionalType.NONE;
- },
+ }
/**
* Whether the printer is enterprise policy controlled printer.
@@ -556,7 +541,44 @@ cr.define('print_preview', function() {
*/
get isEnterprisePrinter() {
return this.isEnterprisePrinter_;
- },
+ }
+ }
+
+ /**
+ * Prefix of the location destination tag.
+ * @type {!Array<string>}
+ * @const
+ */
+ Destination.LOCATION_TAG_PREFIXES =
+ ['__cp__location=', '__cp__printer-location='];
+
+ /**
+ * Enumeration of Google-promoted destination IDs.
+ * @enum {string}
+ */
+ Destination.GooglePromotedId = {
+ DOCS: '__google__docs',
+ SAVE_AS_PDF: 'Save as PDF'
+ };
+
+ /**
+ * Enumeration of relative icon URLs for various types of destinations.
+ * @enum {string}
+ * @private
+ */
+ Destination.IconUrl_ = {
+ CLOUD_1X: 'images/1x/printer.png',
+ CLOUD_2X: 'images/2x/printer.png',
+ CLOUD_SHARED_1X: 'images/1x/printer_shared.png',
+ CLOUD_SHARED_2X: 'images/2x/printer_shared.png',
+ LOCAL_1X: 'images/1x/printer.png',
+ LOCAL_2X: 'images/2x/printer.png',
+ MOBILE: 'images/mobile.png',
+ MOBILE_SHARED: 'images/mobile_shared.png',
+ THIRD_PARTY: 'images/third_party.png',
+ PDF: 'images/pdf.png',
+ DOCS: 'images/google_doc.png',
+ ENTERPRISE: 'images/business.svg'
};
// Export
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination_match.js b/chromium/chrome/browser/resources/print_preview/data/destination_match.js
index 3152abe2342..165aa22f013 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination_match.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination_match.js
@@ -4,59 +4,74 @@
cr.define('print_preview', function() {
'use strict';
-
/**
- * A set of key parameters describing a destination used to determine
- * if two destinations are the same.
- * @param {!Array<!print_preview.DestinationOrigin>} origins Match
- * destinations from these origins.
- * @param {RegExp} idRegExp Match destination's id.
- * @param {RegExp} displayNameRegExp Match destination's displayName.
- * @param {boolean} skipVirtualDestinations Whether to ignore virtual
- * destinations, for example, Save as PDF.
- * @constructor
+ * Converts DestinationOrigin to PrinterType.
+ * @param {!print_preview.DestinationOrigin} origin The printer's
+ * destination origin.
+ * return {?print_preview.PrinterType} The corresponding PrinterType.
+ * Returns null if no match is found.
*/
- function DestinationMatch(
- origins, idRegExp, displayNameRegExp, skipVirtualDestinations) {
- /** @private {!Array<!print_preview.DestinationOrigin>} */
- this.origins_ = origins;
+ var originToType = function(origin) {
+ if (origin === print_preview.DestinationOrigin.LOCAL ||
+ origin === print_preview.DestinationOrigin.CROS) {
+ return print_preview.PrinterType.LOCAL_PRINTER;
+ }
+ if (origin === print_preview.DestinationOrigin.PRIVET)
+ return print_preview.PrinterType.PRIVET_PRINTER;
+ if (origin === print_preview.DestinationOrigin.EXTENSION)
+ return print_preview.PrinterType.EXTENSION_PRINTER;
+ return null;
+ };
- /** @private {RegExp} */
- this.idRegExp_ = idRegExp;
+ class DestinationMatch {
+ /**
+ * A set of key parameters describing a destination used to determine
+ * if two destinations are the same.
+ * @param {!Array<!print_preview.DestinationOrigin>} origins Match
+ * destinations from these origins.
+ * @param {RegExp} idRegExp Match destination's id.
+ * @param {RegExp} displayNameRegExp Match destination's displayName.
+ * @param {boolean} skipVirtualDestinations Whether to ignore virtual
+ * destinations, for example, Save as PDF.
+ */
+ constructor(origins, idRegExp, displayNameRegExp, skipVirtualDestinations) {
+ /** @private {!Array<!print_preview.DestinationOrigin>} */
+ this.origins_ = origins;
- /** @private {RegExp} */
- this.displayNameRegExp_ = displayNameRegExp;
+ /** @private {RegExp} */
+ this.idRegExp_ = idRegExp;
- /** @private {boolean} */
- this.skipVirtualDestinations_ = skipVirtualDestinations;
- }
+ /** @private {RegExp} */
+ this.displayNameRegExp_ = displayNameRegExp;
- DestinationMatch.prototype = {
+ /** @private {boolean} */
+ this.skipVirtualDestinations_ = skipVirtualDestinations;
+ }
/**
* @param {string} origin Origin to match.
* @return {boolean} Whether the origin is one of the {@code origins_}.
*/
- matchOrigin: function(origin) {
+ matchOrigin(origin) {
return arrayContains(this.origins_, origin);
- },
+ }
/**
* @param {string} id Id of the destination.
* @param {string} origin Origin of the destination.
* @return {boolean} Whether destination is the same as initial.
*/
- matchIdAndOrigin: function(id, origin) {
+ matchIdAndOrigin(id, origin) {
return this.matchOrigin(origin) && !!this.idRegExp_ &&
this.idRegExp_.test(id);
- },
+ }
/**
* @param {!print_preview.Destination} destination Destination to match.
* @return {boolean} Whether {@code destination} matches the last user
* selected one.
*/
- match: function(destination) {
+ match(destination) {
if (!this.matchOrigin(destination.origin)) {
return false;
}
@@ -72,7 +87,7 @@ cr.define('print_preview', function() {
return false;
}
return true;
- },
+ }
/**
* @param {!print_preview.Destination} destination Destination to check.
@@ -80,7 +95,7 @@ cr.define('print_preview', function() {
* destination selection.
* @private
*/
- isVirtualDestination_: function(destination) {
+ isVirtualDestination_(destination) {
if (destination.origin == print_preview.DestinationOrigin.LOCAL) {
return arrayContains(
[print_preview.Destination.GooglePromotedId.SAVE_AS_PDF],
@@ -89,8 +104,16 @@ cr.define('print_preview', function() {
return arrayContains(
[print_preview.Destination.GooglePromotedId.DOCS], destination.id);
}
- };
+
+ /**
+ * @return {?print_preview.PrinterType} The printer type of this
+ * destination match. Will return null for Cloud destinations.
+ */
+ getType() {
+ return originToType(this.origins_[0]);
+ }
+ }
// Export
- return {DestinationMatch: DestinationMatch};
+ return {originToType: originToType, DestinationMatch: DestinationMatch};
});
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination_store.js b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
index 8ef5101ccb1..80072b56887 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
@@ -2,404 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+cr.exportPath('print_preview');
+
+/**
+ * Printer search statuses used by the destination store.
+ * @enum {string}
+ */
+print_preview.DestinationStorePrinterSearchStatus = {
+ START: 'start',
+ SEARCHING: 'searching',
+ DONE: 'done'
+};
+
cr.define('print_preview', function() {
'use strict';
-
- /**
- * A data store that stores destinations and dispatches events when the data
- * store changes.
- * @param {!print_preview.UserInfo} userInfo User information repository.
- * @param {!print_preview.AppState} appState Application state.
- * @param {!WebUIListenerTracker} listenerTracker Tracker for WebUI listeners
- * added in DestinationStore constructor.
- * @constructor
- * @extends {cr.EventTarget}
- */
- function DestinationStore(userInfo, appState, listenerTracker) {
- cr.EventTarget.call(this);
-
- /**
- * Used to fetch local print destinations.
- * @private {!print_preview.NativeLayer}
- */
- this.nativeLayer_ = print_preview.NativeLayer.getInstance();
-
- /**
- * User information repository.
- * @private {!print_preview.UserInfo}
- */
- this.userInfo_ = userInfo;
-
- /**
- * Used to load and persist the selected destination.
- * @private {!print_preview.AppState}
- */
- this.appState_ = appState;
-
- /**
- * Used to track metrics.
- * @private {!print_preview.DestinationSearchMetricsContext}
- */
- this.metrics_ = new print_preview.DestinationSearchMetricsContext();
-
- /**
- * Internal backing store for the data store.
- * @private {!Array<!print_preview.Destination>}
- */
- this.destinations_ = [];
-
- /**
- * Cache used for constant lookup of destinations by origin and id.
- * @private {Object<!print_preview.Destination>}
- */
- this.destinationMap_ = {};
-
- /**
- * Currently selected destination.
- * @private {print_preview.Destination}
- */
- this.selectedDestination_ = null;
-
- /**
- * Whether the destination store will auto select the destination that
- * matches this set of parameters.
- * @private {print_preview.DestinationMatch}
- */
- this.autoSelectMatchingDestination_ = null;
-
- /**
- * Event tracker used to track event listeners of the destination store.
- * @private {!EventTracker}
- */
- this.tracker_ = new EventTracker();
-
- /**
- * Whether PDF printer is enabled. It's disabled, for example, in App Kiosk
- * mode.
- * @private {boolean}
- */
- this.pdfPrinterEnabled_ = false;
-
- /**
- * ID of the system default destination.
- * @private {?string}
- */
- this.systemDefaultDestinationId_ = null;
-
- /**
- * Used to fetch cloud-based print destinations.
- * @private {cloudprint.CloudPrintInterface}
- */
- this.cloudPrintInterface_ = null;
-
- /**
- * Maps user account to the list of origins for which destinations are
- * already loaded.
- * @private {!Object<Array<!print_preview.DestinationOrigin>>}
- */
- this.loadedCloudOrigins_ = {};
-
- /**
- * ID of a timeout after the initial destination ID is set. If no inserted
- * destination matches the initial destination ID after the specified
- * timeout, the first destination in the store will be automatically
- * selected.
- * @private {?number}
- */
- this.autoSelectTimeout_ = null;
-
- /**
- * Whether a search for local destinations is in progress.
- * @private {boolean}
- */
- this.isLocalDestinationSearchInProgress_ = false;
-
- /**
- * Whether the destination store has already loaded or is loading all local
- * destinations.
- * @private {boolean}
- */
- this.hasLoadedAllLocalDestinations_ = false;
-
- /**
- * Whether a search for privet destinations is in progress.
- * @private {boolean}
- */
- this.isPrivetDestinationSearchInProgress_ = false;
-
- /**
- * Whether the destination store has already loaded or is loading all privet
- * destinations.
- * @private {boolean}
- */
- this.hasLoadedAllPrivetDestinations_ = false;
-
- /**
- * Whether a search for extension destinations is in progress.
- * @private {boolean}
- */
- this.isExtensionDestinationSearchInProgress_ = false;
-
- /**
- * Whether the destination store has already loaded all extension
- * destinations.
- * @private {boolean}
- */
- this.hasLoadedAllExtensionDestinations_ = false;
-
- /**
- * ID of a timeout set at the start of an extension destination search. The
- * timeout ends the search.
- * @private {?number}
- */
- this.extensionSearchTimeout_ = null;
-
- /**
- * MDNS service name of destination that we are waiting to register.
- * @private {?string}
- */
- this.waitForRegisterDestination_ = null;
-
- /**
- * Local destinations are CROS destinations on ChromeOS because they require
- * extra setup.
- * @private {!print_preview.DestinationOrigin}
- */
- this.platformOrigin_ = cr.isChromeOS ?
- print_preview.DestinationOrigin.CROS :
- print_preview.DestinationOrigin.LOCAL;
-
- /**
- * Whether to default to the system default printer instead of the most
- * recent destination.
- * @private {boolean}
- */
- this.useSystemDefaultAsDefault_ =
- loadTimeData.getBoolean('useSystemDefaultPrinter');
-
- this.reset_();
-
- this.addWebUIEventListeners_(listenerTracker);
- }
-
- /**
- * Event types dispatched by the data store.
- * @enum {string}
- */
- DestinationStore.EventType = {
- DESTINATION_SEARCH_DONE:
- 'print_preview.DestinationStore.DESTINATION_SEARCH_DONE',
- DESTINATION_SEARCH_STARTED:
- 'print_preview.DestinationStore.DESTINATION_SEARCH_STARTED',
- DESTINATION_SELECT: 'print_preview.DestinationStore.DESTINATION_SELECT',
- DESTINATIONS_INSERTED:
- 'print_preview.DestinationStore.DESTINATIONS_INSERTED',
- PROVISIONAL_DESTINATION_RESOLVED:
- 'print_preview.DestinationStore.PROVISIONAL_DESTINATION_RESOLVED',
- CACHED_SELECTED_DESTINATION_INFO_READY:
- 'print_preview.DestinationStore.CACHED_SELECTED_DESTINATION_INFO_READY',
- SELECTED_DESTINATION_CAPABILITIES_READY: 'print_preview.DestinationStore' +
- '.SELECTED_DESTINATION_CAPABILITIES_READY',
- };
-
- /**
- * Delay in milliseconds before the destination store ignores the initial
- * destination ID and just selects any printer (since the initial destination
- * was not found).
- * @private {number}
- * @const
- */
- DestinationStore.AUTO_SELECT_TIMEOUT_ = 15000;
-
- /**
- * Maximum amount of time spent searching for extension destinations, in
- * milliseconds.
- * @private {number}
- * @const
- */
- DestinationStore.EXTENSION_SEARCH_DURATION_ = 5000;
-
- /**
- * Human readable names for media sizes in the cloud print CDD.
- * https://developers.google.com/cloud-print/docs/cdd
- * @private {Object<string>}
- * @const
- */
- DestinationStore.MEDIA_DISPLAY_NAMES_ = {
- 'ISO_2A0': '2A0',
- 'ISO_A0': 'A0',
- 'ISO_A0X3': 'A0x3',
- 'ISO_A1': 'A1',
- 'ISO_A10': 'A10',
- 'ISO_A1X3': 'A1x3',
- 'ISO_A1X4': 'A1x4',
- 'ISO_A2': 'A2',
- 'ISO_A2X3': 'A2x3',
- 'ISO_A2X4': 'A2x4',
- 'ISO_A2X5': 'A2x5',
- 'ISO_A3': 'A3',
- 'ISO_A3X3': 'A3x3',
- 'ISO_A3X4': 'A3x4',
- 'ISO_A3X5': 'A3x5',
- 'ISO_A3X6': 'A3x6',
- 'ISO_A3X7': 'A3x7',
- 'ISO_A3_EXTRA': 'A3 Extra',
- 'ISO_A4': 'A4',
- 'ISO_A4X3': 'A4x3',
- 'ISO_A4X4': 'A4x4',
- 'ISO_A4X5': 'A4x5',
- 'ISO_A4X6': 'A4x6',
- 'ISO_A4X7': 'A4x7',
- 'ISO_A4X8': 'A4x8',
- 'ISO_A4X9': 'A4x9',
- 'ISO_A4_EXTRA': 'A4 Extra',
- 'ISO_A4_TAB': 'A4 Tab',
- 'ISO_A5': 'A5',
- 'ISO_A5_EXTRA': 'A5 Extra',
- 'ISO_A6': 'A6',
- 'ISO_A7': 'A7',
- 'ISO_A8': 'A8',
- 'ISO_A9': 'A9',
- 'ISO_B0': 'B0',
- 'ISO_B1': 'B1',
- 'ISO_B10': 'B10',
- 'ISO_B2': 'B2',
- 'ISO_B3': 'B3',
- 'ISO_B4': 'B4',
- 'ISO_B5': 'B5',
- 'ISO_B5_EXTRA': 'B5 Extra',
- 'ISO_B6': 'B6',
- 'ISO_B6C4': 'B6C4',
- 'ISO_B7': 'B7',
- 'ISO_B8': 'B8',
- 'ISO_B9': 'B9',
- 'ISO_C0': 'C0',
- 'ISO_C1': 'C1',
- 'ISO_C10': 'C10',
- 'ISO_C2': 'C2',
- 'ISO_C3': 'C3',
- 'ISO_C4': 'C4',
- 'ISO_C5': 'C5',
- 'ISO_C6': 'C6',
- 'ISO_C6C5': 'C6C5',
- 'ISO_C7': 'C7',
- 'ISO_C7C6': 'C7C6',
- 'ISO_C8': 'C8',
- 'ISO_C9': 'C9',
- 'ISO_DL': 'Envelope DL',
- 'ISO_RA0': 'RA0',
- 'ISO_RA1': 'RA1',
- 'ISO_RA2': 'RA2',
- 'ISO_SRA0': 'SRA0',
- 'ISO_SRA1': 'SRA1',
- 'ISO_SRA2': 'SRA2',
- 'JIS_B0': 'B0 (JIS)',
- 'JIS_B1': 'B1 (JIS)',
- 'JIS_B10': 'B10 (JIS)',
- 'JIS_B2': 'B2 (JIS)',
- 'JIS_B3': 'B3 (JIS)',
- 'JIS_B4': 'B4 (JIS)',
- 'JIS_B5': 'B5 (JIS)',
- 'JIS_B6': 'B6 (JIS)',
- 'JIS_B7': 'B7 (JIS)',
- 'JIS_B8': 'B8 (JIS)',
- 'JIS_B9': 'B9 (JIS)',
- 'JIS_EXEC': 'Executive (JIS)',
- 'JPN_CHOU2': 'Choukei 2',
- 'JPN_CHOU3': 'Choukei 3',
- 'JPN_CHOU4': 'Choukei 4',
- 'JPN_HAGAKI': 'Hagaki',
- 'JPN_KAHU': 'Kahu Envelope',
- 'JPN_KAKU2': 'Kaku 2',
- 'JPN_OUFUKU': 'Oufuku Hagaki',
- 'JPN_YOU4': 'You 4',
- 'NA_10X11': '10x11',
- 'NA_10X13': '10x13',
- 'NA_10X14': '10x14',
- 'NA_10X15': '10x15',
- 'NA_11X12': '11x12',
- 'NA_11X15': '11x15',
- 'NA_12X19': '12x19',
- 'NA_5X7': '5x7',
- 'NA_6X9': '6x9',
- 'NA_7X9': '7x9',
- 'NA_9X11': '9x11',
- 'NA_A2': 'A2',
- 'NA_ARCH_A': 'Arch A',
- 'NA_ARCH_B': 'Arch B',
- 'NA_ARCH_C': 'Arch C',
- 'NA_ARCH_D': 'Arch D',
- 'NA_ARCH_E': 'Arch E',
- 'NA_ASME_F': 'ASME F',
- 'NA_B_PLUS': 'B-plus',
- 'NA_C': 'C',
- 'NA_C5': 'C5',
- 'NA_D': 'D',
- 'NA_E': 'E',
- 'NA_EDP': 'EDP',
- 'NA_EUR_EDP': 'European EDP',
- 'NA_EXECUTIVE': 'Executive',
- 'NA_F': 'F',
- 'NA_FANFOLD_EUR': 'FanFold European',
- 'NA_FANFOLD_US': 'FanFold US',
- 'NA_FOOLSCAP': 'FanFold German Legal',
- 'NA_GOVT_LEGAL': 'Government Legal',
- 'NA_GOVT_LETTER': 'Government Letter',
- 'NA_INDEX_3X5': 'Index 3x5',
- 'NA_INDEX_4X6': 'Index 4x6',
- 'NA_INDEX_4X6_EXT': 'Index 4x6 ext',
- 'NA_INDEX_5X8': '5x8',
- 'NA_INVOICE': 'Invoice',
- 'NA_LEDGER': 'Tabloid', // Ledger in portrait is called Tabloid.
- 'NA_LEGAL': 'Legal',
- 'NA_LEGAL_EXTRA': 'Legal extra',
- 'NA_LETTER': 'Letter',
- 'NA_LETTER_EXTRA': 'Letter extra',
- 'NA_LETTER_PLUS': 'Letter plus',
- 'NA_MONARCH': 'Monarch',
- 'NA_NUMBER_10': 'Envelope #10',
- 'NA_NUMBER_11': 'Envelope #11',
- 'NA_NUMBER_12': 'Envelope #12',
- 'NA_NUMBER_14': 'Envelope #14',
- 'NA_NUMBER_9': 'Envelope #9',
- 'NA_PERSONAL': 'Personal',
- 'NA_QUARTO': 'Quarto',
- 'NA_SUPER_A': 'Super A',
- 'NA_SUPER_B': 'Super B',
- 'NA_WIDE_FORMAT': 'Wide format',
- 'OM_DAI_PA_KAI': 'Dai-pa-kai',
- 'OM_FOLIO': 'Folio',
- 'OM_FOLIO_SP': 'Folio SP',
- 'OM_INVITE': 'Invite Envelope',
- 'OM_ITALIAN': 'Italian Envelope',
- 'OM_JUURO_KU_KAI': 'Juuro-ku-kai',
- 'OM_LARGE_PHOTO': 'Large photo',
- 'OM_OFICIO': 'Oficio',
- 'OM_PA_KAI': 'Pa-kai',
- 'OM_POSTFIX': 'Postfix Envelope',
- 'OM_SMALL_PHOTO': 'Small photo',
- 'PRC_1': 'prc1 Envelope',
- 'PRC_10': 'prc10 Envelope',
- 'PRC_16K': 'prc 16k',
- 'PRC_2': 'prc2 Envelope',
- 'PRC_3': 'prc3 Envelope',
- 'PRC_32K': 'prc 32k',
- 'PRC_4': 'prc4 Envelope',
- 'PRC_5': 'prc5 Envelope',
- 'PRC_6': 'prc6 Envelope',
- 'PRC_7': 'prc7 Envelope',
- 'PRC_8': 'prc8 Envelope',
- 'ROC_16K': 'ROC 16K',
- 'ROC_8K': 'ROC 8k',
- };
-
/**
* Localizes printer capabilities.
- * @param {!print_preview.Cdd} capabilities Printer capabilities to localize.
+ * @param {!print_preview.Cdd} capabilities Printer capabilities to
+ * localize.
* @return {!print_preview.Cdd} Localized capabilities.
- * @private
*/
- DestinationStore.localizeCapabilities_ = function(capabilities) {
+ var localizeCapabilities = function(capabilities) {
if (!capabilities.printer)
return capabilities;
@@ -422,9 +45,8 @@ cr.define('print_preview', function() {
* @param {!Object} a Media to compare.
* @param {!Object} b Media to compare.
* @return {number} 1 if a > b, -1 if a < b, or 0 if a == b.
- * @private
*/
- DestinationStore.compareMediaNames_ = function(a, b) {
+ var compareMediaNames = function(a, b) {
var nameA = a.custom_display_name_localized || a.custom_display_name;
var nameB = b.custom_display_name_localized || b.custom_display_name;
return nameA == nameB ? 0 : (nameA > nameB ? 1 : -1);
@@ -432,11 +54,12 @@ cr.define('print_preview', function() {
/**
* Sort printer media sizes.
- * @param {!print_preview.Cdd} capabilities Printer capabilities to localize.
+ * @param {!print_preview.Cdd} capabilities Printer capabilities to
+ * localize.
* @return {!print_preview.Cdd} Localized capabilities.
* @private
*/
- DestinationStore.sortMediaSizes_ = function(capabilities) {
+ var sortMediaSizes = function(capabilities) {
if (!capabilities.printer)
return capabilities;
@@ -482,12 +105,12 @@ cr.define('print_preview', function() {
}
// For each category, sort by name.
- categoryStandardNA.sort(DestinationStore.compareMediaNames_);
- categoryStandardCN.sort(DestinationStore.compareMediaNames_);
- categoryStandardISO.sort(DestinationStore.compareMediaNames_);
- categoryStandardJP.sort(DestinationStore.compareMediaNames_);
- categoryStandardMisc.sort(DestinationStore.compareMediaNames_);
- categoryCustom.sort(DestinationStore.compareMediaNames_);
+ categoryStandardNA.sort(compareMediaNames);
+ categoryStandardCN.sort(compareMediaNames);
+ categoryStandardISO.sort(compareMediaNames);
+ categoryStandardJP.sort(compareMediaNames);
+ categoryStandardMisc.sort(compareMediaNames);
+ categoryCustom.sort(compareMediaNames);
// Then put it all back together.
mediaSize.option = categoryStandardNA;
@@ -497,8 +120,157 @@ cr.define('print_preview', function() {
return capabilities;
};
- DestinationStore.prototype = {
- __proto__: cr.EventTarget.prototype,
+
+ class DestinationStore extends cr.EventTarget {
+ /**
+ * A data store that stores destinations and dispatches events when the
+ * data store changes.
+ * @param {!print_preview.UserInfo} userInfo User information repository.
+ * @param {!print_preview.AppState} appState Application state.
+ * @param {!WebUIListenerTracker} listenerTracker Tracker for WebUI
+ * listeners added in DestinationStore constructor.
+ */
+ constructor(userInfo, appState, listenerTracker) {
+ super();
+
+ /**
+ * Used to fetch local print destinations.
+ * @private {!print_preview.NativeLayer}
+ */
+ this.nativeLayer_ = print_preview.NativeLayer.getInstance();
+
+ /**
+ * User information repository.
+ * @private {!print_preview.UserInfo}
+ */
+ this.userInfo_ = userInfo;
+
+ /**
+ * Used to load and persist the selected destination.
+ * @private {!print_preview.AppState}
+ */
+ this.appState_ = appState;
+
+ /**
+ * Used to track metrics.
+ * @private {!print_preview.DestinationSearchMetricsContext}
+ */
+ this.metrics_ = new print_preview.DestinationSearchMetricsContext();
+
+ /**
+ * Internal backing store for the data store.
+ * @private {!Array<!print_preview.Destination>}
+ */
+ this.destinations_ = [];
+
+ /**
+ * Cache used for constant lookup of destinations by origin and id.
+ * @private {Object<!print_preview.Destination>}
+ */
+ this.destinationMap_ = {};
+
+ /**
+ * Currently selected destination.
+ * @private {print_preview.Destination}
+ */
+ this.selectedDestination_ = null;
+
+ /**
+ * Whether the destination store will auto select the destination that
+ * matches this set of parameters.
+ * @private {print_preview.DestinationMatch}
+ */
+ this.autoSelectMatchingDestination_ = null;
+
+ /**
+ * Event tracker used to track event listeners of the destination store.
+ * @private {!EventTracker}
+ */
+ this.tracker_ = new EventTracker();
+
+ /**
+ * Whether PDF printer is enabled. It's disabled, for example, in App
+ * Kiosk mode.
+ * @private {boolean}
+ */
+ this.pdfPrinterEnabled_ = false;
+
+ /**
+ * ID of the system default destination.
+ * @private {string}
+ */
+ this.systemDefaultDestinationId_ = '';
+
+ /**
+ * Used to fetch cloud-based print destinations.
+ * @private {cloudprint.CloudPrintInterface}
+ */
+ this.cloudPrintInterface_ = null;
+
+ /**
+ * Maps user account to the list of origins for which destinations are
+ * already loaded.
+ * @private {!Object<Array<!print_preview.DestinationOrigin>>}
+ */
+ this.loadedCloudOrigins_ = {};
+
+ /**
+ * ID of a timeout after the initial destination ID is set. If no inserted
+ * destination matches the initial destination ID after the specified
+ * timeout, the first destination in the store will be automatically
+ * selected.
+ * @private {?number}
+ */
+ this.autoSelectTimeout_ = null;
+
+ /**
+ * Whether a search for destinations is in progress for each type of
+ * printer.
+ * @private {!Map<!print_preview.PrinterType,
+ * !print_preview.DestinationStorePrinterSearchStatus>}
+ */
+ this.destinationSearchStatus_ = new Map([
+ [
+ print_preview.PrinterType.EXTENSION_PRINTER,
+ print_preview.DestinationStorePrinterSearchStatus.START
+ ],
+ [
+ print_preview.PrinterType.PRIVET_PRINTER,
+ print_preview.DestinationStorePrinterSearchStatus.START
+ ],
+ [
+ print_preview.PrinterType.LOCAL_PRINTER,
+ print_preview.DestinationStorePrinterSearchStatus.START
+ ]
+ ]);
+
+ /**
+ * MDNS service name of destination that we are waiting to register.
+ * @private {?string}
+ */
+ this.waitForRegisterDestination_ = null;
+
+ /**
+ * Local destinations are CROS destinations on ChromeOS because they
+ * require extra setup.
+ * @private {!print_preview.DestinationOrigin}
+ */
+ this.platformOrigin_ = cr.isChromeOS ?
+ print_preview.DestinationOrigin.CROS :
+ print_preview.DestinationOrigin.LOCAL;
+
+ /**
+ * Whether to default to the system default printer instead of the most
+ * recent destination.
+ * @private {boolean}
+ */
+ this.useSystemDefaultAsDefault_ =
+ loadTimeData.getBoolean('useSystemDefaultPrinter');
+
+ this.reset_();
+
+ this.addWebUIEventListeners_(listenerTracker);
+ }
/**
* @param {?string=} opt_account Account to filter destinations by. When
@@ -506,14 +278,14 @@ cr.define('print_preview', function() {
* @return {!Array<!print_preview.Destination>} List of destinations
* accessible by the {@code account}.
*/
- destinations: function(opt_account) {
+ destinations(opt_account) {
if (opt_account) {
return this.destinations_.filter(function(destination) {
return !destination.account || destination.account == opt_account;
});
}
return this.destinations_.slice(0);
- },
+ }
/**
* @return {print_preview.Destination} The currently selected destination or
@@ -521,22 +293,23 @@ cr.define('print_preview', function() {
*/
get selectedDestination() {
return this.selectedDestination_;
- },
+ }
/** @return {boolean} Whether destination selection is pending or not. */
get isAutoSelectDestinationInProgress() {
return this.selectedDestination_ == null &&
this.autoSelectTimeout_ != null;
- },
+ }
/**
* @return {boolean} Whether a search for local destinations is in progress.
*/
get isLocalDestinationSearchInProgress() {
- return this.isLocalDestinationSearchInProgress_ ||
- this.isPrivetDestinationSearchInProgress_ ||
- this.isExtensionDestinationSearchInProgress_;
- },
+ return Array.from(this.destinationSearchStatus_.values())
+ .some(
+ el => el ===
+ print_preview.DestinationStorePrinterSearchStatus.SEARCHING);
+ }
/**
* @return {boolean} Whether a search for cloud destinations is in progress.
@@ -544,7 +317,7 @@ cr.define('print_preview', function() {
get isCloudDestinationSearchInProgress() {
return !!this.cloudPrintInterface_ &&
this.cloudPrintInterface_.isCloudDestinationSearchInProgress;
- },
+ }
/**
* Starts listening for relevant WebUI events and adds the listeners to
@@ -553,15 +326,11 @@ cr.define('print_preview', function() {
* @param {!WebUIListenerTracker} listenerTracker
* @private
*/
- addWebUIEventListeners_: function(listenerTracker) {
- listenerTracker.add(
- 'privet-printer-added', this.onPrivetPrinterAdded_.bind(this));
- listenerTracker.add(
- 'extension-printers-added',
- this.onExtensionPrintersAdded_.bind(this));
+ addWebUIEventListeners_(listenerTracker) {
+ listenerTracker.add('printers-added', this.onPrintersAdded_.bind(this));
listenerTracker.add(
'reload-printer-list', this.onDestinationsReload.bind(this));
- },
+ }
/**
* Initializes the destination store. Sets the initially selected
@@ -570,12 +339,12 @@ cr.define('print_preview', function() {
* print_preview.AppState has been initialized.
* @param {boolean} isInAppKioskMode Whether the print preview is in App
* Kiosk mode.
- * @param {?string} systemDefaultDestinationId ID of the system default
+ * @param {string} systemDefaultDestinationId ID of the system default
* destination.
* @param {?string} serializedDefaultDestinationSelectionRulesStr Serialized
* default destination selection rules.
*/
- init: function(
+ init(
isInAppKioskMode, systemDefaultDestinationId,
serializedDefaultDestinationSelectionRulesStr) {
this.pdfPrinterEnabled_ = !isInAppKioskMode;
@@ -591,7 +360,7 @@ cr.define('print_preview', function() {
}
}
- if (!this.systemDefaultDestinationId_ &&
+ if (this.systemDefaultDestinationId_.length == 0 &&
!this.appState_.isSelectedDestinationValid()) {
this.selectPdfDestination_();
return;
@@ -615,7 +384,7 @@ cr.define('print_preview', function() {
origin = this.appState_.recentDestinations[i].origin;
id = this.appState_.recentDestinations[i].id;
account = this.appState_.recentDestinations[i].account || '';
- name = this.appState_.recentDestinations[i].name || '';
+ name = this.appState_.recentDestinations[i].displayName || '';
capabilities = this.appState_.recentDestinations[i].capabilities;
extensionId = this.appState_.recentDestinations[i].extensionId || '';
extensionName =
@@ -639,7 +408,7 @@ cr.define('print_preview', function() {
return;
// Try the system default
- id = this.systemDefaultDestinationId_ || '';
+ id = this.systemDefaultDestinationId_;
origin = id == print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ?
print_preview.DestinationOrigin.LOCAL :
this.platformOrigin_;
@@ -658,12 +427,12 @@ cr.define('print_preview', function() {
}
this.selectPdfDestination_();
- },
+ }
/**
* Attempts to fetch capabilities of the destination identified by the
* provided origin, id and account.
- * @param {string | print_preview.DestinationOrigin} origin Destination
+ * @param {print_preview.DestinationOrigin} origin Destination
* origin.
* @param {string} id Destination id.
* @param {string} account User account destination is registered for.
@@ -676,67 +445,46 @@ cr.define('print_preview', function() {
* @return {boolean} Whether capabilities fetch was successfully started.
* @private
*/
- fetchPreselectedDestination_: function(
+ fetchPreselectedDestination_(
origin, id, account, name, capabilities, extensionId, extensionName) {
this.autoSelectMatchingDestination_ =
this.createExactDestinationMatch_(origin, id);
- if (origin == print_preview.DestinationOrigin.LOCAL ||
- origin == print_preview.DestinationOrigin.CROS) {
- this.nativeLayer_.getPrinterCapabilities(id).then(
- this.onLocalDestinationCapabilitiesSet_.bind(this),
- this.onGetCapabilitiesFail_.bind(
- this,
- /** @type {print_preview.DestinationOrigin} */ (origin), id));
+ var type = print_preview.originToType(origin);
+ if (type == print_preview.PrinterType.LOCAL_PRINTER) {
+ this.nativeLayer_.getPrinterCapabilities(id, type).then(
+ this.onCapabilitiesSet_.bind(this, origin, id),
+ this.onGetCapabilitiesFail_.bind(this, origin, id));
return true;
}
if (this.cloudPrintInterface_ &&
(origin == print_preview.DestinationOrigin.COOKIES ||
origin == print_preview.DestinationOrigin.DEVICE)) {
- this.cloudPrintInterface_.printer(
- id,
- /** @type {print_preview.DestinationOrigin} */ (origin), account);
+ this.cloudPrintInterface_.printer(id, origin, account);
return true;
}
- if (origin == print_preview.DestinationOrigin.PRIVET) {
+ if (origin == print_preview.DestinationOrigin.PRIVET ||
+ origin == print_preview.DestinationOrigin.EXTENSION) {
// TODO(noamsml): Resolve a specific printer instead of listing all
- // privet printers in this case.
- this.nativeLayer_.getPrivetPrinters().then(
- this.endPrivetPrinterSearch_.bind(this));
+ // privet or extension printers in this case.
+ this.startLoadDestinations(type);
// Create a fake selectedDestination_ that is not actually in the
// destination store. When the real destination is created, this
// destination will be overwritten.
- this.selectedDestination_ = new print_preview.Destination(
- id, print_preview.DestinationType.LOCAL,
- print_preview.DestinationOrigin.PRIVET, name, false /*isRecent*/,
- print_preview.DestinationConnectionStatus.ONLINE);
-
- if (capabilities) {
- this.selectedDestination_.capabilities = capabilities;
-
- cr.dispatchSimpleEvent(
- this,
- DestinationStore.EventType
- .CACHED_SELECTED_DESTINATION_INFO_READY);
- }
- return true;
- }
-
- if (origin == print_preview.DestinationOrigin.EXTENSION) {
- // TODO(tbarzic): Add support for requesting a single extension's
- // printer list.
- this.startLoadExtensionDestinations();
-
- this.selectedDestination_ =
- print_preview.ExtensionDestinationParser.parse({
+ var params =
+ (origin === print_preview.DestinationOrigin.PRIVET) ? {} : {
+ description: '',
extensionId: extensionId,
extensionName: extensionName,
- id: id,
- name: name
- });
+ provisionalType: print_preview.DestinationProvisionalType.NONE
+ };
+ this.selectedDestination_ = new print_preview.Destination(
+ id, print_preview.DestinationType.LOCAL, origin, name,
+ false /*isRecent*/,
+ print_preview.DestinationConnectionStatus.ONLINE, params);
if (capabilities) {
this.selectedDestination_.capabilities = capabilities;
@@ -748,37 +496,27 @@ cr.define('print_preview', function() {
}
return true;
}
-
return false;
- },
+ }
/**
* Attempts to find a destination matching the provided rules.
* @param {!print_preview.DestinationMatch} destinationMatch Rules to match.
* @private
*/
- fetchMatchingDestination_: function(destinationMatch) {
+ fetchMatchingDestination_(destinationMatch) {
this.autoSelectMatchingDestination_ = destinationMatch;
-
- if (destinationMatch.matchOrigin(print_preview.DestinationOrigin.LOCAL) ||
- destinationMatch.matchOrigin(print_preview.DestinationOrigin.CROS)) {
- this.startLoadLocalDestinations();
- }
- if (destinationMatch.matchOrigin(
- print_preview.DestinationOrigin.PRIVET)) {
- this.startLoadPrivetDestinations();
- }
- if (destinationMatch.matchOrigin(
- print_preview.DestinationOrigin.EXTENSION)) {
- this.startLoadExtensionDestinations();
- }
- if (destinationMatch.matchOrigin(
+ var type = destinationMatch.getType();
+ if (type != null) { // Local, Privet, or Extension.
+ this.startLoadDestinations(type);
+ } else if (
+ destinationMatch.matchOrigin(
print_preview.DestinationOrigin.COOKIES) ||
destinationMatch.matchOrigin(
print_preview.DestinationOrigin.DEVICE)) {
this.startLoadCloudDestinations();
}
- },
+ }
/**
* @param {?string} serializedDefaultDestinationSelectionRulesStr Serialized
@@ -787,8 +525,7 @@ cr.define('print_preview', function() {
* previously selected destination.
* @private
*/
- convertToDestinationMatch_: function(
- serializedDefaultDestinationSelectionRulesStr) {
+ convertToDestinationMatch_(serializedDefaultDestinationSelectionRulesStr) {
var matchRules = null;
try {
if (serializedDefaultDestinationSelectionRulesStr) {
@@ -841,25 +578,25 @@ cr.define('print_preview', function() {
return new print_preview.DestinationMatch(
origins, idRegExp, displayNameRegExp,
true /*skipVirtualDestinations*/);
- },
+ }
/**
* @return {print_preview.DestinationMatch} Creates rules matching
* previously selected destination.
* @private
*/
- convertPreselectedToDestinationMatch_: function() {
+ convertPreselectedToDestinationMatch_() {
if (this.appState_.isSelectedDestinationValid()) {
return this.createExactDestinationMatch_(
this.appState_.selectedDestination.origin,
this.appState_.selectedDestination.id);
}
- if (this.systemDefaultDestinationId_) {
+ if (this.systemDefaultDestinationId_.length > 0) {
return this.createExactDestinationMatch_(
this.platformOrigin_, this.systemDefaultDestinationId_);
}
return null;
- },
+ }
/**
* @param {string | print_preview.DestinationOrigin} origin Destination
@@ -869,19 +606,19 @@ cr.define('print_preview', function() {
* provided destination.
* @private
*/
- createExactDestinationMatch_: function(origin, id) {
+ createExactDestinationMatch_(origin, id) {
return new print_preview.DestinationMatch(
[origin],
new RegExp('^' + id.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '$'),
null /*displayNameRegExp*/, false /*skipVirtualDestinations*/);
- },
+ }
/**
* Sets the destination store's Google Cloud Print interface.
* @param {!cloudprint.CloudPrintInterface} cloudPrintInterface Interface
* to set.
*/
- setCloudPrintInterface: function(cloudPrintInterface) {
+ setCloudPrintInterface(cloudPrintInterface) {
assert(this.cloudPrintInterface_ == null);
this.cloudPrintInterface_ = cloudPrintInterface;
this.tracker_.add(
@@ -904,12 +641,12 @@ cr.define('print_preview', function() {
this.cloudPrintInterface_,
cloudprint.CloudPrintInterfaceEventType.PROCESS_INVITE_DONE,
this.onCloudPrintProcessInviteDone_.bind(this));
- },
+ }
/**
* @param {print_preview.Destination} destination Destination to select.
*/
- selectDestination: function(destination) {
+ selectDestination(destination) {
this.autoSelectMatchingDestination_ = null;
// When auto select expires, DESTINATION_SELECT event has to be dispatched
// anyway (see isAutoSelectDestinationInProgress() logic).
@@ -952,24 +689,14 @@ cr.define('print_preview', function() {
// Request destination capabilities from backend, since they are not
// known yet.
if (destination.capabilities == null) {
- if (destination.isPrivet) {
- this.nativeLayer_.getPrivetPrinterCapabilities(destination.id)
- .then(
- this.onPrivetCapabilitiesSet_.bind(this),
- this.onGetCapabilitiesFail_.bind(
- this, destination.origin, destination.id));
- } else if (destination.isExtension) {
- this.nativeLayer_.getExtensionPrinterCapabilities(destination.id)
+ var type = print_preview.originToType(destination.origin);
+ if (type !== null) {
+ this.nativeLayer_.getPrinterCapabilities(destination.id, type)
.then(
- this.onExtensionCapabilitiesSet_.bind(this, destination.id),
- this.onGetCapabilitiesFail_.bind(
- this, destination.origin, destination.id));
- } else if (destination.isLocal) {
- this.nativeLayer_.getPrinterCapabilities(destination.id)
- .then(
- this.onLocalDestinationCapabilitiesSet_.bind(this),
- this.onGetCapabilitiesFail_.bind(
- this, destination.origin, destination.id));
+ (caps) => this.onCapabilitiesSet_(
+ destination.origin, destination.id, caps),
+ () => this.onGetCapabilitiesFail_(
+ destination.origin, destination.origin));
} else {
assert(
this.cloudPrintInterface_ != null,
@@ -982,7 +709,7 @@ cr.define('print_preview', function() {
this,
DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
}
- },
+ }
/**
* Attempt to resolve the capabilities for a Chrome OS printer.
@@ -990,17 +717,17 @@ cr.define('print_preview', function() {
* requires resolution.
* @return {!Promise<!print_preview.PrinterSetupResponse>}
*/
- resolveCrosDestination: function(destination) {
+ resolveCrosDestination(destination) {
assert(destination.origin == print_preview.DestinationOrigin.CROS);
return this.nativeLayer_.setupPrinter(destination.id);
- },
+ }
/**
* Attempts to resolve a provisional destination.
* @param {!print_preview.Destination} destination Provisional destination
* that should be resolved.
*/
- resolveProvisionalDestination: function(destination) {
+ resolveProvisionalDestination(destination) {
assert(
destination.provisionalType ==
print_preview.DestinationProvisionalType.NEEDS_USB_PERMISSION,
@@ -1016,8 +743,7 @@ cr.define('print_preview', function() {
*/
this.removeProvisionalDestination_(destination.id);
var parsedDestination =
- print_preview.ExtensionDestinationParser.parse(
- destinationInfo);
+ print_preview.parseExtensionDestination(destinationInfo);
this.insertIntoStore_(parsedDestination);
this.dispatchProvisionalDestinationResolvedEvent_(
destination.id, parsedDestination);
@@ -1032,27 +758,27 @@ cr.define('print_preview', function() {
this.dispatchProvisionalDestinationResolvedEvent_(
destination.id, null);
});
- },
+ }
/**
* Selects 'Save to PDF' destination (since it always exists).
* @private
*/
- selectPdfDestination_: function() {
+ selectPdfDestination_() {
var saveToPdfKey = this.getDestinationKey_(
print_preview.DestinationOrigin.LOCAL,
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF, '');
this.selectDestination(
this.destinationMap_[saveToPdfKey] || this.destinations_[0] || null);
- },
+ }
/**
* Attempts to select system default destination with a fallback to
* 'Save to PDF' destination.
* @private
*/
- selectDefaultDestination_: function() {
- if (this.systemDefaultDestinationId_) {
+ selectDefaultDestination_() {
+ if (this.systemDefaultDestinationId_.length > 0) {
if (this.autoSelectMatchingDestination_ &&
!this.autoSelectMatchingDestination_.matchIdAndOrigin(
this.systemDefaultDestinationId_, this.platformOrigin_)) {
@@ -1065,59 +791,37 @@ cr.define('print_preview', function() {
}
}
this.selectPdfDestination_();
- },
-
- /** Initiates loading of local print destinations. */
- startLoadLocalDestinations: function() {
- if (!this.hasLoadedAllLocalDestinations_) {
- this.hasLoadedAllLocalDestinations_ = true;
- this.nativeLayer_.getPrinters().then(
- this.onLocalDestinationsSet_.bind(this));
- this.isLocalDestinationSearchInProgress_ = true;
- cr.dispatchSimpleEvent(
- this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
- }
- },
+ }
- /** Initiates loading of privet print destinations. */
- startLoadPrivetDestinations: function() {
- if (this.hasLoadedAllPrivetDestinations_)
+ /**
+ * Initiates loading of destinations.
+ * @param{print_preview.PrinterType} type The type of destinations to load.
+ */
+ startLoadDestinations(type) {
+ if (this.destinationSearchStatus_.get(type) ===
+ print_preview.DestinationStorePrinterSearchStatus.DONE) {
return;
- this.isPrivetDestinationSearchInProgress_ = true;
- this.nativeLayer_.getPrivetPrinters().then(
- this.endPrivetPrinterSearch_.bind(this), () => {
- // Rejected by C++, indicating privet printing is disabled.
- this.hasLoadedAllPrivetDestinations_ = true;
- this.isPrivetDestinationSearchInProgress_ = false;
+ }
+ this.destinationSearchStatus_.set(
+ type, print_preview.DestinationStorePrinterSearchStatus.SEARCHING);
+ this.nativeLayer_.getPrinters(type).then(
+ this.onDestinationSearchDone_.bind(this, type), () => {
+ // Will be rejected by C++ for privet printers if privet printing
+ // is disabled.
+ assert(type === print_preview.PrinterType.PRIVET_PRINTER);
+ this.destinationSearchStatus_.set(
+ type, print_preview.DestinationStorePrinterSearchStatus.DONE);
});
cr.dispatchSimpleEvent(
this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
- },
-
- /** Initializes loading of extension managed print destinations. */
- startLoadExtensionDestinations: function() {
- if (this.hasLoadedAllExtensionDestinations_)
- return;
-
- if (this.isExtensionDestinationSearchInProgress_)
- clearTimeout(this.extensionSearchTimeout_);
-
- this.isExtensionDestinationSearchInProgress_ = true;
- this.nativeLayer_.getExtensionPrinters().then(
- this.onExtensionPrintersDone_.bind(this));
- cr.dispatchSimpleEvent(
- this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
- this.extensionSearchTimeout_ = setTimeout(
- this.endExtensionPrinterSearch_.bind(this),
- DestinationStore.EXTENSION_SEARCH_DURATION_);
- },
+ }
/**
* Initiates loading of cloud destinations.
* @param {print_preview.DestinationOrigin=} opt_origin Search destinations
* for the specified origin only.
*/
- startLoadCloudDestinations: function(opt_origin) {
+ startLoadCloudDestinations(opt_origin) {
if (this.cloudPrintInterface_ != null) {
var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];
if (origins.length == 0 ||
@@ -1128,10 +832,10 @@ cr.define('print_preview', function() {
this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
}
}
- },
+ }
/** Requests load of COOKIE based cloud destinations. */
- reloadUserCookieBasedDestinations: function() {
+ reloadUserCookieBasedDestinations() {
var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];
if (origins.indexOf(print_preview.DestinationOrigin.COOKIES) >= 0) {
cr.dispatchSimpleEvent(
@@ -1140,24 +844,26 @@ cr.define('print_preview', function() {
this.startLoadCloudDestinations(
print_preview.DestinationOrigin.COOKIES);
}
- },
+ }
/** Initiates loading of all known destination types. */
- startLoadAllDestinations: function() {
+ startLoadAllDestinations() {
this.startLoadCloudDestinations();
- this.startLoadLocalDestinations();
- this.startLoadPrivetDestinations();
- this.startLoadExtensionDestinations();
- },
+ for (var printerType of Object.values(print_preview.PrinterType)) {
+ if (printerType !== print_preview.PrinterType.PDF_PRINTER)
+ this.startLoadDestinations(printerType);
+ }
+ }
/**
* Wait for a privet device to be registered.
*/
- waitForRegister: function(id) {
- this.nativeLayer_.getPrivetPrinters().then(
- this.endPrivetPrinterSearch_.bind(this));
+ waitForRegister(id) {
+ var privetType = print_preview.PrinterType.PRIVET_PRINTER;
+ this.nativeLayer_.getPrinters(privetType)
+ .then(this.onDestinationSearchDone_.bind(this, privetType));
this.waitForRegisterDestination_ = id;
- },
+ }
/**
* Removes the provisional destination with ID |provisionalId| from
@@ -1165,7 +871,7 @@ cr.define('print_preview', function() {
* @param{string} provisionalId The provisional destination ID.
* @private
*/
- removeProvisionalDestination_: function(provisionalId) {
+ removeProvisionalDestination_(provisionalId) {
this.destinations_ = this.destinations_.filter(
function(el) {
if (el.id == provisionalId) {
@@ -1174,7 +880,7 @@ cr.define('print_preview', function() {
}
return true;
}, this);
- },
+ }
/**
* Dispatches the PROVISIONAL_DESTINATION_RESOLVED event for id
@@ -1184,14 +890,13 @@ cr.define('print_preview', function() {
* @param {?print_preview.Destination} destination Information about the
* destination if it was resolved successfully.
*/
- dispatchProvisionalDestinationResolvedEvent_: function(
- provisionalId, destination) {
+ dispatchProvisionalDestinationResolvedEvent_(provisionalId, destination) {
var event = new Event(
DestinationStore.EventType.PROVISIONAL_DESTINATION_RESOLVED);
event.provisionalId = provisionalId;
event.destination = destination;
this.dispatchEvent(event);
- },
+ }
/**
* Inserts {@code destination} to the data store and dispatches a
@@ -1200,28 +905,36 @@ cr.define('print_preview', function() {
* insert.
* @private
*/
- insertDestination_: function(destination) {
+ insertDestination_(destination) {
if (this.insertIntoStore_(destination)) {
this.destinationsInserted_(destination);
}
- },
+ }
/**
* Inserts multiple {@code destinations} to the data store and dispatches
* single DESTINATIONS_INSERTED event.
- * @param {!Array<print_preview.Destination>} destinations Print
+ * @param {!Array<!print_preview.Destination |
+ * !Array<print_preview.Destination>>} destinations Print
* destinations to insert.
* @private
*/
- insertDestinations_: function(destinations) {
+ insertDestinations_(destinations) {
var inserted = false;
- destinations.forEach(function(destination) {
- inserted = this.insertIntoStore_(destination) || inserted;
- }, this);
+ destinations.forEach(destination => {
+ if (Array.isArray(destination)) {
+ // privet printers return arrays of 1 or 2 printers
+ inserted = destination.reduce(function(soFar, d) {
+ return this.insertIntoStore_(d) || soFar;
+ }, inserted);
+ } else {
+ inserted = this.insertIntoStore_(destination) || inserted;
+ }
+ });
if (inserted) {
this.destinationsInserted_();
}
- },
+ }
/**
* Dispatches DESTINATIONS_INSERTED event. In auto select mode, tries to
@@ -1232,7 +945,7 @@ cr.define('print_preview', function() {
* changed. Used as a hint to limit destination search scope against
* {@code autoSelectMatchingDestination_}.
*/
- destinationsInserted_: function(opt_destination) {
+ destinationsInserted_(opt_destination) {
cr.dispatchSimpleEvent(
this, DestinationStore.EventType.DESTINATIONS_INSERTED);
if (this.autoSelectMatchingDestination_) {
@@ -1245,7 +958,7 @@ cr.define('print_preview', function() {
}
}, this);
}
- },
+ }
/**
* Updates an existing print destination with capabilities and display name
@@ -1253,12 +966,14 @@ cr.define('print_preview', function() {
* @param {!print_preview.Destination} destination Destination to update.
* @private
*/
- updateDestination_: function(destination) {
+ updateDestination_(destination) {
assert(destination.constructor !== Array, 'Single printer expected');
- destination.capabilities_ = DestinationStore.localizeCapabilities_(
- assert(destination.capabilities_));
destination.capabilities_ =
- DestinationStore.sortMediaSizes_(destination.capabilities_);
+ localizeCapabilities(assert(destination.capabilities_));
+ if (print_preview.originToType(destination.origin) !==
+ print_preview.PrinterType.LOCAL_PRINTER) {
+ destination.capabilities_ = sortMediaSizes(destination.capabilities_);
+ }
var existingDestination = this.destinationMap_[this.getKey_(destination)];
if (existingDestination != null) {
existingDestination.capabilities = destination.capabilities;
@@ -1274,28 +989,13 @@ cr.define('print_preview', function() {
this,
DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
}
- },
-
- /**
- * Called when the search for Privet printers is done.
- * @private
- */
- endPrivetPrinterSearch_: function() {
- this.isPrivetDestinationSearchInProgress_ = false;
- this.hasLoadedAllPrivetDestinations_ = true;
- cr.dispatchSimpleEvent(
- this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
- },
+ }
/**
* Called when loading of extension managed printers is done.
* @private
*/
- endExtensionPrinterSearch_: function() {
- this.isExtensionDestinationSearchInProgress_ = false;
- this.hasLoadedAllExtensionDestinations_ = true;
- cr.dispatchSimpleEvent(
- this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
+ endExtensionPrinterSearch_() {
// Clear initially selected (cached) extension destination if it hasn't
// been found among reported extension destinations.
if (this.autoSelectMatchingDestination_ &&
@@ -1304,15 +1004,17 @@ cr.define('print_preview', function() {
this.selectedDestination_ && this.selectedDestination_.isExtension) {
this.selectDefaultDestination_();
}
- },
+ }
/**
* Inserts a destination into the store without dispatching any events.
+ * @param {!print_preview.Destination} destination The destination to be
+ * inserted.
* @return {boolean} Whether the inserted destination was not already in the
* store.
* @private
*/
- insertIntoStore_: function(destination) {
+ insertIntoStore_(destination) {
var key = this.getKey_(destination);
var existingDestination = this.destinationMap_[key];
if (existingDestination == null) {
@@ -1334,13 +1036,13 @@ cr.define('print_preview', function() {
return true;
}
return false;
- },
+ }
/**
* Creates a local PDF print destination.
* @private
*/
- createLocalPdfPrintDestination_: function() {
+ createLocalPdfPrintDestination_() {
// TODO(alekseys): Create PDF printer in the native code and send its
// capabilities back with other local printers.
if (this.pdfPrinterEnabled_) {
@@ -1351,100 +1053,86 @@ cr.define('print_preview', function() {
loadTimeData.getString('printToPDF'), false /*isRecent*/,
print_preview.DestinationConnectionStatus.ONLINE));
}
- },
+ }
/**
* Resets the state of the destination store to its initial state.
* @private
*/
- reset_: function() {
+ reset_() {
this.destinations_ = [];
this.destinationMap_ = {};
this.selectDestination(null);
this.loadedCloudOrigins_ = {};
- this.hasLoadedAllLocalDestinations_ = false;
- this.hasLoadedAllPrivetDestinations_ = false;
- this.hasLoadedAllExtensionDestinations_ = false;
+ for (var printerType of Object.values(print_preview.PrinterType)) {
+ if (printerType !== print_preview.PrinterType.PDF_PRINTER) {
+ this.destinationSearchStatus_.set(
+ printerType,
+ print_preview.DestinationStorePrinterSearchStatus.START);
+ }
+ }
clearTimeout(this.autoSelectTimeout_);
this.autoSelectTimeout_ = setTimeout(
this.selectDefaultDestination_.bind(this),
DestinationStore.AUTO_SELECT_TIMEOUT_);
- },
+ }
+
/**
- * Called when the local destinations have been got from the native layer.
- * @param {!Array<!print_preview.LocalDestinationInfo>} destinationInfos A
- * list of the local destinations retrieved.
- * @private
+ * Called when destination search is complete for some type of printer.
+ * @param {!print_preview.PrinterType} type The type of printers that are
+ * done being retreived.
*/
- onLocalDestinationsSet_: function(destinationInfos) {
- var localDestinations = destinationInfos.map(function(destInfo) {
- return print_preview.LocalDestinationParser.parse(destInfo);
- });
- this.insertDestinations_(localDestinations);
- this.isLocalDestinationSearchInProgress_ = false;
+ onDestinationSearchDone_(type) {
+ this.destinationSearchStatus_.set(
+ type, print_preview.DestinationStorePrinterSearchStatus.DONE);
cr.dispatchSimpleEvent(
this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
- },
+ if (type === print_preview.PrinterType.EXTENSION_PRINTER)
+ this.endExtensionPrinterSearch_();
+ }
/**
* Called when the native layer retrieves the capabilities for the selected
* local destination. Updates the destination with new capabilities if the
* destination already exists, otherwise it creates a new destination and
* then updates its capabilities.
- * @param {print_preview.PrinterCapabilitiesResponse} settingsInfo Contains
- * information about and capabilities of the local print destination.
+ * @param {!print_preview.DestinationOrigin} origin The origin of the
+ * print destination.
+ * @param {string} id The id of the print destination.
+ * @param {!print_preview.CapabilitiesResponse} settingsInfo Contains
+ * the capabilities of the print destination, and information about
+ * the destination except in the case of extension printers.
* @private
*/
- onLocalDestinationCapabilitiesSet_: function(settingsInfo) {
- var destinationId = settingsInfo['printerId'];
- var printerName = settingsInfo['printerName'];
- var printerDescription = settingsInfo['printerDescription'];
- // PDF is special since we don't need to query the device for
- // capabilities.
- var origin = destinationId ==
- print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ?
- print_preview.DestinationOrigin.LOCAL :
- this.platformOrigin_;
- var key = this.getDestinationKey_(origin, destinationId, '');
- var destination = this.destinationMap_[key];
- var capabilities =
- DestinationStore.localizeCapabilities_(settingsInfo.capabilities);
- // Special case for PDF printer (until local printers capabilities are
- // reported in CDD format too).
- if (destinationId ==
- print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
- if (destination) {
- destination.capabilities = capabilities;
+ onCapabilitiesSet_(origin, id, settingsInfo) {
+ var dest = null;
+ if (origin !== print_preview.DestinationOrigin.PRIVET) {
+ var key = this.getDestinationKey_(origin, id, '');
+ dest = this.destinationMap_[key];
+ }
+ if (!dest) {
+ // Ignore unrecognized extension printers
+ if (!settingsInfo.printer) {
+ assert(origin === print_preview.DestinationOrigin.EXTENSION);
+ return;
}
- } else {
- if (destination) {
- // In case there were multiple capabilities request for this local
- // destination, just ignore the later ones.
- if (destination.capabilities != null) {
- return;
- }
- destination.capabilities = capabilities;
+ dest = print_preview.parseDestination(
+ print_preview.originToType(origin), assert(settingsInfo.printer));
+ }
+ if (dest) {
+ var updateDestination = destination => {
+ destination.capabilities = settingsInfo.capabilities;
+ this.updateDestination_(destination);
+ };
+ if (Array.isArray(dest)) {
+ dest.forEach(updateDestination);
} else {
- var isEnterprisePrinter = settingsInfo['cupsEnterprisePrinter'];
- destination = print_preview.LocalDestinationParser.parse({
- deviceName: destinationId,
- printerName: printerName,
- cupsEnterprisePrinter: isEnterprisePrinter,
- printerDescription: printerDescription
- });
- destination.capabilities = capabilities;
- this.insertDestination_(destination);
+ updateDestination(dest);
}
}
- if (this.selectedDestination_ &&
- this.selectedDestination_.id == destinationId) {
- cr.dispatchSimpleEvent(
- this,
- DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
- }
- },
+ }
/**
* Called when a request to get a local destination's print capabilities
@@ -1455,15 +1143,22 @@ cr.define('print_preview', function() {
* @param {string} destinationId The destination ID that failed.
* @private
*/
- onGetCapabilitiesFail_: function(origin, destinationId) {
+ onGetCapabilitiesFail_(origin, destinationId) {
console.warn(
'Failed to get print capabilities for printer ' + destinationId);
+ if (this.selectedDestination_ &&
+ this.selectedDestination_.id == destinationId) {
+ var event =
+ new Event(DestinationStore.EventType.SELECTED_DESTINATION_INVALID);
+ event.destinationId = destinationId;
+ this.dispatchEvent(event);
+ }
if (this.autoSelectMatchingDestination_ &&
this.autoSelectMatchingDestination_.matchIdAndOrigin(
destinationId, origin)) {
this.selectDefaultDestination_();
}
- },
+ }
/**
* Called when the /search call completes, either successfully or not.
@@ -1471,7 +1166,7 @@ cr.define('print_preview', function() {
* @param {Event} event Contains the request result.
* @private
*/
- onCloudPrintSearchDone_: function(event) {
+ onCloudPrintSearchDone_(event) {
if (event.printers) {
this.insertDestinations_(event.printers);
}
@@ -1483,7 +1178,7 @@ cr.define('print_preview', function() {
}
cr.dispatchSimpleEvent(
this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
- },
+ }
/**
* Called when /printer call completes. Updates the specified destination's
@@ -1492,9 +1187,9 @@ cr.define('print_preview', function() {
* destination.
* @private
*/
- onCloudPrintPrinterDone_: function(event) {
+ onCloudPrintPrinterDone_(event) {
this.updateDestination_(event.printer);
- },
+ }
/**
* Called when the Google Cloud Print interface fails to lookup a
@@ -1504,7 +1199,7 @@ cr.define('print_preview', function() {
* to be looked up.
* @private
*/
- onCloudPrintPrinterFailed_: function(event) {
+ onCloudPrintPrinterFailed_(event) {
if (this.autoSelectMatchingDestination_ &&
this.autoSelectMatchingDestination_.matchIdAndOrigin(
event.destinationId, event.destinationOrigin)) {
@@ -1512,7 +1207,7 @@ cr.define('print_preview', function() {
'Failed to fetch last used printer caps: ' + event.destinationId);
this.selectDefaultDestination_();
}
- },
+ }
/**
* Called when printer sharing invitation was processed successfully.
@@ -1520,105 +1215,49 @@ cr.define('print_preview', function() {
* newly accepted destination (if known).
* @private
*/
- onCloudPrintProcessInviteDone_: function(event) {
+ onCloudPrintProcessInviteDone_(event) {
if (event.accept && event.printer) {
// Hint the destination list to promote this new destination.
event.printer.isRecent = true;
this.insertDestination_(event.printer);
}
- },
-
- /**
- * Called when a Privet printer is added to the local network.
- * @param {!{serviceName: string,
- * name: string,
- * hasLocalPrinting: boolean,
- * isUnregistered: boolean,
- * cloudID: string}} printer Information about the added printer.
- * @private
- */
- onPrivetPrinterAdded_: function(printer) {
- if (printer.serviceName == this.waitForRegisterDestination_ &&
- !printer.isUnregistered) {
- this.waitForRegisterDestination_ = null;
- this.onDestinationsReload();
- } else {
- this.insertDestinations_(
- print_preview.PrivetDestinationParser.parse(printer));
- }
- },
-
- /**
- * Called when capabilities for a privet printer are set.
- * @param {!print_preview.PrivetPrinterCapabilitiesResponse} printerInfo
- * Contains the privet printer's description and capabilities.
- * @private
- */
- onPrivetCapabilitiesSet_: function(printerInfo) {
- var destinations =
- print_preview.PrivetDestinationParser.parse(printerInfo.printer);
- destinations.forEach(function(dest) {
- dest.capabilities = printerInfo.capabilities;
- this.updateDestination_(dest);
- }, this);
- },
-
- /**
- * Called when an extension responds to a getExtensionDestinations
- * request.
- * @param {!Array<!{extensionId: string,
- * extensionName: string,
- * id: string,
- * name: string,
- * description: (string|undefined),
- * provisional: (boolean|undefined)}>} printers The list
- * containing information about printers added by an extension.
- * @private
- */
- onExtensionPrintersAdded_: function(printers) {
- this.insertDestinations_(
- printers.map(print_preview.ExtensionDestinationParser.parse));
- },
+ }
/**
- * Called when all extensions are done adding printers.
- * @private
- */
- onExtensionPrintersDone_: function() {
- if (this.isExtensionDestinationSearchInProgress_) {
- clearTimeout(this.extensionSearchTimeout_);
- this.endExtensionPrinterSearch_();
+ * Called when a printer or printers are detected after sending getPrinters
+ * from the native layer.
+ * @param {print_preview.PrinterType} type The type of printer(s) added.
+ * @param {!Array<!print_preview.LocalDestinationInfo |
+ * !print_preview.PrivetPrinterDescription |
+ * !print_preview.ProvisionalDestinationInfo>} printers
+ * Information about the printers that have been retrieved.
+ */
+ onPrintersAdded_(type, printers) {
+ if (type == print_preview.PrinterType.PRIVET_PRINTER) {
+ var printer =
+ /** !print_preview.PrivetPrinterDescription */ (printers[0]);
+ if (printer.serviceName == this.waitForRegisterDestination_ &&
+ !printer.isUnregistered) {
+ this.waitForRegisterDestination_ = null;
+ this.onDestinationsReload();
+ return;
+ }
}
- },
-
- /**
- * Called when capabilities for an extension managed printer are set.
- * @param {string} printerId The printer Id.
- * @param {!print_preview.Cdd} capabilities The printer's capabilities.
- * @private
- */
- onExtensionCapabilitiesSet_: function(printerId, capabilities) {
- var destinationKey = this.getDestinationKey_(
- print_preview.DestinationOrigin.EXTENSION, printerId,
- '' /* account */);
- var destination = this.destinationMap_[destinationKey];
- if (!destination)
- return;
- destination.capabilities = capabilities;
- this.updateDestination_(destination);
- },
+ this.insertDestinations_(printers.map(
+ printer => print_preview.parseDestination(type, printer)));
+ }
/**
* Called from print preview after the user was requested to sign in, and
* did so successfully.
*/
- onDestinationsReload: function() {
+ onDestinationsReload() {
this.reset_();
this.autoSelectMatchingDestination_ =
this.convertPreselectedToDestinationMatch_();
this.createLocalPdfPrintDestination_();
this.startLoadAllDestinations();
- },
+ }
// TODO(vitalybuka): Remove three next functions replacing Destination.id
// and Destination.origin by complex ID.
@@ -1630,19 +1269,232 @@ cr.define('print_preview', function() {
* @param {string} account User account destination is registered for.
* @private
*/
- getDestinationKey_: function(origin, id, account) {
+ getDestinationKey_(origin, id, account) {
return origin + '/' + id + '/' + account;
- },
+ }
/**
* Returns key to be used with {@code destinationMap_}.
* @param {!print_preview.Destination} destination Destination.
* @private
*/
- getKey_: function(destination) {
+ getKey_(destination) {
return this.getDestinationKey_(
destination.origin, destination.id, destination.account);
}
+ }
+
+ /**
+ * Event types dispatched by the data store.
+ * @enum {string}
+ */
+ DestinationStore.EventType = {
+ DESTINATION_SEARCH_DONE:
+ 'print_preview.DestinationStore.DESTINATION_SEARCH_DONE',
+ DESTINATION_SEARCH_STARTED:
+ 'print_preview.DestinationStore.DESTINATION_SEARCH_STARTED',
+ DESTINATION_SELECT: 'print_preview.DestinationStore.DESTINATION_SELECT',
+ DESTINATIONS_INSERTED:
+ 'print_preview.DestinationStore.DESTINATIONS_INSERTED',
+ PROVISIONAL_DESTINATION_RESOLVED:
+ 'print_preview.DestinationStore.PROVISIONAL_DESTINATION_RESOLVED',
+ CACHED_SELECTED_DESTINATION_INFO_READY:
+ 'print_preview.DestinationStore.CACHED_SELECTED_DESTINATION_INFO_READY',
+ SELECTED_DESTINATION_CAPABILITIES_READY: 'print_preview.DestinationStore' +
+ '.SELECTED_DESTINATION_CAPABILITIES_READY',
+ SELECTED_DESTINATION_INVALID:
+ 'print_preview.DestinationStore.SELECTED_DESTINATION_INVALID',
+ };
+
+ /**
+ * Delay in milliseconds before the destination store ignores the initial
+ * destination ID and just selects any printer (since the initial destination
+ * was not found).
+ * @private {number}
+ * @const
+ */
+ DestinationStore.AUTO_SELECT_TIMEOUT_ = 15000;
+
+ /**
+ * Maximum amount of time spent searching for extension destinations, in
+ * milliseconds.
+ * @private {number}
+ * @const
+ */
+ DestinationStore.EXTENSION_SEARCH_DURATION_ = 5000;
+
+ /**
+ * Human readable names for media sizes in the cloud print CDD.
+ * https://developers.google.com/cloud-print/docs/cdd
+ * @private {Object<string>}
+ * @const
+ */
+ DestinationStore.MEDIA_DISPLAY_NAMES_ = {
+ 'ISO_2A0': '2A0',
+ 'ISO_A0': 'A0',
+ 'ISO_A0X3': 'A0x3',
+ 'ISO_A1': 'A1',
+ 'ISO_A10': 'A10',
+ 'ISO_A1X3': 'A1x3',
+ 'ISO_A1X4': 'A1x4',
+ 'ISO_A2': 'A2',
+ 'ISO_A2X3': 'A2x3',
+ 'ISO_A2X4': 'A2x4',
+ 'ISO_A2X5': 'A2x5',
+ 'ISO_A3': 'A3',
+ 'ISO_A3X3': 'A3x3',
+ 'ISO_A3X4': 'A3x4',
+ 'ISO_A3X5': 'A3x5',
+ 'ISO_A3X6': 'A3x6',
+ 'ISO_A3X7': 'A3x7',
+ 'ISO_A3_EXTRA': 'A3 Extra',
+ 'ISO_A4': 'A4',
+ 'ISO_A4X3': 'A4x3',
+ 'ISO_A4X4': 'A4x4',
+ 'ISO_A4X5': 'A4x5',
+ 'ISO_A4X6': 'A4x6',
+ 'ISO_A4X7': 'A4x7',
+ 'ISO_A4X8': 'A4x8',
+ 'ISO_A4X9': 'A4x9',
+ 'ISO_A4_EXTRA': 'A4 Extra',
+ 'ISO_A4_TAB': 'A4 Tab',
+ 'ISO_A5': 'A5',
+ 'ISO_A5_EXTRA': 'A5 Extra',
+ 'ISO_A6': 'A6',
+ 'ISO_A7': 'A7',
+ 'ISO_A8': 'A8',
+ 'ISO_A9': 'A9',
+ 'ISO_B0': 'B0',
+ 'ISO_B1': 'B1',
+ 'ISO_B10': 'B10',
+ 'ISO_B2': 'B2',
+ 'ISO_B3': 'B3',
+ 'ISO_B4': 'B4',
+ 'ISO_B5': 'B5',
+ 'ISO_B5_EXTRA': 'B5 Extra',
+ 'ISO_B6': 'B6',
+ 'ISO_B6C4': 'B6C4',
+ 'ISO_B7': 'B7',
+ 'ISO_B8': 'B8',
+ 'ISO_B9': 'B9',
+ 'ISO_C0': 'C0',
+ 'ISO_C1': 'C1',
+ 'ISO_C10': 'C10',
+ 'ISO_C2': 'C2',
+ 'ISO_C3': 'C3',
+ 'ISO_C4': 'C4',
+ 'ISO_C5': 'C5',
+ 'ISO_C6': 'C6',
+ 'ISO_C6C5': 'C6C5',
+ 'ISO_C7': 'C7',
+ 'ISO_C7C6': 'C7C6',
+ 'ISO_C8': 'C8',
+ 'ISO_C9': 'C9',
+ 'ISO_DL': 'Envelope DL',
+ 'ISO_RA0': 'RA0',
+ 'ISO_RA1': 'RA1',
+ 'ISO_RA2': 'RA2',
+ 'ISO_SRA0': 'SRA0',
+ 'ISO_SRA1': 'SRA1',
+ 'ISO_SRA2': 'SRA2',
+ 'JIS_B0': 'B0 (JIS)',
+ 'JIS_B1': 'B1 (JIS)',
+ 'JIS_B10': 'B10 (JIS)',
+ 'JIS_B2': 'B2 (JIS)',
+ 'JIS_B3': 'B3 (JIS)',
+ 'JIS_B4': 'B4 (JIS)',
+ 'JIS_B5': 'B5 (JIS)',
+ 'JIS_B6': 'B6 (JIS)',
+ 'JIS_B7': 'B7 (JIS)',
+ 'JIS_B8': 'B8 (JIS)',
+ 'JIS_B9': 'B9 (JIS)',
+ 'JIS_EXEC': 'Executive (JIS)',
+ 'JPN_CHOU2': 'Choukei 2',
+ 'JPN_CHOU3': 'Choukei 3',
+ 'JPN_CHOU4': 'Choukei 4',
+ 'JPN_HAGAKI': 'Hagaki',
+ 'JPN_KAHU': 'Kahu Envelope',
+ 'JPN_KAKU2': 'Kaku 2',
+ 'JPN_OUFUKU': 'Oufuku Hagaki',
+ 'JPN_YOU4': 'You 4',
+ 'NA_10X11': '10x11',
+ 'NA_10X13': '10x13',
+ 'NA_10X14': '10x14',
+ 'NA_10X15': '10x15',
+ 'NA_11X12': '11x12',
+ 'NA_11X15': '11x15',
+ 'NA_12X19': '12x19',
+ 'NA_5X7': '5x7',
+ 'NA_6X9': '6x9',
+ 'NA_7X9': '7x9',
+ 'NA_9X11': '9x11',
+ 'NA_A2': 'A2',
+ 'NA_ARCH_A': 'Arch A',
+ 'NA_ARCH_B': 'Arch B',
+ 'NA_ARCH_C': 'Arch C',
+ 'NA_ARCH_D': 'Arch D',
+ 'NA_ARCH_E': 'Arch E',
+ 'NA_ASME_F': 'ASME F',
+ 'NA_B_PLUS': 'B-plus',
+ 'NA_C': 'C',
+ 'NA_C5': 'C5',
+ 'NA_D': 'D',
+ 'NA_E': 'E',
+ 'NA_EDP': 'EDP',
+ 'NA_EUR_EDP': 'European EDP',
+ 'NA_EXECUTIVE': 'Executive',
+ 'NA_F': 'F',
+ 'NA_FANFOLD_EUR': 'FanFold European',
+ 'NA_FANFOLD_US': 'FanFold US',
+ 'NA_FOOLSCAP': 'FanFold German Legal',
+ 'NA_GOVT_LEGAL': 'Government Legal',
+ 'NA_GOVT_LETTER': 'Government Letter',
+ 'NA_INDEX_3X5': 'Index 3x5',
+ 'NA_INDEX_4X6': 'Index 4x6',
+ 'NA_INDEX_4X6_EXT': 'Index 4x6 ext',
+ 'NA_INDEX_5X8': '5x8',
+ 'NA_INVOICE': 'Invoice',
+ 'NA_LEDGER': 'Tabloid', // Ledger in portrait is called Tabloid.
+ 'NA_LEGAL': 'Legal',
+ 'NA_LEGAL_EXTRA': 'Legal extra',
+ 'NA_LETTER': 'Letter',
+ 'NA_LETTER_EXTRA': 'Letter extra',
+ 'NA_LETTER_PLUS': 'Letter plus',
+ 'NA_MONARCH': 'Monarch',
+ 'NA_NUMBER_10': 'Envelope #10',
+ 'NA_NUMBER_11': 'Envelope #11',
+ 'NA_NUMBER_12': 'Envelope #12',
+ 'NA_NUMBER_14': 'Envelope #14',
+ 'NA_NUMBER_9': 'Envelope #9',
+ 'NA_PERSONAL': 'Personal',
+ 'NA_QUARTO': 'Quarto',
+ 'NA_SUPER_A': 'Super A',
+ 'NA_SUPER_B': 'Super B',
+ 'NA_WIDE_FORMAT': 'Wide format',
+ 'OM_DAI_PA_KAI': 'Dai-pa-kai',
+ 'OM_FOLIO': 'Folio',
+ 'OM_FOLIO_SP': 'Folio SP',
+ 'OM_INVITE': 'Invite Envelope',
+ 'OM_ITALIAN': 'Italian Envelope',
+ 'OM_JUURO_KU_KAI': 'Juuro-ku-kai',
+ 'OM_LARGE_PHOTO': 'Large photo',
+ 'OM_OFICIO': 'Oficio',
+ 'OM_PA_KAI': 'Pa-kai',
+ 'OM_POSTFIX': 'Postfix Envelope',
+ 'OM_SMALL_PHOTO': 'Small photo',
+ 'PRC_1': 'prc1 Envelope',
+ 'PRC_10': 'prc10 Envelope',
+ 'PRC_16K': 'prc 16k',
+ 'PRC_2': 'prc2 Envelope',
+ 'PRC_3': 'prc3 Envelope',
+ 'PRC_32K': 'prc 32k',
+ 'PRC_4': 'prc4 Envelope',
+ 'PRC_5': 'prc5 Envelope',
+ 'PRC_6': 'prc6 Envelope',
+ 'PRC_7': 'prc7 Envelope',
+ 'PRC_8': 'prc8 Envelope',
+ 'ROC_16K': 'ROC 16K',
+ 'ROC_8K': 'ROC 8k',
};
// Export
diff --git a/chromium/chrome/browser/resources/print_preview/data/invitation.js b/chromium/chrome/browser/resources/print_preview/data/invitation.js
index 8aef4f3b23c..6f5d09de7ee 100644
--- a/chromium/chrome/browser/resources/print_preview/data/invitation.js
+++ b/chromium/chrome/browser/resources/print_preview/data/invitation.js
@@ -5,62 +5,61 @@
cr.define('print_preview', function() {
'use strict';
- /**
- * Printer sharing invitation data object.
- * @param {string} sender Text identifying invitation sender.
- * @param {string} receiver Text identifying invitation receiver. Empty in
- * case of a personal invitation. Identifies a group or domain in case
- * of an invitation received by a group manager.
- * @param {!print_preview.Destination} destination Shared destination.
- * @param {!Object} aclEntry JSON representation of the ACL entry this
- * invitation was sent to.
- * @param {string} account User account this invitation is sent for.
- * @constructor
- */
- function Invitation(sender, receiver, destination, aclEntry, account) {
+ class Invitation {
/**
- * Text identifying invitation sender.
- * @private {string}
+ * Printer sharing invitation data object.
+ * @param {string} sender Text identifying invitation sender.
+ * @param {string} receiver Text identifying invitation receiver. Empty in
+ * case of a personal invitation. Identifies a group or domain in case
+ * of an invitation received by a group manager.
+ * @param {!print_preview.Destination} destination Shared destination.
+ * @param {!Object} aclEntry JSON representation of the ACL entry this
+ * invitation was sent to.
+ * @param {string} account User account this invitation is sent for.
*/
- this.sender_ = sender;
+ constructor(sender, receiver, destination, aclEntry, account) {
+ /**
+ * Text identifying invitation sender.
+ * @private {string}
+ */
+ this.sender_ = sender;
- /**
- * Text identifying invitation receiver. Empty in case of a personal
- * invitation. Identifies a group or domain in case of an invitation
- * received by a group manager.
- * @private {string}
- */
- this.receiver_ = receiver;
+ /**
+ * Text identifying invitation receiver. Empty in case of a personal
+ * invitation. Identifies a group or domain in case of an invitation
+ * received by a group manager.
+ * @private {string}
+ */
+ this.receiver_ = receiver;
- /**
- * Shared destination.
- * @private {!print_preview.Destination}
- */
- this.destination_ = destination;
+ /**
+ * Shared destination.
+ * @private {!print_preview.Destination}
+ */
+ this.destination_ = destination;
- /**
- * JSON representation of the ACL entry this invitation was sent to.
- * @private {!Object}
- */
- this.aclEntry_ = aclEntry;
+ /**
+ * JSON representation of the ACL entry this invitation was sent to.
+ * @private {!Object}
+ */
+ this.aclEntry_ = aclEntry;
- /**
- * Account this invitation is sent for.
- * @private {string}
- */
- this.account_ = account;
- }
+ /**
+ * Account this invitation is sent for.
+ * @private {string}
+ */
+ this.account_ = account;
+ }
- Invitation.prototype = {
/** @return {string} Text identifying invitation sender. */
get sender() {
return this.sender_;
- },
+ }
/** @return {string} Text identifying invitation receiver. */
get receiver() {
return this.receiver_;
- },
+ }
/**
* @return {boolean} Whether this user acts as a manager for a group of
@@ -68,23 +67,23 @@ cr.define('print_preview', function() {
*/
get asGroupManager() {
return !!this.receiver_;
- },
+ }
/** @return {!print_preview.Destination} Shared destination. */
get destination() {
return this.destination_;
- },
+ }
/** @return {string} Scope (account) this invitation was sent to. */
get scopeId() {
return this.aclEntry_['scope'] || '';
- },
+ }
/** @return {string} Account this invitation is sent for. */
get account() {
return this.account_;
}
- };
+ }
// Export
return {Invitation: Invitation};
diff --git a/chromium/chrome/browser/resources/print_preview/data/local_parsers.js b/chromium/chrome/browser/resources/print_preview/data/local_parsers.js
index 8748f37b625..9b09d62e06f 100644
--- a/chromium/chrome/browser/resources/print_preview/data/local_parsers.js
+++ b/chromium/chrome/browser/resources/print_preview/data/local_parsers.js
@@ -5,8 +5,33 @@
cr.define('print_preview', function() {
'use strict';
- /** Namespace that contains a method to parse local print destinations. */
- function LocalDestinationParser() {}
+ /**
+ * @param{!print_preview.PrinterType} type The type of printer to parse.
+ * @param{!print_preview.LocalDestinationInfo |
+ * !print_preview.PrivetPrinterDescription |
+ * !print_preview.ProvisionalDestinationInfo} printer Information
+ * about the printer. Type expected depends on |type|:
+ * For LOCAL_PRINTER => print_preview.LocalDestinationInfo
+ * For PRIVET_PRINTER => print_preview.PrivetPrinterDescription
+ * For EXTENSION_PRINTER => print_preview.ProvisionalDestinationInfo
+ * @return {!Array<!print_preview.Destination> | !print_preview.Destination}
+ */
+ var parseDestination = function(type, printer) {
+ if (type === print_preview.PrinterType.LOCAL_PRINTER) {
+ return parseLocalDestination(
+ /** @type {!print_preview.LocalDestinationInfo} */ (printer));
+ }
+ if (type === print_preview.PrinterType.PRIVET_PRINTER) {
+ return parsePrivetDestination(
+ /** @type {!print_preview.PrivetPrinterDescription} */ (printer));
+ }
+ if (type === print_preview.PrinterType.EXTENSION_PRINTER) {
+ return parseExtensionDestination(
+ /** @type {!print_preview.ProvisionalDestinationInfo} */ (printer));
+ }
+ assertNotReached('Unknown printer type ' + type);
+ return [];
+ };
/**
* Parses a local print destination.
@@ -14,7 +39,7 @@ cr.define('print_preview', function() {
* describing a local print destination.
* @return {!print_preview.Destination} Parsed local print destination.
*/
- LocalDestinationParser.parse = function(destinationInfo) {
+ var parseLocalDestination = function(destinationInfo) {
var options = {
description: destinationInfo.printerDescription,
isEnterprisePrinter: destinationInfo.cupsEnterprisePrinter
@@ -34,15 +59,14 @@ cr.define('print_preview', function() {
print_preview.DestinationConnectionStatus.ONLINE, options);
};
- function PrivetDestinationParser() {}
-
/**
* Parses a privet destination as one or more local printers.
* @param {!print_preview.PrivetPrinterDescription} destinationInfo Object
* that describes a privet printer.
- * @return {!Array<!print_preview.Destination>} Parsed destination info.
+ * @return {!print_preview.Destination |
+ * !Array<!print_preview.Destination>} Parsed destination info.
*/
- PrivetDestinationParser.parse = function(destinationInfo) {
+ var parsePrivetDestination = function(destinationInfo) {
var returnedPrinters = [];
if (destinationInfo.hasLocalPrinting) {
@@ -61,11 +85,10 @@ cr.define('print_preview', function() {
print_preview.DestinationConnectionStatus.UNREGISTERED));
}
- return returnedPrinters;
+ return returnedPrinters.length === 1 ? returnedPrinters[0] :
+ returnedPrinters;
};
- function ExtensionDestinationParser() {}
-
/**
* Parses an extension destination from an extension supplied printer
* description.
@@ -73,7 +96,7 @@ cr.define('print_preview', function() {
* describing an extension printer.
* @return {!print_preview.Destination} Parsed destination.
*/
- ExtensionDestinationParser.parse = function(destinationInfo) {
+ var parseExtensionDestination = function(destinationInfo) {
var provisionalType = destinationInfo.provisional ?
print_preview.DestinationProvisionalType.NEEDS_USB_PERMISSION :
print_preview.DestinationProvisionalType.NONE;
@@ -92,8 +115,7 @@ cr.define('print_preview', function() {
// Export
return {
- LocalDestinationParser: LocalDestinationParser,
- PrivetDestinationParser: PrivetDestinationParser,
- ExtensionDestinationParser: ExtensionDestinationParser
+ parseDestination: parseDestination,
+ parseExtensionDestination: parseExtensionDestination
};
});
diff --git a/chromium/chrome/browser/resources/print_preview/data/margins.js b/chromium/chrome/browser/resources/print_preview/data/margins.js
index ba8239b9210..b7bef50c686 100644
--- a/chromium/chrome/browser/resources/print_preview/data/margins.js
+++ b/chromium/chrome/browser/resources/print_preview/data/margins.js
@@ -5,54 +5,55 @@
cr.define('print_preview', function() {
'use strict';
- /**
- * Creates a Margins object that holds four margin values in points.
- * @param {number} top The top margin in pts.
- * @param {number} right The right margin in pts.
- * @param {number} bottom The bottom margin in pts.
- * @param {number} left The left margin in pts.
- * @constructor
- */
- function Margins(top, right, bottom, left) {
+ class Margins {
/**
- * Backing store for the margin values in points.
- * @type {!Object<
- * !print_preview.ticket_items.CustomMarginsOrientation, number>}
- * @private
+ * Creates a Margins object that holds four margin values in points.
+ * @param {number} top The top margin in pts.
+ * @param {number} right The right margin in pts.
+ * @param {number} bottom The bottom margin in pts.
+ * @param {number} left The left margin in pts.
*/
- this.value_ = {};
- this.value_[print_preview.ticket_items.CustomMarginsOrientation.TOP] = top;
- this.value_[print_preview.ticket_items.CustomMarginsOrientation.RIGHT] =
- right;
- this.value_[print_preview.ticket_items.CustomMarginsOrientation.BOTTOM] =
- bottom;
- this.value_[print_preview.ticket_items.CustomMarginsOrientation.LEFT] =
- left;
- }
+ constructor(top, right, bottom, left) {
+ /**
+ * Backing store for the margin values in points.
+ * @type {!Object<
+ * !print_preview.ticket_items.CustomMarginsOrientation, number>}
+ * @private
+ */
+ this.value_ = {};
+ this.value_[print_preview.ticket_items.CustomMarginsOrientation.TOP] =
+ top;
+ this.value_[print_preview.ticket_items.CustomMarginsOrientation.RIGHT] =
+ right;
+ this.value_[print_preview.ticket_items.CustomMarginsOrientation.BOTTOM] =
+ bottom;
+ this.value_[print_preview.ticket_items.CustomMarginsOrientation.LEFT] =
+ left;
+ }
- /**
- * Parses a margins object from the given serialized state.
- * @param {Object} state Serialized representation of the margins created by
- * the {@code serialize} method.
- * @return {!print_preview.Margins} New margins instance.
- */
- Margins.parse = function(state) {
- return new print_preview.Margins(
- state[print_preview.ticket_items.CustomMarginsOrientation.TOP] || 0,
- state[print_preview.ticket_items.CustomMarginsOrientation.RIGHT] || 0,
- state[print_preview.ticket_items.CustomMarginsOrientation.BOTTOM] || 0,
- state[print_preview.ticket_items.CustomMarginsOrientation.LEFT] || 0);
- };
+ /**
+ * Parses a margins object from the given serialized state.
+ * @param {Object} state Serialized representation of the margins created by
+ * the {@code serialize} method.
+ * @return {!print_preview.Margins} New margins instance.
+ */
+ static parse(state) {
+ return new print_preview.Margins(
+ state[print_preview.ticket_items.CustomMarginsOrientation.TOP] || 0,
+ state[print_preview.ticket_items.CustomMarginsOrientation.RIGHT] || 0,
+ state[print_preview.ticket_items.CustomMarginsOrientation.BOTTOM] ||
+ 0,
+ state[print_preview.ticket_items.CustomMarginsOrientation.LEFT] || 0);
+ }
- Margins.prototype = {
/**
* @param {!print_preview.ticket_items.CustomMarginsOrientation}
* orientation Specifies the margin value to get.
* @return {number} Value of the margin of the given orientation.
*/
- get: function(orientation) {
+ get(orientation) {
return this.value_[orientation];
- },
+ }
/**
* @param {!print_preview.ticket_items.CustomMarginsOrientation}
@@ -61,7 +62,7 @@ cr.define('print_preview', function() {
* @return {!print_preview.Margins} A new copy of |this| with the
* modification made to the specified margin.
*/
- set: function(orientation, value) {
+ set(orientation, value) {
var newValue = this.clone_();
newValue[orientation] = value;
return new Margins(
@@ -69,14 +70,14 @@ cr.define('print_preview', function() {
newValue[print_preview.ticket_items.CustomMarginsOrientation.RIGHT],
newValue[print_preview.ticket_items.CustomMarginsOrientation.BOTTOM],
newValue[print_preview.ticket_items.CustomMarginsOrientation.LEFT]);
- },
+ }
/**
* @param {print_preview.Margins} other The other margins object to compare
* against.
* @return {boolean} Whether this margins object is equal to another.
*/
- equals: function(other) {
+ equals(other) {
if (other == null) {
return false;
}
@@ -86,25 +87,25 @@ cr.define('print_preview', function() {
}
}
return true;
- },
+ }
/** @return {Object} A serialized representation of the margins. */
- serialize: function() {
+ serialize() {
return this.clone_();
- },
+ }
/**
* @return {Object} Cloned state of the margins.
* @private
*/
- clone_: function() {
+ clone_() {
var clone = {};
for (var o in this.value_) {
clone[o] = this.value_[o];
}
return clone;
}
- };
+ }
// Export
return {Margins: Margins};
diff --git a/chromium/chrome/browser/resources/print_preview/data/measurement_system.js b/chromium/chrome/browser/resources/print_preview/data/measurement_system.js
index 01c6a55f4ee..1548de6b4e1 100644
--- a/chromium/chrome/browser/resources/print_preview/data/measurement_system.js
+++ b/chromium/chrome/browser/resources/print_preview/data/measurement_system.js
@@ -32,23 +32,6 @@ cr.define('print_preview', function() {
}
/**
- * Parses |numberFormat| and extracts the symbols used for the thousands point
- * and decimal point.
- * @param {string} numberFormat The formatted version of the number 12345678.
- * @return {!Array<string>} The extracted symbols in the order
- * [thousandsSymbol, decimalSymbol]. For example,
- * parseNumberFormat("123,456.78") returns [",", "."].
- */
- MeasurementSystem.parseNumberFormat = function(numberFormat) {
- if (!numberFormat) {
- return [',', '.'];
- }
- var regex = /^(\d+)(\W?)(\d+)(\W?)(\d+)$/;
- var matches = numberFormat.match(regex) || ['', '', ',', '', '.'];
- return [matches[2], matches[4]];
- };
-
- /**
* Maximum resolution of local unit values.
* @type {!Object<!print_preview.MeasurementSystemUnitType, number>}
* @private
diff --git a/chromium/chrome/browser/resources/print_preview/data/measurement_system_unittest.gtestjs b/chromium/chrome/browser/resources/print_preview/data/measurement_system_unittest.gtestjs
deleted file mode 100644
index f81960d5969..00000000000
--- a/chromium/chrome/browser/resources/print_preview/data/measurement_system_unittest.gtestjs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * Test fixture for the MeasurementSystem.
- * @constructor
- * @extends {testing.Test}
- */
-function MeasurementSystemUnitTest() {
- testing.Test.call(this);
-}
-
-MeasurementSystemUnitTest.prototype = {
- __proto__: testing.Test.prototype,
-
- extraLibraries: [
- '../../../../../ui/webui/resources/js/cr.js',
- '../print_preview_utils.js',
- 'measurement_system.js'
- ]
-};
-
-TEST_F('MeasurementSystemUnitTest', 'parseNumberFormat', function() {
- assertTrue(areArraysEqual(
- ['.', ','],
- print_preview.MeasurementSystem.parseNumberFormat('123.456,78')));
- assertTrue(areArraysEqual(
- ['.', '.'],
- print_preview.MeasurementSystem.parseNumberFormat('123.456.78')));
- assertTrue(areArraysEqual(
- [',', '.'],
- print_preview.MeasurementSystem.parseNumberFormat('123,456.78')));
- assertTrue(areArraysEqual(
- [',', ','],
- print_preview.MeasurementSystem.parseNumberFormat('123,456,78')));
- assertTrue(areArraysEqual(
- [' ', ','],
- print_preview.MeasurementSystem.parseNumberFormat('123 456,78')));
- assertTrue(areArraysEqual(
- [' ', '.'],
- print_preview.MeasurementSystem.parseNumberFormat('123 456.78')));
- assertTrue(areArraysEqual(
- [' ', ' '],
- print_preview.MeasurementSystem.parseNumberFormat('123 456 78')));
- assertTrue(areArraysEqual(
- ['', ''],
- print_preview.MeasurementSystem.parseNumberFormat('123')));
-
- assertTrue(areArraysEqual(
- [',', '.'],
- print_preview.MeasurementSystem.parseNumberFormat('abcdef')));
- assertTrue(areArraysEqual(
- [',', '.'],
- print_preview.MeasurementSystem.parseNumberFormat(null)));
- assertTrue(areArraysEqual(
- [',', '.'],
- print_preview.MeasurementSystem.parseNumberFormat(undefined)));
- assertTrue(areArraysEqual(
- [',', '.'],
- print_preview.MeasurementSystem.parseNumberFormat('')));
- assertTrue(areArraysEqual(
- [',', '.'],
- print_preview.MeasurementSystem.parseNumberFormat('1')));
- assertTrue(areArraysEqual(
- [',', '.'],
- print_preview.MeasurementSystem.parseNumberFormat('12')));
-});
diff --git a/chromium/chrome/browser/resources/print_preview/data/page_number_set.js b/chromium/chrome/browser/resources/print_preview/data/page_number_set.js
index 81fb7b66815..7eef255936e 100644
--- a/chromium/chrome/browser/resources/print_preview/data/page_number_set.js
+++ b/chromium/chrome/browser/resources/print_preview/data/page_number_set.js
@@ -5,57 +5,56 @@
cr.define('print_preview', function() {
'use strict';
- /**
- * An immutable ordered set of page numbers.
- * @param {!Array<number>} pageNumberList A list of page numbers to include
- * in the set.
- * @constructor
- */
- function PageNumberSet(pageNumberList) {
+ class PageNumberSet {
/**
- * Internal data store for the page number set.
- * @type {!Array<number>}
- * @private
+ * An immutable ordered set of page numbers.
+ * @param {!Array<number>} pageNumberList A list of page numbers to include
+ * in the set.
*/
- this.pageNumberSet_ = pageListToPageSet(pageNumberList);
- }
+ constructor(pageNumberList) {
+ /**
+ * Internal data store for the page number set.
+ * @type {!Array<number>}
+ * @private
+ */
+ this.pageNumberSet_ = pageListToPageSet(pageNumberList);
+ }
- PageNumberSet.prototype = {
/** @return {number} The number of page numbers in the set. */
get size() {
return this.pageNumberSet_.length;
- },
+ }
/**
* @param {number} index 0-based index of the page number to get.
* @return {number} Page number at the given index.
*/
- getPageNumberAt: function(index) {
+ getPageNumberAt(index) {
return this.pageNumberSet_[index];
- },
+ }
/**
* @param {number} pageNumber 1-based page number to check for.
* @return {boolean} Whether the given page number is in the page range.
*/
- hasPageNumber: function(pageNumber) {
+ hasPageNumber(pageNumber) {
return arrayContains(this.pageNumberSet_, pageNumber);
- },
+ }
/**
* @param {number} pageNumber 1-based number of the page to get index of.
* @return {number} 0-based index of the given page number with respect to
* all of the pages in the page range.
*/
- getPageNumberIndex: function(pageNumber) {
+ getPageNumberIndex(pageNumber) {
return this.pageNumberSet_.indexOf(pageNumber);
- },
+ }
/** @return {!Array<number>} Array representation of the set. */
- asArray: function() {
+ asArray() {
return this.pageNumberSet_.slice(0);
- },
- };
+ }
+ }
// Export
return {PageNumberSet: PageNumberSet};
diff --git a/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js b/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js
index 63a42bc086f..6675843b53e 100644
--- a/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js
+++ b/chromium/chrome/browser/resources/print_preview/data/print_ticket_store.js
@@ -10,310 +10,289 @@ cr.define('print_preview', function() {
// destination changes, the new destination might not support duplex anymore,
// so we should clear the ticket's isDuplexEnabled state.
- /**
- * Storage of the print ticket and document statistics. Dispatches events when
- * the contents of the print ticket or document statistics change. Also
- * handles validation of the print ticket against destination capabilities and
- * against the document.
- * @param {!print_preview.DestinationStore} destinationStore Used to
- * understand which printer is selected.
- * @param {!print_preview.AppState} appState Print preview application state.
- * @param {!print_preview.DocumentInfo} documentInfo Document data model.
- * @constructor
- * @extends {cr.EventTarget}
- */
- function PrintTicketStore(destinationStore, appState, documentInfo) {
- cr.EventTarget.call(this);
-
- /**
- * Destination store used to understand which printer is selected.
- * @type {!print_preview.DestinationStore}
- * @private
- */
- this.destinationStore_ = destinationStore;
-
- /**
- * App state used to persist and load ticket values.
- * @type {!print_preview.AppState}
- * @private
- */
- this.appState_ = appState;
-
- /**
- * Information about the document to print.
- * @type {!print_preview.DocumentInfo}
- * @private
- */
- this.documentInfo_ = documentInfo;
-
- /**
- * Printing capabilities of Chromium and the currently selected destination.
- * @type {!print_preview.CapabilitiesHolder}
- * @private
- */
- this.capabilitiesHolder_ = new print_preview.CapabilitiesHolder();
-
- /**
- * Current measurement system. Used to work with margin measurements.
- * @type {!print_preview.MeasurementSystem}
- * @private
- */
- this.measurementSystem_ = new print_preview.MeasurementSystem(
- ',', '.', print_preview.MeasurementSystemUnitType.IMPERIAL);
-
- /**
- * Collate ticket item.
- * @type {!print_preview.ticket_items.Collate}
- * @private
- */
- this.collate_ = new print_preview.ticket_items.Collate(
- this.appState_, this.destinationStore_);
-
- /**
- * Color ticket item.
- * @type {!print_preview.ticket_items.Color}
- * @private
- */
- this.color_ = new print_preview.ticket_items.Color(
- this.appState_, this.destinationStore_);
-
- /**
- * Copies ticket item.
- * @type {!print_preview.ticket_items.Copies}
- * @private
- */
- this.copies_ =
- new print_preview.ticket_items.Copies(this.destinationStore_);
-
- /**
- * DPI ticket item.
- * @type {!print_preview.ticket_items.Dpi}
- * @private
- */
- this.dpi_ = new print_preview.ticket_items.Dpi(
- this.appState_, this.destinationStore_);
-
- /**
- * Duplex ticket item.
- * @type {!print_preview.ticket_items.Duplex}
- * @private
- */
- this.duplex_ = new print_preview.ticket_items.Duplex(
- this.appState_, this.destinationStore_);
-
- /**
- * Page range ticket item.
- * @type {!print_preview.ticket_items.PageRange}
- * @private
- */
- this.pageRange_ =
- new print_preview.ticket_items.PageRange(this.documentInfo_);
-
- /**
- * Rasterize PDF ticket item.
- * @type {!print_preview.ticket_items.Rasterize}
- * @private
- */
- this.rasterize_ = new print_preview.ticket_items.Rasterize(
- this.destinationStore_, this.documentInfo_);
-
- /**
- * Scaling ticket item.
- * @type {!print_preview.ticket_items.Scaling}
- * @private
- */
- this.scaling_ = new print_preview.ticket_items.Scaling(
- this.appState_, this.destinationStore_, this.documentInfo_);
-
- /**
- * Custom margins ticket item.
- * @type {!print_preview.ticket_items.CustomMargins}
- * @private
- */
- this.customMargins_ = new print_preview.ticket_items.CustomMargins(
- this.appState_, this.documentInfo_);
-
- /**
- * Margins type ticket item.
- * @type {!print_preview.ticket_items.MarginsType}
- * @private
- */
- this.marginsType_ = new print_preview.ticket_items.MarginsType(
- this.appState_, this.documentInfo_, this.customMargins_);
-
- /**
- * Media size ticket item.
- * @type {!print_preview.ticket_items.MediaSize}
- * @private
- */
- this.mediaSize_ = new print_preview.ticket_items.MediaSize(
- this.appState_, this.destinationStore_, this.documentInfo_,
- this.marginsType_, this.customMargins_);
-
- /**
- * Landscape ticket item.
- * @type {!print_preview.ticket_items.Landscape}
- * @private
- */
- this.landscape_ = new print_preview.ticket_items.Landscape(
- this.appState_, this.destinationStore_, this.documentInfo_,
- this.marginsType_, this.customMargins_);
-
- /**
- * Header-footer ticket item.
- * @type {!print_preview.ticket_items.HeaderFooter}
- * @private
- */
- this.headerFooter_ = new print_preview.ticket_items.HeaderFooter(
- this.appState_, this.documentInfo_, this.marginsType_,
- this.customMargins_, this.mediaSize_, this.landscape_);
-
- /**
- * Fit-to-page ticket item.
- * @type {!print_preview.ticket_items.FitToPage}
- * @private
- */
- this.fitToPage_ = new print_preview.ticket_items.FitToPage(
- this.appState_, this.documentInfo_, this.destinationStore_);
-
- /**
- * Print CSS backgrounds ticket item.
- * @type {!print_preview.ticket_items.CssBackground}
- * @private
- */
- this.cssBackground_ = new print_preview.ticket_items.CssBackground(
- this.appState_, this.documentInfo_);
-
- /**
- * Print selection only ticket item.
- * @type {!print_preview.ticket_items.SelectionOnly}
- * @private
- */
- this.selectionOnly_ =
- new print_preview.ticket_items.SelectionOnly(this.documentInfo_);
+ class PrintTicketStore extends cr.EventTarget {
+ /**
+ * Storage of the print ticket and document statistics. Dispatches events
+ * when the contents of the print ticket or document statistics change. Also
+ * handles validation of the print ticket against destination capabilities
+ * and against the document.
+ * @param {!print_preview.DestinationStore} destinationStore Used to
+ * understand which printer is selected.
+ * @param {!print_preview.AppState} appState Print preview application
+ * state.
+ * @param {!print_preview.DocumentInfo} documentInfo Document data model.
+ */
+ constructor(destinationStore, appState, documentInfo) {
+ super();
+
+ /**
+ * Destination store used to understand which printer is selected.
+ * @type {!print_preview.DestinationStore}
+ * @private
+ */
+ this.destinationStore_ = destinationStore;
+
+ /**
+ * App state used to persist and load ticket values.
+ * @type {!print_preview.AppState}
+ * @private
+ */
+ this.appState_ = appState;
+
+ /**
+ * Information about the document to print.
+ * @type {!print_preview.DocumentInfo}
+ * @private
+ */
+ this.documentInfo_ = documentInfo;
+
+ /**
+ * Printing capabilities of Chromium and the currently selected
+ * destination.
+ * @type {!print_preview.CapabilitiesHolder}
+ * @private
+ */
+ this.capabilitiesHolder_ = new print_preview.CapabilitiesHolder();
+
+ /**
+ * Current measurement system. Used to work with margin measurements.
+ * @type {!print_preview.MeasurementSystem}
+ * @private
+ */
+ this.measurementSystem_ = new print_preview.MeasurementSystem(
+ ',', '.', print_preview.MeasurementSystemUnitType.IMPERIAL);
+
+ /**
+ * Collate ticket item.
+ * @type {!print_preview.ticket_items.Collate}
+ * @private
+ */
+ this.collate_ = new print_preview.ticket_items.Collate(
+ this.appState_, this.destinationStore_);
+
+ /**
+ * Color ticket item.
+ * @type {!print_preview.ticket_items.Color}
+ * @private
+ */
+ this.color_ = new print_preview.ticket_items.Color(
+ this.appState_, this.destinationStore_);
+
+ /**
+ * Copies ticket item.
+ * @type {!print_preview.ticket_items.Copies}
+ * @private
+ */
+ this.copies_ =
+ new print_preview.ticket_items.Copies(this.destinationStore_);
+
+ /**
+ * DPI ticket item.
+ * @type {!print_preview.ticket_items.Dpi}
+ * @private
+ */
+ this.dpi_ = new print_preview.ticket_items.Dpi(
+ this.appState_, this.destinationStore_);
+
+ /**
+ * Duplex ticket item.
+ * @type {!print_preview.ticket_items.Duplex}
+ * @private
+ */
+ this.duplex_ = new print_preview.ticket_items.Duplex(
+ this.appState_, this.destinationStore_);
+
+ /**
+ * Page range ticket item.
+ * @type {!print_preview.ticket_items.PageRange}
+ * @private
+ */
+ this.pageRange_ =
+ new print_preview.ticket_items.PageRange(this.documentInfo_);
+
+ /**
+ * Rasterize PDF ticket item.
+ * @type {!print_preview.ticket_items.Rasterize}
+ * @private
+ */
+ this.rasterize_ = new print_preview.ticket_items.Rasterize(
+ this.destinationStore_, this.documentInfo_);
+
+ /**
+ * Scaling ticket item.
+ * @type {!print_preview.ticket_items.Scaling}
+ * @private
+ */
+ this.scaling_ = new print_preview.ticket_items.Scaling(
+ this.appState_, this.destinationStore_, this.documentInfo_);
+
+ /**
+ * Custom margins ticket item.
+ * @type {!print_preview.ticket_items.CustomMargins}
+ * @private
+ */
+ this.customMargins_ = new print_preview.ticket_items.CustomMargins(
+ this.appState_, this.documentInfo_);
+
+ /**
+ * Margins type ticket item.
+ * @type {!print_preview.ticket_items.MarginsType}
+ * @private
+ */
+ this.marginsType_ = new print_preview.ticket_items.MarginsType(
+ this.appState_, this.documentInfo_, this.customMargins_);
+
+ /**
+ * Media size ticket item.
+ * @type {!print_preview.ticket_items.MediaSize}
+ * @private
+ */
+ this.mediaSize_ = new print_preview.ticket_items.MediaSize(
+ this.appState_, this.destinationStore_, this.documentInfo_,
+ this.marginsType_, this.customMargins_);
+
+ /**
+ * Landscape ticket item.
+ * @type {!print_preview.ticket_items.Landscape}
+ * @private
+ */
+ this.landscape_ = new print_preview.ticket_items.Landscape(
+ this.appState_, this.destinationStore_, this.documentInfo_,
+ this.marginsType_, this.customMargins_);
+
+ /**
+ * Header-footer ticket item.
+ * @type {!print_preview.ticket_items.HeaderFooter}
+ * @private
+ */
+ this.headerFooter_ = new print_preview.ticket_items.HeaderFooter(
+ this.appState_, this.documentInfo_, this.marginsType_,
+ this.customMargins_, this.mediaSize_, this.landscape_);
+
+ /**
+ * Fit-to-page ticket item.
+ * @type {!print_preview.ticket_items.FitToPage}
+ * @private
+ */
+ this.fitToPage_ = new print_preview.ticket_items.FitToPage(
+ this.appState_, this.documentInfo_, this.destinationStore_);
+
+ /**
+ * Print CSS backgrounds ticket item.
+ * @type {!print_preview.ticket_items.CssBackground}
+ * @private
+ */
+ this.cssBackground_ = new print_preview.ticket_items.CssBackground(
+ this.appState_, this.documentInfo_);
+
+ /**
+ * Print selection only ticket item.
+ * @type {!print_preview.ticket_items.SelectionOnly}
+ * @private
+ */
+ this.selectionOnly_ =
+ new print_preview.ticket_items.SelectionOnly(this.documentInfo_);
+
+ /**
+ * Vendor ticket items.
+ * @type {!print_preview.ticket_items.VendorItems}
+ * @private
+ */
+ this.vendorItems_ = new print_preview.ticket_items.VendorItems(
+ this.appState_, this.destinationStore_);
+
+ /**
+ * Keeps track of event listeners for the print ticket store.
+ * @type {!EventTracker}
+ * @private
+ */
+ this.tracker_ = new EventTracker();
+
+ /**
+ * Whether the print preview has been initialized.
+ * @type {boolean}
+ * @private
+ */
+ this.isInitialized_ = false;
+
+ this.addEventListeners_();
+ }
- /**
- * Vendor ticket items.
- * @type {!print_preview.ticket_items.VendorItems}
- * @private
- */
- this.vendorItems_ = new print_preview.ticket_items.VendorItems(
- this.appState_, this.destinationStore_);
-
- /**
- * Keeps track of event listeners for the print ticket store.
- * @type {!EventTracker}
- * @private
- */
- this.tracker_ = new EventTracker();
-
- /**
- * Whether the print preview has been initialized.
- * @type {boolean}
- * @private
- */
- this.isInitialized_ = false;
-
- this.addEventListeners_();
- }
-
- /**
- * Event types dispatched by the print ticket store.
- * @enum {string}
- */
- PrintTicketStore.EventType = {
- CAPABILITIES_CHANGE: 'print_preview.PrintTicketStore.CAPABILITIES_CHANGE',
- DOCUMENT_CHANGE: 'print_preview.PrintTicketStore.DOCUMENT_CHANGE',
- INITIALIZE: 'print_preview.PrintTicketStore.INITIALIZE',
- TICKET_CHANGE: 'print_preview.PrintTicketStore.TICKET_CHANGE'
- };
-
- PrintTicketStore.prototype = {
- __proto__: cr.EventTarget.prototype,
-
- /**
- * Whether the print preview has been initialized.
- * @type {boolean}
- */
get isInitialized() {
return this.isInitialized_;
- },
+ }
get collate() {
return this.collate_;
- },
+ }
get color() {
return this.color_;
- },
+ }
get copies() {
return this.copies_;
- },
+ }
get cssBackground() {
return this.cssBackground_;
- },
+ }
get customMargins() {
return this.customMargins_;
- },
+ }
get dpi() {
return this.dpi_;
- },
+ }
get duplex() {
return this.duplex_;
- },
+ }
get fitToPage() {
return this.fitToPage_;
- },
+ }
get headerFooter() {
return this.headerFooter_;
- },
+ }
get mediaSize() {
return this.mediaSize_;
- },
+ }
get landscape() {
return this.landscape_;
- },
+ }
get marginsType() {
return this.marginsType_;
- },
+ }
get pageRange() {
return this.pageRange_;
- },
+ }
get rasterize() {
return this.rasterize_;
- },
+ }
get scaling() {
return this.scaling_;
- },
+ }
get selectionOnly() {
return this.selectionOnly_;
- },
+ }
get vendorItems() {
return this.vendorItems_;
- },
+ }
- /**
- * @return {!print_preview.MeasurementSystem} Measurement system of the
- * local system.
- */
get measurementSystem() {
return this.measurementSystem_;
- },
+ }
/**
* Initializes the print ticket store. Dispatches an INITIALIZE event.
@@ -324,8 +303,7 @@ cr.define('print_preview', function() {
* @param {boolean} selectionOnly Whether only selected content should be
* printed.
*/
- init: function(
- thousandsDelimeter, decimalDelimeter, unitType, selectionOnly) {
+ init(thousandsDelimeter, decimalDelimeter, unitType, selectionOnly) {
this.measurementSystem_.setSystem(
thousandsDelimeter, decimalDelimeter, unitType);
this.selectionOnly_.updateValue(selectionOnly);
@@ -404,35 +382,35 @@ cr.define('print_preview', function() {
/** @type {!Object<string>} */ (this.appState_.getField(
print_preview.AppStateField.VENDOR_OPTIONS)));
}
- },
+ }
/**
* @return {boolean} {@code true} if the stored print ticket is valid,
* {@code false} otherwise.
*/
- isTicketValid: function() {
+ isTicketValid() {
return this.isTicketValidForPreview() &&
(!this.copies_.isCapabilityAvailable() || this.copies_.isValid()) &&
(!this.pageRange_.isCapabilityAvailable() ||
this.pageRange_.isValid());
- },
+ }
/** @return {boolean} Whether the ticket is valid for preview generation. */
- isTicketValidForPreview: function() {
+ isTicketValidForPreview() {
return (
(!this.marginsType_.isCapabilityAvailable() ||
!this.marginsType_.isValueEqual(
print_preview.ticket_items.MarginsTypeValue.CUSTOM) ||
this.customMargins_.isValid()) &&
(!this.scaling_.isCapabilityAvailable() || this.scaling_.isValid()));
- },
+ }
/**
* Creates an object that represents a Google Cloud Print print ticket.
* @param {!print_preview.Destination} destination Destination to print to.
* @return {string} Google Cloud Print print ticket.
*/
- createPrintTicket: function(destination) {
+ createPrintTicket(destination) {
assert(
!destination.isLocal || destination.isPrivet ||
destination.isExtension,
@@ -506,18 +484,13 @@ cr.define('print_preview', function() {
}
}
return JSON.stringify(cjt);
- },
+ }
/**
* Adds event listeners for the print ticket store.
* @private
*/
- addEventListeners_: function() {
- this.tracker_.add(
- this.destinationStore_,
- print_preview.DestinationStore.EventType.DESTINATION_SELECT,
- this.onDestinationSelect_.bind(this));
-
+ addEventListeners_() {
this.tracker_.add(
this.destinationStore_,
print_preview.DestinationStore.EventType
@@ -537,14 +510,13 @@ cr.define('print_preview', function() {
this.tracker_.add(
this.documentInfo_, print_preview.DocumentInfo.EventType.CHANGE,
this.onDocumentInfoChange_.bind(this));
- },
+ }
/**
- * Called when the destination selected.
+ * Called when the capabilities of the selected destination are ready.
* @private
*/
- onDestinationSelect_: function() {
- // Reset user selection for certain ticket items.
+ onSelectedDestinationCapabilitiesReady_() {
if (this.capabilitiesHolder_.get() != null) {
this.customMargins_.updateValue(null);
if (this.marginsType_.getValue() ==
@@ -554,13 +526,6 @@ cr.define('print_preview', function() {
}
this.vendorItems_.updateValue({});
}
- },
-
- /**
- * Called when the capabilities of the selected destination are ready.
- * @private
- */
- onSelectedDestinationCapabilitiesReady_: function() {
var caps =
assert(this.destinationStore_.selectedDestination.capabilities);
var isFirstUpdate = this.capabilitiesHolder_.get() == null;
@@ -572,16 +537,26 @@ cr.define('print_preview', function() {
cr.dispatchSimpleEvent(
this, PrintTicketStore.EventType.CAPABILITIES_CHANGE);
}
- },
+ }
/**
* Called when document data model has changed. Dispatches a print ticket
* store event.
* @private
*/
- onDocumentInfoChange_: function() {
+ onDocumentInfoChange_() {
cr.dispatchSimpleEvent(this, PrintTicketStore.EventType.DOCUMENT_CHANGE);
- },
+ }
+ }
+
+ /**
+ * Event types dispatched by the print ticket store.
+ * @enum {string}
+ */
+ PrintTicketStore.EventType = {
+ CAPABILITIES_CHANGE: 'print_preview.PrintTicketStore.CAPABILITIES_CHANGE',
+ DOCUMENT_CHANGE: 'print_preview.PrintTicketStore.DOCUMENT_CHANGE',
+ INITIALIZE: 'print_preview.PrintTicketStore.INITIALIZE',
};
// Export
diff --git a/chromium/chrome/browser/resources/print_preview/data/printable_area.js b/chromium/chrome/browser/resources/print_preview/data/printable_area.js
index ae0f076096e..83791b717d7 100644
--- a/chromium/chrome/browser/resources/print_preview/data/printable_area.js
+++ b/chromium/chrome/browser/resources/print_preview/data/printable_area.js
@@ -5,56 +5,55 @@
cr.define('print_preview', function() {
'use strict';
- /**
- * Object describing the printable area of a page in the document.
- * @param {!print_preview.Coordinate2d} origin Top left corner of the
- * printable area of the document.
- * @param {!print_preview.Size} size Size of the printable area of the
- * document.
- * @constructor
- */
- function PrintableArea(origin, size) {
+ class PrintableArea {
/**
- * Top left corner of the printable area of the document.
- * @type {!print_preview.Coordinate2d}
- * @private
+ * Object describing the printable area of a page in the document.
+ * @param {!print_preview.Coordinate2d} origin Top left corner of the
+ * printable area of the document.
+ * @param {!print_preview.Size} size Size of the printable area of the
+ * document.
*/
- this.origin_ = origin;
+ constructor(origin, size) {
+ /**
+ * Top left corner of the printable area of the document.
+ * @type {!print_preview.Coordinate2d}
+ * @private
+ */
+ this.origin_ = origin;
- /**
- * Size of the printable area of the document.
- * @type {!print_preview.Size}
- * @private
- */
- this.size_ = size;
- }
+ /**
+ * Size of the printable area of the document.
+ * @type {!print_preview.Size}
+ * @private
+ */
+ this.size_ = size;
+ }
- PrintableArea.prototype = {
/**
* @return {!print_preview.Coordinate2d} Top left corner of the printable
* area of the document.
*/
get origin() {
return this.origin_;
- },
+ }
/**
* @return {!print_preview.Size} Size of the printable area of the document.
*/
get size() {
return this.size_;
- },
+ }
/**
* @param {print_preview.PrintableArea} other Other printable area to check
* for equality.
* @return {boolean} Whether another printable area is equal to this one.
*/
- equals: function(other) {
+ equals(other) {
return other != null && this.origin_.equals(other.origin_) &&
this.size_.equals(other.size_);
}
- };
+ }
// Export
return {PrintableArea: PrintableArea};
diff --git a/chromium/chrome/browser/resources/print_preview/data/size.js b/chromium/chrome/browser/resources/print_preview/data/size.js
index 078ce7d7b1e..8012258284d 100644
--- a/chromium/chrome/browser/resources/print_preview/data/size.js
+++ b/chromium/chrome/browser/resources/print_preview/data/size.js
@@ -5,48 +5,47 @@
cr.define('print_preview', function() {
'use strict';
- /**
- * Immutable two-dimensional size.
- * @param {number} width Width of the size.
- * @param {number} height Height of the size.
- * @constructor
- */
- function Size(width, height) {
+ class Size {
/**
- * Width of the size.
- * @type {number}
- * @private
+ * Immutable two-dimensional size.
+ * @param {number} width Width of the size.
+ * @param {number} height Height of the size.
*/
- this.width_ = width;
+ constructor(width, height) {
+ /**
+ * Width of the size.
+ * @type {number}
+ * @private
+ */
+ this.width_ = width;
- /**
- * Height of the size.
- * @type {number}
- * @private
- */
- this.height_ = height;
- }
+ /**
+ * Height of the size.
+ * @type {number}
+ * @private
+ */
+ this.height_ = height;
+ }
- Size.prototype = {
/** @return {number} Width of the size. */
get width() {
return this.width_;
- },
+ }
/** @return {number} Height of the size. */
get height() {
return this.height_;
- },
+ }
/**
* @param {print_preview.Size} other Other size object to compare against.
* @return {boolean} Whether this size object is equal to another.
*/
- equals: function(other) {
+ equals(other) {
return other != null && this.width_ == other.width_ &&
this.height_ == other.height_;
}
- };
+ }
// Export
return {Size: Size};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/collate.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/collate.js
index ec59d895da3..227cf03cf2d 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/collate.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/collate.js
@@ -5,57 +5,53 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Collate ticket item whose value is a {@code boolean} that indicates whether
- * collation is enabled.
- * @param {!print_preview.AppState} appState App state used to persist collate
- * selection.
- * @param {!print_preview.DestinationStore} destinationStore Destination store
- * used determine if a destination has the collate capability.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Collate(appState, destinationStore) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.IS_COLLATE_ENABLED,
- destinationStore);
- }
-
- Collate.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class Collate extends print_preview.ticket_items.TicketItem {
+ /**
+ * Collate ticket item whose value is a {@code boolean} that indicates
+ * whether collation is enabled.
+ * @param {!print_preview.AppState} appState App state used to persist
+ * collate selection.
+ * @param {!print_preview.DestinationStore} destinationStore Destination
+ * store used determine if a destination has the collate capability.
+ */
+ constructor(appState, destinationStore) {
+ super(
+ appState, print_preview.AppStateField.IS_COLLATE_ENABLED,
+ destinationStore);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return !!this.getCollateCapability_();
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
var capability = this.getCollateCapability_();
return capability.hasOwnProperty('default') ? capability.default : true;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return true;
- },
+ }
/**
* @return {Object} Collate capability of the selected destination.
* @private
*/
- getCollateCapability_: function() {
+ getCollateCapability_() {
var dest = this.getSelectedDestInternal();
return (dest && dest.capabilities && dest.capabilities.printer &&
dest.capabilities.printer.collate) ||
null;
}
- };
+ }
// Export
return {Collate: Collate};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/color.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/color.js
index 67d2dec3619..a78d6ccc9e1 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/color.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/color.js
@@ -5,44 +5,28 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Color ticket item whose value is a {@code boolean} that indicates whether
- * the document should be printed in color.
- * @param {!print_preview.AppState} appState App state persistence object to
- * save the state of the color selection.
- * @param {!print_preview.DestinationStore} destinationStore Used to determine
- * whether color printing should be available.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Color(appState, destinationStore) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.IS_COLOR_ENABLED,
- destinationStore);
- }
-
- /**
- * @private {!Array<string>} List of capability types considered color.
- * @const
- */
- Color.COLOR_TYPES_ = ['STANDARD_COLOR', 'CUSTOM_COLOR'];
-
- /**
- * @private {!Array<string>} List of capability types considered monochrome.
- * @const
- */
- Color.MONOCHROME_TYPES_ = ['STANDARD_MONOCHROME', 'CUSTOM_MONOCHROME'];
-
- Color.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class Color extends print_preview.ticket_items.TicketItem {
+ /**
+ * Color ticket item whose value is a {@code boolean} that indicates whether
+ * the document should be printed in color.
+ * @param {!print_preview.AppState} appState App state persistence object to
+ * save the state of the color selection.
+ * @param {!print_preview.DestinationStore} destinationStore Used to
+ * determine whether color printing should be available.
+ */
+ constructor(appState, destinationStore) {
+ super(
+ appState, print_preview.AppStateField.IS_COLOR_ENABLED,
+ destinationStore);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
var capability = this.capability;
if (!capability) {
return false;
@@ -55,7 +39,7 @@ cr.define('print_preview.ticket_items', function() {
(Color.MONOCHROME_TYPES_.indexOf(option.type) >= 0);
});
return hasColor && hasMonochrome;
- },
+ }
/** @return {Object} Color capability of the selected destination. */
get capability() {
@@ -63,10 +47,10 @@ cr.define('print_preview.ticket_items', function() {
return (dest && dest.capabilities && dest.capabilities.printer &&
dest.capabilities.printer.color) ||
null;
- },
+ }
/** @return {Object} Color option corresponding to the current value. */
- getSelectedOption: function() {
+ getSelectedOption() {
var capability = this.capability;
var options = capability ? capability.option : null;
if (options) {
@@ -82,19 +66,19 @@ cr.define('print_preview.ticket_items', function() {
}
}
return null;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
var capability = this.capability;
var defaultOption =
capability ? this.getDefaultColorOption_(capability.option) : null;
return defaultOption &&
(Color.COLOR_TYPES_.indexOf(defaultOption.type) >= 0);
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
// TODO(rltoscano): Get rid of this check based on destination ID. These
// destinations should really update their CDDs to have only one color
// option that has type 'STANDARD_COLOR'.
@@ -106,7 +90,7 @@ cr.define('print_preview.ticket_items', function() {
}
}
return this.getDefaultValueInternal();
- },
+ }
/**
* @param {!Array<!Object<{type: (string|undefined),
@@ -116,13 +100,26 @@ cr.define('print_preview.ticket_items', function() {
* option of the given list.
* @private
*/
- getDefaultColorOption_: function(options) {
+ getDefaultColorOption_(options) {
var defaultOptions = options.filter(function(option) {
return option.is_default;
});
return (defaultOptions.length == 0) ? null : defaultOptions[0];
}
- };
+ }
+
+ /**
+ * @private {!Array<string>} List of capability types considered color.
+ * @const
+ */
+ Color.COLOR_TYPES_ = ['STANDARD_COLOR', 'CUSTOM_COLOR'];
+
+ /**
+ * @private {!Array<string>} List of capability types considered monochrome.
+ * @const
+ */
+ Color.MONOCHROME_TYPES_ = ['STANDARD_MONOCHROME', 'CUSTOM_MONOCHROME'];
+
// Export
return {Color: Color};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/copies.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/copies.js
index 936342cb1d2..84f20a7cb2f 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/copies.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/copies.js
@@ -5,61 +5,56 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Copies ticket item whose value is a {@code string} that indicates how many
- * copies of the document should be printed. The ticket item is backed by a
- * string since the user can textually input the copies value.
- * @param {!print_preview.DestinationStore} destinationStore Destination store
- * used determine if a destination has the copies capability.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Copies(destinationStore) {
- print_preview.ticket_items.TicketItem.call(
- this, null /*appState*/, null /*field*/, destinationStore);
- }
-
- Copies.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class Copies extends print_preview.ticket_items.TicketItem {
+ /**
+ * Copies ticket item whose value is a {@code string} that indicates how
+ * many copies of the document should be printed. The ticket item is backed
+ * by a string since the user can textually input the copies value.
+ * @param {!print_preview.DestinationStore} destinationStore Destination
+ * store used to determine if a destination has the copies capability.
+ */
+ constructor(destinationStore) {
+ super(null /*appState*/, null /*field*/, destinationStore);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return value != '';
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return !!this.getCopiesCapability_();
- },
+ }
/** @return {number} The number of copies indicated by the ticket item. */
- getValueAsNumber: function() {
+ getValueAsNumber() {
var value = this.getValue();
return value == '' ? 0 : parseInt(value, 10);
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
var cap = this.getCopiesCapability_();
return cap.hasOwnProperty('default') ? cap.default : '1';
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return '1';
- },
+ }
/**
* @return {Object} Copies capability of the selected destination.
* @private
*/
- getCopiesCapability_: function() {
+ getCopiesCapability_() {
var dest = this.getSelectedDestInternal();
return (dest && dest.capabilities && dest.capabilities.printer &&
dest.capabilities.printer.copies) ||
null;
}
- };
+ }
// Export
return {Copies: Copies};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/css_background.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/css_background.js
index ab205878a7d..9279d03ec0f 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/css_background.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/css_background.js
@@ -5,45 +5,41 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Ticket item whose value is a {@code boolean} that represents whether to
- * print CSS backgrounds.
- * @param {!print_preview.AppState} appState App state to persist CSS
- * background value.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function CssBackground(appState, documentInfo) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.IS_CSS_BACKGROUND_ENABLED,
- null /*destinationStore*/, documentInfo);
- }
-
- CssBackground.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class CssBackground extends print_preview.ticket_items.TicketItem {
+ /**
+ * Ticket item whose value is a {@code boolean} that represents whether to
+ * print CSS backgrounds.
+ * @param {!print_preview.AppState} appState App state to persist CSS
+ * background value.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ */
+ constructor(appState, documentInfo) {
+ super(
+ appState, print_preview.AppStateField.IS_CSS_BACKGROUND_ENABLED,
+ null /*destinationStore*/, documentInfo);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return this.getDocumentInfoInternal().isModifiable;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return false;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return false;
}
- };
+ }
// Export
return {CssBackground: CssBackground};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js
index 97c0ed8399b..a29bc892378 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/custom_margins.js
@@ -21,51 +21,23 @@ cr.define('print_preview.ticket_items', function() {
var CustomMarginsOrientation =
print_preview.ticket_items.CustomMarginsOrientation;
- /**
- * Custom page margins ticket item whose value is a
- * {@code print_preview.Margins}.
- * @param {!print_preview.AppState} appState App state used to persist custom
- * margins.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function CustomMargins(appState, documentInfo) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.CUSTOM_MARGINS,
- null /*destinationStore*/, documentInfo);
- }
-
- /**
- * Mapping of a margin orientation to its opposite.
- * @type {!Object<!print_preview.ticket_items.CustomMarginsOrientation,
- * !print_preview.ticket_items.CustomMarginsOrientation>}
- * @private
- */
- CustomMargins.OppositeOrientation_ = {};
- CustomMargins.OppositeOrientation_[CustomMarginsOrientation.TOP] =
- CustomMarginsOrientation.BOTTOM;
- CustomMargins.OppositeOrientation_[CustomMarginsOrientation.RIGHT] =
- CustomMarginsOrientation.LEFT;
- CustomMargins.OppositeOrientation_[CustomMarginsOrientation.BOTTOM] =
- CustomMarginsOrientation.TOP;
- CustomMargins.OppositeOrientation_[CustomMarginsOrientation.LEFT] =
- CustomMarginsOrientation.RIGHT;
-
- /**
- * Minimum distance in points that two margins can be separated by.
- * @type {number}
- * @const
- * @private
- */
- CustomMargins.MINIMUM_MARGINS_DISTANCE_ = 72; // 1 inch.
-
- CustomMargins.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class CustomMargins extends print_preview.ticket_items.TicketItem {
+ /**
+ * Custom page margins ticket item whose value is a
+ * {@code print_preview.Margins}.
+ * @param {!print_preview.AppState} appState App state used to persist
+ * custom margins.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ */
+ constructor(appState, documentInfo) {
+ super(
+ appState, print_preview.AppStateField.CUSTOM_MARGINS,
+ null /*destinationStore*/, documentInfo);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
var margins = /** @type {!print_preview.Margins} */ (value);
for (var key in CustomMarginsOrientation) {
var o = CustomMarginsOrientation[key];
@@ -76,31 +48,31 @@ cr.define('print_preview.ticket_items', function() {
}
}
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return this.getDocumentInfoInternal().isModifiable;
- },
+ }
/** @override */
- isValueEqual: function(value) {
+ isValueEqual(value) {
return this.getValue().equals(value);
- },
+ }
/**
* @param {!print_preview.ticket_items.CustomMarginsOrientation}
* orientation Specifies the margin to get the maximum value for.
* @return {number} Maximum value in points of the specified margin.
*/
- getMarginMax: function(orientation) {
+ getMarginMax(orientation) {
var oppositeOrient = CustomMargins.OppositeOrientation_[orientation];
var margins = /** @type {!print_preview.Margins} */ (this.getValue());
return this.getMarginMax_(orientation, margins.get(oppositeOrient));
- },
+ }
/** @override */
- updateValue: function(value) {
+ updateValue(value) {
var margins = /** @type {!print_preview.Margins} */ (value);
if (margins != null) {
margins = new print_preview.Margins(
@@ -111,7 +83,7 @@ cr.define('print_preview.ticket_items', function() {
}
print_preview.ticket_items.TicketItem.prototype.updateValue.call(
this, margins);
- },
+ }
/**
* Updates the specified margin in points while keeping the value within
@@ -120,26 +92,26 @@ cr.define('print_preview.ticket_items', function() {
* orientation Specifies the margin to update.
* @param {number} value Updated margin value in points.
*/
- updateMargin: function(orientation, value) {
+ updateMargin(orientation, value) {
var margins = /** @type {!print_preview.Margins} */ (this.getValue());
var oppositeOrientation = CustomMargins.OppositeOrientation_[orientation];
var max =
this.getMarginMax_(orientation, margins.get(oppositeOrientation));
value = Math.max(0, Math.min(max, value));
this.updateValue(margins.set(orientation, value));
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return this.getDocumentInfoInternal().margins ||
new print_preview.Margins(72, 72, 72, 72);
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return this.getDocumentInfoInternal().margins ||
new print_preview.Margins(72, 72, 72, 72);
- },
+ }
/**
* @param {!print_preview.ticket_items.CustomMarginsOrientation}
@@ -149,7 +121,7 @@ cr.define('print_preview.ticket_items', function() {
* @return {number} Maximum value in points of the specified margin.
* @private
*/
- getMarginMax_: function(orientation, oppositeMargin) {
+ getMarginMax_(orientation, oppositeMargin) {
var dimensionLength = (orientation == CustomMarginsOrientation.TOP ||
orientation == CustomMarginsOrientation.BOTTOM) ?
this.getDocumentInfoInternal().pageSize.height :
@@ -159,7 +131,32 @@ cr.define('print_preview.ticket_items', function() {
dimensionLength - CustomMargins.MINIMUM_MARGINS_DISTANCE_;
return Math.round(totalMargin > 0 ? totalMargin - oppositeMargin : 0);
}
- };
+ }
+
+ /**
+ * Mapping of a margin orientation to its opposite.
+ * @type {!Object<!print_preview.ticket_items.CustomMarginsOrientation,
+ * !print_preview.ticket_items.CustomMarginsOrientation>}
+ * @private
+ */
+ CustomMargins.OppositeOrientation_ = {};
+ CustomMargins.OppositeOrientation_[CustomMarginsOrientation.TOP] =
+ CustomMarginsOrientation.BOTTOM;
+ CustomMargins.OppositeOrientation_[CustomMarginsOrientation.RIGHT] =
+ CustomMarginsOrientation.LEFT;
+ CustomMargins.OppositeOrientation_[CustomMarginsOrientation.BOTTOM] =
+ CustomMarginsOrientation.TOP;
+ CustomMargins.OppositeOrientation_[CustomMarginsOrientation.LEFT] =
+ CustomMarginsOrientation.RIGHT;
+
+ /**
+ * Minimum distance in points that two margins can be separated by.
+ * @type {number}
+ * @const
+ * @private
+ */
+ CustomMargins.MINIMUM_MARGINS_DISTANCE_ = 72; // 1 inch.
+
// Export
return {CustomMargins: CustomMargins};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/dpi.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/dpi.js
index 7a514f1c9d8..218c7cc9b8f 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/dpi.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/dpi.js
@@ -5,25 +5,20 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * DPI ticket item.
- * @param {!print_preview.AppState} appState App state used to persist DPI
- * selection.
- * @param {!print_preview.DestinationStore} destinationStore Destination store
- * used to determine if a destination has the DPI capability.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Dpi(appState, destinationStore) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.DPI, destinationStore);
- }
-
- Dpi.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class Dpi extends print_preview.ticket_items.TicketItem {
+ /**
+ * DPI ticket item.
+ * @param {!print_preview.AppState} appState App state used to persist DPI
+ * selection.
+ * @param {!print_preview.DestinationStore} destinationStore Destination
+ * store used to determine if a destination has the DPI capability.
+ */
+ constructor(appState, destinationStore) {
+ super(appState, print_preview.AppStateField.DPI, destinationStore);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
if (!this.isCapabilityAvailable())
return false;
return this.capability.option.some(function(option) {
@@ -31,21 +26,21 @@ cr.define('print_preview.ticket_items', function() {
option.vertical_dpi == value.vertical_dpi &&
option.vendor_id == value.vendor_id;
});
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return !!this.capability && !!this.capability.option &&
this.capability.option.length > 1;
- },
+ }
/** @override */
- isValueEqual: function(value) {
+ isValueEqual(value) {
var myValue = this.getValue();
return myValue.horizontal_dpi == value.horizontal_dpi &&
myValue.vertical_dpi == value.vertical_dpi &&
myValue.vendor_id == value.vendor_id;
- },
+ }
/** @return {Object} DPI capability of the selected destination. */
get capability() {
@@ -54,21 +49,21 @@ cr.define('print_preview.ticket_items', function() {
destination.capabilities.printer &&
destination.capabilities.printer.dpi) ||
null;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
var defaultOptions = this.capability.option.filter(function(option) {
return option.is_default;
});
return defaultOptions.length > 0 ? defaultOptions[0] : null;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return {};
}
- };
+ }
// Export
return {Dpi: Dpi};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/duplex.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/duplex.js
index 9930e1cac0b..6d061d70360 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/duplex.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/duplex.js
@@ -5,32 +5,28 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Duplex ticket item whose value is a {@code boolean} that indicates whether
- * the document should be duplex printed.
- * @param {!print_preview.AppState} appState App state used to persist collate
- * selection.
- * @param {!print_preview.DestinationStore} destinationStore Destination store
- * used determine if a destination has the collate capability.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Duplex(appState, destinationStore) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.IS_DUPLEX_ENABLED,
- destinationStore);
- }
-
- Duplex.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class Duplex extends print_preview.ticket_items.TicketItem {
+ /**
+ * Duplex ticket item whose value is a {@code boolean} that indicates
+ * whether the document should be duplex printed.
+ * @param {!print_preview.AppState} appState App state used to persist
+ * collate selection.
+ * @param {!print_preview.DestinationStore} destinationStore Destination
+ * store used determine if a destination has the collate capability.
+ */
+ constructor(appState, destinationStore) {
+ super(
+ appState, print_preview.AppStateField.IS_DUPLEX_ENABLED,
+ destinationStore);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
var cap = this.getDuplexCapability_();
if (!cap) {
return false;
@@ -42,34 +38,34 @@ cr.define('print_preview.ticket_items', function() {
hasSimplexOption = hasSimplexOption || option.type == 'NO_DUPLEX';
});
return hasLongEdgeOption && hasSimplexOption;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
var cap = this.getDuplexCapability_();
var defaultOptions = cap.option.filter(function(option) {
return option.is_default;
});
return defaultOptions.length == 0 ? false :
defaultOptions[0].type == 'LONG_EDGE';
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return false;
- },
+ }
/**
* @return {Object} Duplex capability of the selected destination.
* @private
*/
- getDuplexCapability_: function() {
+ getDuplexCapability_() {
var dest = this.getSelectedDestInternal();
return (dest && dest.capabilities && dest.capabilities.printer &&
dest.capabilities.printer.duplex) ||
null;
}
- };
+ }
// Export
return {Duplex: Duplex};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js
index 6dc52f782e9..e24c6fd11d2 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js
@@ -5,54 +5,51 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Fit-to-page ticket item whose value is a {@code boolean} that indicates
- * whether to scale the document to fit the page.
- * @param {!print_preview.AppState} appState App state to persist item value.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @param {!print_preview.DestinationStore} destinationStore Used to determine
- * whether fit to page should be available.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function FitToPage(appState, documentInfo, destinationStore) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.IS_FIT_TO_PAGE_ENABLED,
- destinationStore, documentInfo);
- }
-
- FitToPage.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class FitToPage extends print_preview.ticket_items.TicketItem {
+ /**
+ * Fit-to-page ticket item whose value is a {@code boolean} that indicates
+ * whether to scale the document to fit the page.
+ * @param {!print_preview.AppState} appState App state to persist item
+ * value.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ * @param {!print_preview.DestinationStore} destinationStore Used to
+ * determine whether fit to page should be available.
+ */
+ constructor(appState, documentInfo, destinationStore) {
+ super(
+ appState, print_preview.AppStateField.IS_FIT_TO_PAGE_ENABLED,
+ destinationStore, documentInfo);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return !this.getDocumentInfoInternal().isModifiable &&
(!this.getSelectedDestInternal() ||
this.getSelectedDestInternal().id !=
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF);
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
// It's on by default since it is not a document feature, it is rather
// a property of the printer, hardware margins limitations. User can
// always override it.
return true;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return !this.getSelectedDestInternal() ||
this.getSelectedDestInternal().id !=
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;
}
- };
+ }
// Export
return {FitToPage: FitToPage};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js
index b144537bbd4..f69389f27c9 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/header_footer.js
@@ -5,77 +5,64 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Header-footer ticket item whose value is a {@code boolean} that indicates
- * whether the document should be printed with headers and footers.
- * @param {!print_preview.AppState} appState App state used to persist whether
- * header-footer is enabled.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @param {!print_preview.ticket_items.MarginsType} marginsType Ticket item
- * that stores which predefined margins to print with.
- * @param {!print_preview.ticket_items.CustomMargins} customMargins Ticket
- * item that stores custom margin values.
- * @param {!print_preview.ticket_items.MediaSize} mediaSize Ticket item that
- * stores media size values.
- * @param {!print_preview.ticket_items.Landscape} landscape Ticket item that
- * stores landscape values.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function HeaderFooter(
- appState, documentInfo, marginsType, customMargins, mediaSize,
- landscape) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.IS_HEADER_FOOTER_ENABLED,
- null /*destinationStore*/, documentInfo);
-
+ class HeaderFooter extends print_preview.ticket_items.TicketItem {
/**
- * Ticket item that stores which predefined margins to print with.
- * @private {!print_preview.ticket_items.MarginsType}
+ * Header-footer ticket item whose value is a {@code boolean} that indicates
+ * whether the document should be printed with headers and footers.
+ * @param {!print_preview.AppState} appState App state used to persist
+ * whether header-footer is enabled.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ * @param {!print_preview.ticket_items.MarginsType} marginsType Ticket item
+ * that stores which predefined margins to print with.
+ * @param {!print_preview.ticket_items.CustomMargins} customMargins Ticket
+ * item that stores custom margin values.
+ * @param {!print_preview.ticket_items.MediaSize} mediaSize Ticket item that
+ * stores media size values.
+ * @param {!print_preview.ticket_items.Landscape} landscape Ticket item that
+ * stores landscape values.
*/
- this.marginsType_ = marginsType;
+ constructor(
+ appState, documentInfo, marginsType, customMargins, mediaSize,
+ landscape) {
+ super(
+ appState, print_preview.AppStateField.IS_HEADER_FOOTER_ENABLED,
+ null /*destinationStore*/, documentInfo);
- /**
- * Ticket item that stores custom margin values.
- * @private {!print_preview.ticket_items.CustomMargins}
- */
- this.customMargins_ = customMargins;
+ /**
+ * Ticket item that stores which predefined margins to print with.
+ * @private {!print_preview.ticket_items.MarginsType}
+ */
+ this.marginsType_ = marginsType;
- /**
- * Ticket item that stores media size values.
- * @private {!print_preview.ticket_items.MediaSize}
- */
- this.mediaSize_ = mediaSize;
+ /**
+ * Ticket item that stores custom margin values.
+ * @private {!print_preview.ticket_items.CustomMargins}
+ */
+ this.customMargins_ = customMargins;
- /**
- * Ticket item that stores landscape values.
- * @private {!print_preview.ticket_items.Landscape}
- */
- this.landscape_ = landscape;
+ /**
+ * Ticket item that stores media size values.
+ * @private {!print_preview.ticket_items.MediaSize}
+ */
+ this.mediaSize_ = mediaSize;
- this.addEventListeners_();
- }
+ /**
+ * Ticket item that stores landscape values.
+ * @private {!print_preview.ticket_items.Landscape}
+ */
+ this.landscape_ = landscape;
- /**
- * Minimum height of page in microns to allow headers and footers. Should
- * match the value for min_size_printer_units in printing/print_settings.cc
- * so that we do not request header/footer for margins that will be zero.
- * @private {number}
- * @const
- */
- HeaderFooter.MINIMUM_HEIGHT_MICRONS_ = 25400;
-
- HeaderFooter.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ this.addEventListeners_();
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
if (!this.getDocumentInfoInternal().isModifiable) {
return false;
}
@@ -108,23 +95,23 @@ cr.define('print_preview.ticket_items', function() {
var orientEnum = print_preview.ticket_items.CustomMarginsOrientation;
return margins == null || margins.get(orientEnum.TOP) > 0 ||
margins.get(orientEnum.BOTTOM) > 0;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return true;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return false;
- },
+ }
/**
* Adds CHANGE listeners to dependent ticket items.
* @private
*/
- addEventListeners_: function() {
+ addEventListeners_() {
this.getTrackerInternal().add(
this.marginsType_,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
@@ -142,7 +129,17 @@ cr.define('print_preview.ticket_items', function() {
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.dispatchChangeEventInternal.bind(this));
}
- };
+ }
+
+ /**
+ * Minimum height of page in microns to allow headers and footers. Should
+ * match the value for min_size_printer_units in printing/print_settings.cc
+ * so that we do not request header/footer for margins that will be zero.
+ * @private {number}
+ * @const
+ */
+ HeaderFooter.MINIMUM_HEIGHT_MICRONS_ = 25400;
+
// Export
return {HeaderFooter: HeaderFooter};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/landscape.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/landscape.js
index df4dc00d0e8..5c8ef4f6438 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/landscape.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/landscape.js
@@ -5,54 +5,50 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Landscape ticket item whose value is a {@code boolean} that indicates
- * whether the document should be printed in landscape orientation.
- * @param {!print_preview.AppState} appState App state object used to persist
- * ticket item values.
- * @param {!print_preview.DestinationStore} destinationStore Destination store
- * used to determine the default landscape value and if landscape
- * printing is available.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @param {!print_preview.ticket_items.MarginsType} marginsType Reset when
- * landscape value changes.
- * @param {!print_preview.ticket_items.CustomMargins} customMargins Reset when
- * landscape value changes.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Landscape(
- appState, destinationStore, documentInfo, marginsType, customMargins) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.IS_LANDSCAPE_ENABLED,
- destinationStore, documentInfo);
-
+ class Landscape extends print_preview.ticket_items.TicketItem {
/**
- * Margins ticket item. Reset when landscape ticket item changes.
- * @type {!print_preview.ticket_items.MarginsType}
- * @private
+ * Landscape ticket item whose value is a {@code boolean} that indicates
+ * whether the document should be printed in landscape orientation.
+ * @param {!print_preview.AppState} appState App state object used to
+ * persist ticket item values.
+ * @param {!print_preview.DestinationStore} destinationStore Destination
+ * store used to determine the default landscape value and if landscape
+ * printing is available.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ * @param {!print_preview.ticket_items.MarginsType} marginsType Reset when
+ * landscape value changes.
+ * @param {!print_preview.ticket_items.CustomMargins} customMargins Reset
+ * when landscape value changes.
*/
- this.marginsType_ = marginsType;
+ constructor(
+ appState, destinationStore, documentInfo, marginsType, customMargins) {
+ super(
+ appState, print_preview.AppStateField.IS_LANDSCAPE_ENABLED,
+ destinationStore, documentInfo);
- /**
- * Custom margins ticket item. Reset when landscape ticket item changes.
- * @type {!print_preview.ticket_items.CustomMargins}
- * @private
- */
- this.customMargins_ = customMargins;
- }
+ /**
+ * Margins ticket item. Reset when landscape ticket item changes.
+ * @type {!print_preview.ticket_items.MarginsType}
+ * @private
+ */
+ this.marginsType_ = marginsType;
- Landscape.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ /**
+ * Custom margins ticket item. Reset when landscape ticket item changes.
+ * @type {!print_preview.ticket_items.CustomMargins}
+ * @private
+ */
+ this.customMargins_ = customMargins;
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
var cap = this.getPageOrientationCapability_();
if (!cap)
return false;
@@ -70,28 +66,28 @@ cr.define('print_preview.ticket_items', function() {
return this.getDocumentInfoInternal().isModifiable &&
!this.getDocumentInfoInternal().hasCssMediaStyles &&
hasAutoOrPortraitOption && hasLandscapeOption;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
var cap = this.getPageOrientationCapability_();
var defaultOptions = cap.option.filter(function(option) {
return option.is_default;
});
return defaultOptions.length == 0 ? false :
defaultOptions[0].type == 'LANDSCAPE';
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
var doc = this.getDocumentInfoInternal();
return doc.hasCssMediaStyles ?
(doc.pageSize.width > doc.pageSize.height) :
false;
- },
+ }
/** @override */
- updateValueInternal: function(value) {
+ updateValueInternal(value) {
var updateMargins = !this.isValueEqual(value);
print_preview.ticket_items.TicketItem.prototype.updateValueInternal.call(
this, value);
@@ -101,32 +97,32 @@ cr.define('print_preview.ticket_items', function() {
print_preview.ticket_items.MarginsTypeValue.DEFAULT);
this.customMargins_.updateValue(null);
}
- },
+ }
/**
* @return {boolean} Whether capability contains the |value|.
* @param {string} value Option to check.
*/
- hasOption: function(value) {
+ hasOption(value) {
var cap = this.getPageOrientationCapability_();
if (!cap)
return false;
return cap.option.some(function(option) {
return option.type == value;
});
- },
+ }
/**
* @return {Object} Page orientation capability of the selected destination.
* @private
*/
- getPageOrientationCapability_: function() {
+ getPageOrientationCapability_() {
var dest = this.getSelectedDestInternal();
return (dest && dest.capabilities && dest.capabilities.printer &&
dest.capabilities.printer.page_orientation) ||
null;
}
- };
+ }
// Export
return {Landscape: Landscape};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/margins_type.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/margins_type.js
index 808e1486464..a9ae4351994 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/margins_type.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/margins_type.js
@@ -20,57 +20,53 @@ print_preview.ticket_items.MarginsTypeValue = {
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Margins type ticket item whose value is a
- * print_preview.ticket_items.MarginsTypeValue} that indicates what
- * predefined margins type to use.
- * @param {!print_preview.AppState} appState App state persistence object to
- * save the state of the margins type selection.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @param {!print_preview.ticket_items.CustomMargins} customMargins Custom
- * margins ticket item, used to write when margins type changes.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function MarginsType(appState, documentInfo, customMargins) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.MARGINS_TYPE,
- null /*destinationStore*/, documentInfo);
-
+ class MarginsType extends print_preview.ticket_items.TicketItem {
/**
- * Custom margins ticket item, used to write when margins type changes.
- * @type {!print_preview.ticket_items.CustomMargins}
- * @private
+ * Margins type ticket item whose value is a
+ * print_preview.ticket_items.MarginsTypeValue} that indicates what
+ * predefined margins type to use.
+ * @param {!print_preview.AppState} appState App state persistence object to
+ * save the state of the margins type selection.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ * @param {!print_preview.ticket_items.CustomMargins} customMargins Custom
+ * margins ticket item, used to write when margins type changes.
*/
- this.customMargins_ = customMargins;
- }
+ constructor(appState, documentInfo, customMargins) {
+ super(
+ appState, print_preview.AppStateField.MARGINS_TYPE,
+ null /*destinationStore*/, documentInfo);
- MarginsType.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ /**
+ * Custom margins ticket item, used to write when margins type changes.
+ * @type {!print_preview.ticket_items.CustomMargins}
+ * @private
+ */
+ this.customMargins_ = customMargins;
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return this.getDocumentInfoInternal().isModifiable;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return print_preview.ticket_items.MarginsTypeValue.DEFAULT;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return print_preview.ticket_items.MarginsTypeValue.DEFAULT;
- },
+ }
/** @override */
- updateValueInternal: function(value) {
+ updateValueInternal(value) {
print_preview.ticket_items.TicketItem.prototype.updateValueInternal.call(
this, value);
if (this.isValueEqual(
@@ -80,7 +76,7 @@ cr.define('print_preview.ticket_items', function() {
this.customMargins_.updateValue(this.customMargins_.getValue());
}
}
- };
+ }
// Export
return {MarginsType: MarginsType};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/media_size.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/media_size.js
index 09abc7a3c91..8f49b7eaaba 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/media_size.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/media_size.js
@@ -5,45 +5,42 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Media size ticket item.
- * @param {!print_preview.AppState} appState App state used to persist media
- * size selection.
- * @param {!print_preview.DestinationStore} destinationStore Destination store
- * used to determine if a destination has the media size capability.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @param {!print_preview.ticket_items.MarginsType} marginsType Reset when
- * landscape value changes.
- * @param {!print_preview.ticket_items.CustomMargins} customMargins Reset when
- * landscape value changes.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function MediaSize(
- appState, destinationStore, documentInfo, marginsType, customMargins) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.MEDIA_SIZE,
- destinationStore, documentInfo);
-
+ class MediaSize extends print_preview.ticket_items.TicketItem {
/**
- * Margins ticket item. Reset when this item changes.
- * @private {!print_preview.ticket_items.MarginsType}
+ * Media size ticket item.
+ * @param {!print_preview.AppState} appState App state used to persist media
+ * size selection.
+ * @param {!print_preview.DestinationStore} destinationStore Destination
+ * store used to determine if a destination has the media size
+ * capability.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ * @param {!print_preview.ticket_items.MarginsType} marginsType Reset when
+ * landscape value changes.
+ * @param {!print_preview.ticket_items.CustomMargins} customMargins Reset
+ * when landscape value changes.
*/
- this.marginsType_ = marginsType;
+ constructor(
+ appState, destinationStore, documentInfo, marginsType, customMargins) {
+ super(
+ appState, print_preview.AppStateField.MEDIA_SIZE, destinationStore,
+ documentInfo);
- /**
- * Custom margins ticket item. Reset when this item changes.
- * @private {!print_preview.ticket_items.CustomMargins}
- */
- this.customMargins_ = customMargins;
- }
+ /**
+ * Margins ticket item. Reset when this item changes.
+ * @private {!print_preview.ticket_items.MarginsType}
+ */
+ this.marginsType_ = marginsType;
- MediaSize.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ /**
+ * Custom margins ticket item. Reset when this item changes.
+ * @private {!print_preview.ticket_items.CustomMargins}
+ */
+ this.customMargins_ = customMargins;
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
if (!this.isCapabilityAvailable()) {
return false;
}
@@ -53,10 +50,10 @@ cr.define('print_preview.ticket_items', function() {
option.is_continuous_feed == value.is_continuous_feed &&
option.vendor_id == value.vendor_id;
});
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
var knownSizeToSaveAsPdf =
(!this.getDocumentInfoInternal().isModifiable ||
this.getDocumentInfoInternal().hasCssMediaStyles) &&
@@ -64,16 +61,16 @@ cr.define('print_preview.ticket_items', function() {
this.getSelectedDestInternal().id ==
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;
return !knownSizeToSaveAsPdf && !!this.capability;
- },
+ }
/** @override */
- isValueEqual: function(value) {
+ isValueEqual(value) {
var myValue = this.getValue();
return myValue.width_microns == value.width_microns &&
myValue.height_microns == value.height_microns &&
myValue.is_continuous_feed == value.is_continuous_feed &&
myValue.vendor_id == value.vendor_id;
- },
+ }
/** @return {Object} Media size capability of the selected destination. */
get capability() {
@@ -82,23 +79,23 @@ cr.define('print_preview.ticket_items', function() {
destination.capabilities.printer &&
destination.capabilities.printer.media_size) ||
null;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
var defaultOptions = this.capability.option.filter(function(option) {
return option.is_default;
});
return defaultOptions.length > 0 ? defaultOptions[0] : null;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return {};
- },
+ }
/** @override */
- updateValueInternal: function(value) {
+ updateValueInternal(value) {
var updateMargins = !this.isValueEqual(value);
print_preview.ticket_items.TicketItem.prototype.updateValueInternal.call(
this, value);
@@ -109,7 +106,7 @@ cr.define('print_preview.ticket_items', function() {
this.customMargins_.updateValue(null);
}
}
- };
+ }
// Export
return {MediaSize: MediaSize};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/page_range.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/page_range.js
index 5eb176f8bbe..23de286cfe4 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/page_range.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/page_range.js
@@ -5,79 +5,67 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Page range ticket item whose value is a {@code string} that represents
- * which pages in the document should be printed.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function PageRange(documentInfo) {
- print_preview.ticket_items.TicketItem.call(
- this, null /*appState*/, null /*field*/, null /*destinationStore*/,
- documentInfo);
- }
-
- /**
- * Impossibly large page number.
- * @type {number}
- * @const
- * @private
- */
- PageRange.MAX_PAGE_NUMBER_ = 1000000000;
-
- PageRange.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class PageRange extends print_preview.ticket_items.TicketItem {
+ /**
+ * Page range ticket item whose value is a {@code string} that represents
+ * which pages in the document should be printed.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ */
+ constructor(documentInfo) {
+ super(
+ null /*appState*/, null /*field*/, null /*destinationStore*/,
+ documentInfo);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
var result = pageRangeTextToPageRanges(
value, this.getDocumentInfoInternal().pageCount);
- return result instanceof Array;
- },
+ return Array.isArray(result);
+ }
/**
* @return {!print_preview.PageNumberSet} Set of page numbers defined by the
* page range string.
*/
- getPageNumberSet: function() {
+ getPageNumberSet() {
var pageNumberList = pageRangeTextToPageList(
this.getValueAsString_(), this.getDocumentInfoInternal().pageCount);
return new print_preview.PageNumberSet(pageNumberList);
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return true;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return '';
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return '';
- },
+ }
/**
* @return {string} The value of the ticket item as a string.
* @private
*/
- getValueAsString_: function() {
+ getValueAsString_() {
return /** @type {string} */ (this.getValue());
- },
+ }
/**
* @return {!Array<Object<{from: number, to: number}>>} A list of page
* ranges.
*/
- getPageRanges: function() {
+ getPageRanges() {
var pageRanges = pageRangeTextToPageRanges(this.getValueAsString_());
- return pageRanges instanceof Array ? pageRanges : [];
- },
+ return Array.isArray(pageRanges) ? pageRanges : [];
+ }
/**
* @return {!Array<Object<{from: number, to: number}>>} A list of page
@@ -85,29 +73,37 @@ cr.define('print_preview.ticket_items', function() {
* TODO(vitalybuka): this should be removed when native layer switched to
* page ranges.
*/
- getDocumentPageRanges: function() {
+ getDocumentPageRanges() {
var pageRanges = pageRangeTextToPageRanges(
this.getValueAsString_(), this.getDocumentInfoInternal().pageCount);
- return pageRanges instanceof Array ? pageRanges : [];
- },
+ return Array.isArray(pageRanges) ? pageRanges : [];
+ }
/**
* @return {!number} Number of pages reported by the document.
*/
- getDocumentNumPages: function() {
+ getDocumentNumPages() {
return this.getDocumentInfoInternal().pageCount;
- },
+ }
/**
* @return {!PageRangeStatus}
*/
- checkValidity: function() {
+ checkValidity() {
var pageRanges = pageRangeTextToPageRanges(
this.getValueAsString_(), this.getDocumentInfoInternal().pageCount);
- return pageRanges instanceof Array ? PageRangeStatus.NO_ERROR :
- pageRanges;
- },
- };
+ return Array.isArray(pageRanges) ? PageRangeStatus.NO_ERROR : pageRanges;
+ }
+ }
+
+ /**
+ * Impossibly large page number.
+ * @type {number}
+ * @const
+ * @private
+ */
+ PageRange.MAX_PAGE_NUMBER_ = 1000000000;
+
// Export
return {PageRange: PageRange};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/rasterize.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/rasterize.js
index 5827ba55025..15771711264 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/rasterize.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/rasterize.js
@@ -5,43 +5,39 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Rasterize ticket item whose value is a {@code boolean} that indicates
- * whether the PDF document should be rendered as images.
- * @constructor
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print, used to determine if document is a PDF.
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Rasterize(destinationStore, documentInfo) {
- print_preview.ticket_items.TicketItem.call(
- this, null /* appState */, null /* field */,
- null /* destinationStore */, documentInfo);
- }
-
- Rasterize.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class Rasterize extends print_preview.ticket_items.TicketItem {
+ /**
+ * Rasterize ticket item whose value is a {@code boolean} that indicates
+ * whether the PDF document should be rendered as images.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print, used to determine if document is a PDF.
+ */
+ constructor(destinationStore, documentInfo) {
+ super(
+ null /* appState */, null /* field */, null /* destinationStore */,
+ documentInfo);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return !this.getDocumentInfoInternal().isModifiable;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return false;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return this.getDefaultValueInternal();
}
- };
+ }
// Export
return {Rasterize: Rasterize};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/scaling.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/scaling.js
index e51252fce26..6ecc989d0e1 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/scaling.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/scaling.js
@@ -5,39 +5,36 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Scaling ticket item whose value is a {@code string} that indicates what the
- * scaling (in percent) of the document should be. The ticket item is backed
- * by a string since the user can textually input the scaling value.
- * @param {!print_preview.AppState} appState App state to persist item value.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @param {!print_preview.DestinationStore} destinationStore Used to determine
- * whether fit to page should be available.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function Scaling(appState, destinationStore, documentInfo) {
- print_preview.ticket_items.TicketItem.call(
- this, appState, print_preview.AppStateField.SCALING, destinationStore,
- documentInfo);
- }
-
- Scaling.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class Scaling extends print_preview.ticket_items.TicketItem {
+ /**
+ * Scaling ticket item whose value is a {@code string} that indicates what
+ * the scaling (in percent) of the document should be. The ticket item is
+ * backed by a string since the user can textually input the scaling value.
+ * @param {!print_preview.AppState} appState App state to persist item
+ * value.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ * @param {!print_preview.DestinationStore} destinationStore Used to
+ * determine whether scaling should be available.
+ */
+ constructor(appState, destinationStore, documentInfo) {
+ super(
+ appState, print_preview.AppStateField.SCALING, destinationStore,
+ documentInfo);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return value != '';
- },
+ }
/** @override */
- isValueEqual: function(value) {
+ isValueEqual(value) {
return this.getValue() == value;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
// This is not a function of the printer, but should be disabled if we are
// saving a PDF to a PDF.
var knownSizeToSaveAsPdf =
@@ -47,25 +44,25 @@ cr.define('print_preview.ticket_items', function() {
this.getSelectedDestInternal().id ==
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;
return !knownSizeToSaveAsPdf;
- },
+ }
/** @return {number} The scaling percentage indicated by the ticket item. */
- getValueAsNumber: function() {
+ getValueAsNumber() {
var value = this.getValue() == '' ? 0 : parseInt(this.getValue(), 10);
assert(!isNaN(value));
return value;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return '100';
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return '100';
- },
- };
+ }
+ }
// Export
return {Scaling: Scaling};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/selection_only.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/selection_only.js
index f6bfaf73c62..75c5554be5e 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/selection_only.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/selection_only.js
@@ -5,44 +5,40 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * Ticket item whose value is a {@code boolean} that represents whether to
- * print selection only.
- * @param {!print_preview.DocumentInfo} documentInfo Information about the
- * document to print.
- * @constructor
- * @extends {print_preview.ticket_items.TicketItem}
- */
- function SelectionOnly(documentInfo) {
- print_preview.ticket_items.TicketItem.call(
- this, null /*appState*/, null /*field*/, null /*destinationStore*/,
- documentInfo);
- }
-
- SelectionOnly.prototype = {
- __proto__: print_preview.ticket_items.TicketItem.prototype,
+ class SelectionOnly extends print_preview.ticket_items.TicketItem {
+ /**
+ * Ticket item whose value is a {@code boolean} that represents whether to
+ * print selection only.
+ * @param {!print_preview.DocumentInfo} documentInfo Information about the
+ * document to print.
+ */
+ constructor(documentInfo) {
+ super(
+ null /*appState*/, null /*field*/, null /*destinationStore*/,
+ documentInfo);
+ }
/** @override */
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
return true;
- },
+ }
/** @override */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return this.getDocumentInfoInternal().isModifiable &&
this.getDocumentInfoInternal().hasSelection;
- },
+ }
/** @override */
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
return false;
- },
+ }
/** @override */
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
return false;
}
- };
+ }
// Export
return {SelectionOnly: SelectionOnly};
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/ticket_item.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/ticket_item.js
index ce3da11b16e..9d543289ea7 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/ticket_item.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/ticket_item.js
@@ -9,103 +9,92 @@ print_preview.ValueType;
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * An object that represents a user modifiable item in a print ticket. Each
- * ticket item has a value which can be set by the user. Ticket items can also
- * be unavailable for modifying if the print destination doesn't support it or
- * if other ticket item constraints are not met.
- * @param {?print_preview.AppState} appState Application state model to update
- * when ticket items update.
- * @param {?print_preview.AppStateField} field Field of the app state to
- * update when ticket item is updated.
- * @param {?print_preview.DestinationStore} destinationStore Used listen for
- * changes in the currently selected destination's capabilities. Since
- * this is a common dependency of ticket items, it's handled in the base
- * class.
- * @param {?print_preview.DocumentInfo=} opt_documentInfo Used to listen for
- * changes in the document. Since this is a common dependency of ticket
- * items, it's handled in the base class.
- * @constructor
- * @extends {cr.EventTarget}
- */
- function TicketItem(appState, field, destinationStore, opt_documentInfo) {
- cr.EventTarget.call(this);
-
- /**
- * Application state model to update when ticket items update.
- * @type {print_preview.AppState}
- * @private
- */
- this.appState_ = appState || null;
-
- /**
- * Field of the app state to update when ticket item is updated.
- * @type {?print_preview.AppStateField}
- * @private
- */
- this.field_ = field || null;
-
- /**
- * Used listen for changes in the currently selected destination's
- * capabilities.
- * @type {print_preview.DestinationStore}
- * @private
- */
- this.destinationStore_ = destinationStore || null;
-
- /**
- * Used to listen for changes in the document.
- * @type {print_preview.DocumentInfo}
- * @private
- */
- this.documentInfo_ = opt_documentInfo || null;
-
- /**
- * Backing store of the print ticket item.
- * @type {Object}
- * @private
- */
- this.value_ = null;
-
- /**
- * Keeps track of event listeners for the ticket item.
- * @type {!EventTracker}
- * @private
- */
- this.tracker_ = new EventTracker();
-
- this.addEventHandlers_();
- }
-
- /**
- * Event types dispatched by this class.
- * @enum {string}
- */
- TicketItem.EventType = {
- CHANGE: 'print_preview.ticket_items.TicketItem.CHANGE'
- };
-
- TicketItem.prototype = {
- __proto__: cr.EventTarget.prototype,
+ class TicketItem extends cr.EventTarget {
+ /**
+ * An object that represents a user modifiable item in a print ticket. Each
+ * ticket item has a value which can be set by the user. Ticket items can
+ * also be unavailable for modifying if the print destination doesn't
+ * support it or if other ticket item constraints are not met.
+ * @param {?print_preview.AppState} appState Application state model to
+ * update
+ * when ticket items update.
+ * @param {?print_preview.AppStateField} field Field of the app state to
+ * update when ticket item is updated.
+ * @param {?print_preview.DestinationStore} destinationStore Used listen for
+ * changes in the currently selected destination's capabilities. Since
+ * this is a common dependency of ticket items, it's handled in the base
+ * class.
+ * @param {?print_preview.DocumentInfo=} opt_documentInfo Used to listen for
+ * changes in the document. Since this is a common dependency of ticket
+ * items, it's handled in the base class.
+ */
+ constructor(appState, field, destinationStore, opt_documentInfo) {
+ super();
+
+ /**
+ * Application state model to update when ticket items update.
+ * @type {print_preview.AppState}
+ * @private
+ */
+ this.appState_ = appState || null;
+
+ /**
+ * Field of the app state to update when ticket item is updated.
+ * @type {?print_preview.AppStateField}
+ * @private
+ */
+ this.field_ = field || null;
+
+ /**
+ * Used listen for changes in the currently selected destination's
+ * capabilities.
+ * @type {print_preview.DestinationStore}
+ * @private
+ */
+ this.destinationStore_ = destinationStore || null;
+
+ /**
+ * Used to listen for changes in the document.
+ * @type {print_preview.DocumentInfo}
+ * @private
+ */
+ this.documentInfo_ = opt_documentInfo || null;
+
+ /**
+ * Backing store of the print ticket item.
+ * @type {Object}
+ * @private
+ */
+ this.value_ = null;
+
+ /**
+ * Keeps track of event listeners for the ticket item.
+ * @type {!EventTracker}
+ * @private
+ */
+ this.tracker_ = new EventTracker();
+
+ this.addEventHandlers_();
+ }
/**
* Determines whether a given value is valid for the ticket item.
* @param {?} value The value to check for validity.
* @return {boolean} Whether the given value is valid for the ticket item.
*/
- wouldValueBeValid: function(value) {
+ wouldValueBeValid(value) {
throw Error('Abstract method not overridden');
- },
+ }
/**
* @return {boolean} Whether the print destination capability is available.
*/
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
throw Error('Abstract method not overridden');
- },
+ }
/** @return {print_preview.ValueType} The value of the ticket item. */
- getValue: function() {
+ getValue() {
if (!this.isCapabilityAvailable()) {
return this.getCapabilityNotAvailableValueInternal();
}
@@ -113,34 +102,34 @@ cr.define('print_preview.ticket_items', function() {
return this.getDefaultValueInternal();
}
return this.value_;
- },
+ }
/** @return {boolean} Whether the ticket item was modified by the user. */
- isUserEdited: function() {
+ isUserEdited() {
return this.value_ != null;
- },
+ }
/** @return {boolean} Whether the ticket item's value is valid. */
- isValid: function() {
+ isValid() {
if (!this.isUserEdited()) {
return true;
}
return this.wouldValueBeValid(this.value_);
- },
+ }
/**
* @param {?} value Value to compare to the value of this ticket item.
* @return {boolean} Whether the given value is equal to the value of the
* ticket item.
*/
- isValueEqual: function(value) {
+ isValueEqual(value) {
return this.getValue() == value;
- },
+ }
/**
* @param {?} value Value to set as the value of the ticket item.
*/
- updateValue: function(value) {
+ updateValue(value) {
// Use comparison with capabilities for event.
var sendUpdateEvent = !this.isValueEqual(value);
// Don't lose requested value if capability is not available.
@@ -152,77 +141,77 @@ cr.define('print_preview.ticket_items', function() {
}
if (sendUpdateEvent)
cr.dispatchSimpleEvent(this, TicketItem.EventType.CHANGE);
- },
+ }
/**
* @return {?} Default value of the ticket item if no value was set by
* the user.
* @protected
*/
- getDefaultValueInternal: function() {
+ getDefaultValueInternal() {
throw Error('Abstract method not overridden');
- },
+ }
/**
* @return {?} Default value of the ticket item if the capability is
* not available.
* @protected
*/
- getCapabilityNotAvailableValueInternal: function() {
+ getCapabilityNotAvailableValueInternal() {
throw Error('Abstract method not overridden');
- },
+ }
/**
* @return {!EventTracker} Event tracker to keep track of events from
* dependencies.
* @protected
*/
- getTrackerInternal: function() {
+ getTrackerInternal() {
return this.tracker_;
- },
+ }
/**
* @return {print_preview.Destination} Selected destination from the
* destination store, or {@code null} if no destination is selected.
* @protected
*/
- getSelectedDestInternal: function() {
+ getSelectedDestInternal() {
return this.destinationStore_ ?
this.destinationStore_.selectedDestination :
null;
- },
+ }
/**
* @return {print_preview.DocumentInfo} Document data model.
* @protected
*/
- getDocumentInfoInternal: function() {
+ getDocumentInfoInternal() {
return this.documentInfo_;
- },
+ }
/**
* Dispatches a CHANGE event.
* @protected
*/
- dispatchChangeEventInternal: function() {
+ dispatchChangeEventInternal() {
cr.dispatchSimpleEvent(
this, print_preview.ticket_items.TicketItem.EventType.CHANGE);
- },
+ }
/**
* Updates the value of the ticket item without dispatching any events or
* persisting the value.
* @protected
*/
- updateValueInternal: function(value) {
+ updateValueInternal(value) {
this.value_ = value;
- },
+ }
/**
* Adds event handlers for this class.
* @private
*/
- addEventHandlers_: function() {
+ addEventHandlers_() {
if (this.destinationStore_) {
this.tracker_.add(
this.destinationStore_,
@@ -235,9 +224,18 @@ cr.define('print_preview.ticket_items', function() {
this.documentInfo_, print_preview.DocumentInfo.EventType.CHANGE,
this.dispatchChangeEventInternal.bind(this));
}
- },
+ }
+ }
+
+ /**
+ * Event types dispatched by this class.
+ * @enum {string}
+ */
+ TicketItem.EventType = {
+ CHANGE: 'print_preview.ticket_items.TicketItem.CHANGE'
};
+
// Export
return {TicketItem: TicketItem};
});
diff --git a/chromium/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js b/chromium/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js
index 82a65d361f5..0bdcd9f9e5c 100644
--- a/chromium/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js
+++ b/chromium/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js
@@ -5,60 +5,56 @@
cr.define('print_preview.ticket_items', function() {
'use strict';
- /**
- * An object that represents a user modifiable item in a print ticket. Each
- * ticket item has a value which can be set by the user. Ticket items can also
- * be unavailable for modifying if the print destination doesn't support it or
- * if other ticket item constraints are not met.
- * @param {print_preview.AppState} appState Application state model to update
- * when ticket items update.
- * @param {print_preview.DestinationStore} destinationStore Used listen for
- * changes in the currently selected destination's capabilities. Since
- * this is a common dependency of ticket items, it's handled in the base
- * class.
- * @constructor
- * @extends {cr.EventTarget}
- */
- function VendorItems(appState, destinationStore) {
- cr.EventTarget.call(this);
-
+ class VendorItems extends cr.EventTarget {
/**
- * Application state model to update when ticket items update.
- * @private {print_preview.AppState}
+ * An object that represents a user modifiable item in a print ticket. Each
+ * ticket item has a value which can be set by the user. Ticket items can
+ * also be unavailable for modifying if the print destination doesn't
+ * support it or if other ticket item constraints are not met.
+ * @param {print_preview.AppState} appState Application state model to
+ * update when ticket items update.
+ * @param {print_preview.DestinationStore} destinationStore Used listen for
+ * changes in the currently selected destination's capabilities. Since
+ * this is a common dependency of ticket items, it's handled in the
+ * base class.
*/
- this.appState_ = appState || null;
+ constructor(appState, destinationStore) {
+ super();
- /**
- * Used listen for changes in the currently selected destination's
- * capabilities.
- * @private {print_preview.DestinationStore}
- */
- this.destinationStore_ = destinationStore || null;
+ /**
+ * Application state model to update when ticket items update.
+ * @private {print_preview.AppState}
+ */
+ this.appState_ = appState || null;
- /**
- * Vendor ticket items store, maps item id to the item value.
- * @private {!Object<string>}
- */
- this.items_ = {};
- }
+ /**
+ * Used listen for changes in the currently selected destination's
+ * capabilities.
+ * @private {print_preview.DestinationStore}
+ */
+ this.destinationStore_ = destinationStore || null;
- VendorItems.prototype = {
- __proto__: cr.EventTarget.prototype,
+ /**
+ * Vendor ticket items store, maps item id to the item value.
+ * @private {!Object<string>}
+ */
+ this.items_ = {};
+ }
/** @return {boolean} Whether vendor capabilities are available. */
- isCapabilityAvailable: function() {
+ isCapabilityAvailable() {
return !!this.capability;
- },
+ }
/** @return {boolean} Whether the ticket item was modified by the user. */
- isUserEdited: function() {
+ isUserEdited() {
// If there's at least one ticket item stored in values, it was edited.
for (var key in this.items_) {
if (this.items_.hasOwnProperty(key))
return true;
}
return false;
- },
+ }
/** @return {Object} Vendor capabilities of the selected destination. */
get capability() {
@@ -73,7 +69,7 @@ cr.define('print_preview.ticket_items', function() {
return (destination.capabilities && destination.capabilities.printer &&
destination.capabilities.printer.vendor_capability) ||
null;
- },
+ }
/**
* Vendor ticket items store, maps item id to the item value.
@@ -81,13 +77,13 @@ cr.define('print_preview.ticket_items', function() {
*/
get ticketItems() {
return this.items_;
- },
+ }
/**
* @param {!Object<string>} values Values to set as the values of vendor
* ticket items. Maps vendor item id to the value.
*/
- updateValue: function(values) {
+ updateValue(values) {
this.items_ = {};
if (typeof values == 'object') {
for (var key in values) {
@@ -103,7 +99,7 @@ cr.define('print_preview.ticket_items', function() {
print_preview.AppStateField.VENDOR_OPTIONS, this.items_);
}
}
- };
+ }
// Export
return {VendorItems: VendorItems};
diff --git a/chromium/chrome/browser/resources/print_preview/images/printer.png b/chromium/chrome/browser/resources/print_preview/images/1x/printer.png
index a0a85bbc236..a0a85bbc236 100644
--- a/chromium/chrome/browser/resources/print_preview/images/printer.png
+++ b/chromium/chrome/browser/resources/print_preview/images/1x/printer.png
Binary files differ
diff --git a/chromium/chrome/browser/resources/print_preview/images/printer_shared.png b/chromium/chrome/browser/resources/print_preview/images/1x/printer_shared.png
index 026ed450f86..026ed450f86 100644
--- a/chromium/chrome/browser/resources/print_preview/images/printer_shared.png
+++ b/chromium/chrome/browser/resources/print_preview/images/1x/printer_shared.png
Binary files differ
diff --git a/chromium/chrome/browser/resources/print_preview/images/2x/printer.png b/chromium/chrome/browser/resources/print_preview/images/2x/printer.png
new file mode 100644
index 00000000000..b704e02f841
--- /dev/null
+++ b/chromium/chrome/browser/resources/print_preview/images/2x/printer.png
Binary files differ
diff --git a/chromium/chrome/browser/resources/print_preview/images/2x/printer_shared.png b/chromium/chrome/browser/resources/print_preview/images/2x/printer_shared.png
new file mode 100644
index 00000000000..bbddfd04d2c
--- /dev/null
+++ b/chromium/chrome/browser/resources/print_preview/images/2x/printer_shared.png
Binary files differ
diff --git a/chromium/chrome/browser/resources/print_preview/native_layer.js b/chromium/chrome/browser/resources/print_preview/native_layer.js
index 05072dc29e0..3aaa9947da1 100644
--- a/chromium/chrome/browser/resources/print_preview/native_layer.js
+++ b/chromium/chrome/browser/resources/print_preview/native_layer.js
@@ -28,14 +28,22 @@ print_preview.LocalDestinationInfo;
/**
* @typedef {{
- * printerId: string,
+ * isInKioskAutoPrintMode: boolean,
+ * isInAppKioskMode: boolean,
+ * thousandsDelimeter: string,
+ * decimalDelimeter: string,
+ * unitType: !print_preview.MeasurementSystemUnitType,
+ * previewModifiable: boolean,
+ * documentTitle: string,
+ * documentHasSelection: boolean,
+ * shouldPrintSelectionOnly: boolean,
* printerName: string,
- * printerDescription: string,
- * cupsEnterprisePrinter: (boolean | undefined),
- * capabilities: !print_preview.Cdd,
+ * serializedAppStateStr: ?string,
+ * serializedDefaultDestinationSelectionRulesStr: ?string,
* }}
+ * @see corresponding field name definitions in print_preview_handler.cc
*/
-print_preview.PrinterCapabilitiesResponse;
+print_preview.NativeInitialSettings;
/**
* @typedef {{
@@ -51,11 +59,13 @@ print_preview.PrivetPrinterDescription;
/**
* @typedef {{
- * printer: !print_preview.PrivetPrinterDescription,
+ * printer:(print_preview.PrivetPrinterDescription |
+ * print_preview.LocalDestinationInfo |
+ * undefined),
* capabilities: !print_preview.Cdd,
* }}
*/
-print_preview.PrivetPrinterCapabilitiesResponse;
+print_preview.CapabilitiesResponse;
/**
* @typedef {{
@@ -85,6 +95,8 @@ print_preview.ProvisionalDestinationInfo;
print_preview.PrinterType = {
PRIVET_PRINTER: 0,
EXTENSION_PRINTER: 1,
+ PDF_PRINTER: 2,
+ LOCAL_PRINTER: 3,
};
cr.define('print_preview', function() {
@@ -126,104 +138,35 @@ cr.define('print_preview', function() {
* @return {!Promise<!print_preview.NativeInitialSettings>}
*/
getInitialSettings() {
- return cr.sendWithPromise('getInitialSettings')
- .then(
- /**
- * @param {!Object} initialSettings Object containing the raw
- * Print Preview settings.
- */
- function(initialSettings) {
- var numberFormatSymbols =
- print_preview.MeasurementSystem.parseNumberFormat(
- initialSettings['numberFormat']);
- var unitType = print_preview.MeasurementSystemUnitType.IMPERIAL;
- if (initialSettings['measurementSystem'] != null) {
- unitType = initialSettings['measurementSystem'];
- }
- return new print_preview.NativeInitialSettings(
- initialSettings['printAutomaticallyInKioskMode'] || false,
- initialSettings['appKioskMode'] || false,
- numberFormatSymbols[0] || ',',
- numberFormatSymbols[1] || '.', unitType,
- initialSettings['previewModifiable'] || false,
- initialSettings['initiatorTitle'] || '',
- initialSettings['documentHasSelection'] || false,
- initialSettings['shouldPrintSelectionOnly'] || false,
- initialSettings['printerName'] || null,
- initialSettings['appState'] || null,
- initialSettings['defaultDestinationSelectionRules'] ||
- null);
- });
- }
-
- /**
- * Requests the system's local print destinations. The promise will be
- * resolved with a list of the local destinations.
- * @return {!Promise<!Array<print_preview.LocalDestinationInfo>>}
- */
- getPrinters() {
- return cr.sendWithPromise('getPrinters');
+ return cr.sendWithPromise('getInitialSettings');
}
/**
- * Requests the network's privet print destinations. After this is called,
- * a number of privet-printer-changed events may be fired.
- * @return {!Promise} Resolves when privet printer search is completed.
- * Rejected if privet printers are not enabled.
+ * Requests the system's print destinations. The promise will be resolved
+ * when all destinations of that type have been retrieved. One or more
+ * 'printers-added' events may be fired in response before resolution.
+ * @param {!print_preview.PrinterType} type The type of destinations to
+ * request.
+ * @return {!Promise}
*/
- getPrivetPrinters() {
- return cr.sendWithPromise(
- 'getExtensionOrPrivetPrinters',
- print_preview.PrinterType.PRIVET_PRINTER);
- }
-
- /**
- * Request a list of extension printers. Printers are reported as they are
- * found by a series of 'extension-printers-added' events.
- * @return {!Promise} Will be resolved when all extension managed printers
- * have been sent.
- */
- getExtensionPrinters() {
- return cr.sendWithPromise(
- 'getExtensionOrPrivetPrinters',
- print_preview.PrinterType.EXTENSION_PRINTER);
+ getPrinters(type) {
+ return cr.sendWithPromise('getPrinters', type);
}
/**
* Requests the destination's printing capabilities. Returns a promise that
* will be resolved with the capabilities if they are obtained successfully.
* @param {string} destinationId ID of the destination.
- * @return {!Promise<!print_preview.PrinterCapabilitiesResponse>}
- */
- getPrinterCapabilities(destinationId) {
- return cr.sendWithPromise('getPrinterCapabilities', destinationId);
- }
-
- /**
- * Requests the privet destination's printing capabilities. Returns a
- * promise that will be resolved with capabilities and printer information
- * if capabilities are obtained successfully.
- * @param {string} destinationId The ID of the destination
- * @return {!Promise<!print_preview.PrivetPrinterCapabilitiesResponse>}
- */
- getPrivetPrinterCapabilities(destinationId) {
- return cr.sendWithPromise(
- 'getExtensionOrPrivetPrinterCapabilities', destinationId,
- print_preview.PrinterType.PRIVET_PRINTER);
- }
-
- /**
- * Requests the extension destination's printing capabilities. Returns a
- * promise that will be resolved with the capabilities if capabilities are
- * obtained successfully.
- * @param {string} destinationId The ID of the destination whose
- * capabilities are requested.
- * @return {!Promise<!print_preview.Cdd>}
+ * @param {!print_preview.PrinterType} type The destination's printer type.
+ * @return {!Promise<!print_preview.CapabilitiesResponse>}
*/
- getExtensionPrinterCapabilities(destinationId) {
+ getPrinterCapabilities(destinationId, type) {
return cr.sendWithPromise(
- 'getExtensionOrPrivetPrinterCapabilities', destinationId,
- print_preview.PrinterType.EXTENSION_PRINTER);
+ 'getPrinterCapabilities', destinationId,
+ destinationId ==
+ print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ?
+ print_preview.PrinterType.PDF_PRINTER :
+ type);
}
/**
@@ -571,185 +514,8 @@ cr.define('print_preview', function() {
*/
NativeLayer.SERIALIZED_STATE_VERSION_ = 1;
- /**
- * Initial settings retrieved from the native layer.
- */
- class NativeInitialSettings {
- /**
- * @param {boolean} isInKioskAutoPrintMode Whether the print preview should
- * be in auto-print mode.
- * @param {boolean} isInAppKioskMode Whether the print preview is in App
- * Kiosk mode.
- * @param {string} thousandsDelimeter Character delimeter of thousands
- * digits.
- * @param {string} decimalDelimeter Character delimeter of the decimal
- * point.
- * @param {!print_preview.MeasurementSystemUnitType} unitType Unit type of
- * local machine's measurement system.
- * @param {boolean} isDocumentModifiable Whether the document to print is
- * modifiable.
- * @param {string} documentTitle Title of the document.
- * @param {boolean} documentHasSelection Whether the document has selected
- * content.
- * @param {boolean} selectionOnly Whether only selected content should be
- * printed.
- * @param {?string} systemDefaultDestinationId ID of the system default
- * destination.
- * @param {?string} serializedAppStateStr Serialized app state.
- * @param {?string} serializedDefaultDestinationSelectionRulesStr Serialized
- * default destination selection rules.
- */
- constructor(
- isInKioskAutoPrintMode, isInAppKioskMode, thousandsDelimeter,
- decimalDelimeter, unitType, isDocumentModifiable, documentTitle,
- documentHasSelection, selectionOnly, systemDefaultDestinationId,
- serializedAppStateStr, serializedDefaultDestinationSelectionRulesStr) {
- /**
- * Whether the print preview should be in auto-print mode.
- * @private {boolean}
- */
- this.isInKioskAutoPrintMode_ = isInKioskAutoPrintMode;
-
- /**
- * Whether the print preview should switch to App Kiosk mode.
- * @private {boolean}
- */
- this.isInAppKioskMode_ = isInAppKioskMode;
-
- /**
- * Character delimeter of thousands digits.
- * @private {string}
- */
- this.thousandsDelimeter_ = thousandsDelimeter;
-
- /**
- * Character delimeter of the decimal point.
- * @private {string}
- */
- this.decimalDelimeter_ = decimalDelimeter;
-
- /**
- * Unit type of local machine's measurement system.
- * @private {print_preview.MeasurementSystemUnitType}
- */
- this.unitType_ = unitType;
-
- /**
- * Whether the document to print is modifiable.
- * @private {boolean}
- */
- this.isDocumentModifiable_ = isDocumentModifiable;
-
- /**
- * Title of the document.
- * @private {string}
- */
- this.documentTitle_ = documentTitle;
-
- /**
- * Whether the document has selection.
- * @private {boolean}
- */
- this.documentHasSelection_ = documentHasSelection;
-
- /**
- * Whether selection only should be printed.
- * @private {boolean}
- */
- this.selectionOnly_ = selectionOnly;
-
- /**
- * ID of the system default destination.
- * @private {?string}
- */
- this.systemDefaultDestinationId_ = systemDefaultDestinationId;
-
- /**
- * Serialized app state.
- * @private {?string}
- */
- this.serializedAppStateStr_ = serializedAppStateStr;
-
- /**
- * Serialized default destination selection rules.
- * @private {?string}
- */
- this.serializedDefaultDestinationSelectionRulesStr_ =
- serializedDefaultDestinationSelectionRulesStr;
- }
-
- /**
- * @return {boolean} Whether the print preview should be in auto-print mode.
- */
- get isInKioskAutoPrintMode() {
- return this.isInKioskAutoPrintMode_;
- }
-
- /**
- * @return {boolean} Whether the print preview should switch to App Kiosk
- * mode.
- */
- get isInAppKioskMode() {
- return this.isInAppKioskMode_;
- }
-
- /** @return {string} Character delimeter of thousands digits. */
- get thousandsDelimeter() {
- return this.thousandsDelimeter_;
- }
-
- /** @return {string} Character delimeter of the decimal point. */
- get decimalDelimeter() {
- return this.decimalDelimeter_;
- }
-
- /**
- * @return {!print_preview.MeasurementSystemUnitType} Unit type of local
- * machine's measurement system.
- */
- get unitType() {
- return this.unitType_;
- }
-
- /** @return {boolean} Whether the document to print is modifiable. */
- get isDocumentModifiable() {
- return this.isDocumentModifiable_;
- }
-
- /** @return {string} Document title. */
- get documentTitle() {
- return this.documentTitle_;
- }
-
- /** @return {boolean} Whether the document has selection. */
- get documentHasSelection() {
- return this.documentHasSelection_;
- }
-
- /** @return {boolean} Whether selection only should be printed. */
- get selectionOnly() {
- return this.selectionOnly_;
- }
-
- /** @return {?string} ID of the system default destination. */
- get systemDefaultDestinationId() {
- return this.systemDefaultDestinationId_;
- }
-
- /** @return {?string} Serialized app state. */
- get serializedAppStateStr() {
- return this.serializedAppStateStr_;
- }
-
- /** @return {?string} Serialized default destination selection rules. */
- get serializedDefaultDestinationSelectionRulesStr() {
- return this.serializedDefaultDestinationSelectionRulesStr_;
- }
- }
-
// Export
return {
- NativeInitialSettings: NativeInitialSettings,
NativeLayer: NativeLayer
};
});
diff --git a/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js b/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js
index 3ef1805c88b..98e8f1c9add 100644
--- a/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js
+++ b/chromium/chrome/browser/resources/print_preview/previewarea/preview_area.js
@@ -318,8 +318,8 @@ cr.define('print_preview', function() {
this.onOpenSystemDialogButtonClick_.bind(this));
var TicketStoreEvent = print_preview.PrintTicketStore.EventType;
- [TicketStoreEvent.INITIALIZE, TicketStoreEvent.TICKET_CHANGE,
- TicketStoreEvent.CAPABILITIES_CHANGE, TicketStoreEvent.DOCUMENT_CHANGE]
+ [TicketStoreEvent.INITIALIZE, TicketStoreEvent.CAPABILITIES_CHANGE,
+ TicketStoreEvent.DOCUMENT_CHANGE]
.forEach(eventType => {
this.tracker.add(
this.printTicketStore_, eventType,
diff --git a/chromium/chrome/browser/resources/print_preview/print_header.js b/chromium/chrome/browser/resources/print_preview/print_header.js
index 810e286d16f..b8f12871fe8 100644
--- a/chromium/chrome/browser/resources/print_preview/print_header.js
+++ b/chromium/chrome/browser/resources/print_preview/print_header.js
@@ -108,35 +108,19 @@ cr.define('print_preview', function() {
this.tracker.add(
this.printTicketStore_,
print_preview.PrintTicketStore.EventType.INITIALIZE,
- this.onTicketChange_.bind(this));
+ this.onTicketChange.bind(this));
this.tracker.add(
this.printTicketStore_,
print_preview.PrintTicketStore.EventType.DOCUMENT_CHANGE,
- this.onTicketChange_.bind(this));
- this.tracker.add(
- this.printTicketStore_,
- print_preview.PrintTicketStore.EventType.TICKET_CHANGE,
- this.onTicketChange_.bind(this));
+ this.onTicketChange.bind(this));
this.tracker.add(
this.destinationStore_,
print_preview.DestinationStore.EventType.DESTINATION_SELECT,
this.onDestinationSelect_.bind(this));
this.tracker.add(
- this.printTicketStore_.copies,
- print_preview.ticket_items.TicketItem.EventType.CHANGE,
- this.onTicketChange_.bind(this));
- this.tracker.add(
this.printTicketStore_.duplex,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
- this.onTicketChange_.bind(this));
- this.tracker.add(
- this.printTicketStore_.pageRange,
- print_preview.ticket_items.TicketItem.EventType.CHANGE,
- this.onTicketChange_.bind(this));
- this.tracker.add(
- this.printTicketStore_.scaling,
- print_preview.ticket_items.TicketItem.EventType.CHANGE,
- this.updatePrintButtonEnabledState_.bind(this));
+ this.onTicketChange.bind(this));
},
/**
@@ -266,9 +250,8 @@ cr.define('print_preview', function() {
/**
* Called when the print ticket has changed. Disables the print button if
* any of the settings are invalid.
- * @private
*/
- onTicketChange_: function() {
+ onTicketChange: function() {
this.updatePrintButtonEnabledState_();
this.updateSummary_();
if (document.activeElement == null ||
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.css b/chromium/chrome/browser/resources/print_preview/print_preview.css
index bb69ab6e9ed..d9b3f8f2bdd 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.css
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.css
@@ -62,17 +62,6 @@ header {
width: 99%;
}
-.right-column .checkbox,
-.right-column .radio {
- margin: 0;
-}
-
-.right-column .checkbox label,
-.right-column .radio label {
- padding-bottom: 5px;
- padding-top: 10px;
-}
-
.right-column .radio input[type='radio'],
.right-column label input[type='checkbox'] {
--min-size: 13.19px;
@@ -105,7 +94,7 @@ header {
}
.two-column.visible .left-column.multirow {
- padding-top: 16px;
+ padding-top: 13px;
vertical-align: top;
}
@@ -137,12 +126,6 @@ h1 {
margin: 8px 20px;
}
-#print-preview .navbar-link.disabled {
- color: rgba(0, 0, 0, .5);
- cursor: default;
- pointer-events: none;
-}
-
button.loading {
cursor: progress;
}
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.html b/chromium/chrome/browser/resources/print_preview/print_preview.html
index 3373d046f4c..c59e8e9b0d6 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.html
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.html
@@ -15,14 +15,12 @@
<link rel="stylesheet" href="common/search_bubble.css">
<link rel="stylesheet" href="settings/destination_settings.css">
<link rel="stylesheet" href="settings/color_settings.css">
- <link rel="stylesheet" href="settings/copies_settings.css">
<link rel="stylesheet" href="settings/settings_box.css">
<link rel="stylesheet" href="settings/page_settings.css">
<link rel="stylesheet" href="settings/margin_settings.css">
<link rel="stylesheet" href="settings/media_size_settings.css">
<link rel="stylesheet" href="settings/layout_settings.css">
<link rel="stylesheet" href="settings/dpi_settings.css">
- <link rel="stylesheet" href="settings/scaling_settings.css">
<link rel="stylesheet" href="settings/advanced_options_settings.css">
<link rel="stylesheet" href="settings/advanced_settings/advanced_settings.css">
<link rel="stylesheet" href="settings/advanced_settings/advanced_settings_item.css">
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.js b/chromium/chrome/browser/resources/print_preview/print_preview.js
index 00a9b0e427a..bee9f809d16 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.js
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.js
@@ -390,6 +390,10 @@ cr.define('print_preview', function() {
this.printIfReady_.bind(this));
this.tracker.add(
this.destinationStore_,
+ print_preview.DestinationStore.EventType.SELECTED_DESTINATION_INVALID,
+ this.onSelectedDestinationInvalid_.bind(this));
+ this.tracker.add(
+ this.destinationStore_,
print_preview.DestinationStore.EventType.DESTINATION_SELECT,
this.onDestinationSelect_.bind(this));
@@ -435,6 +439,15 @@ cr.define('print_preview', function() {
this.advancedOptionsSettings_,
print_preview.AdvancedOptionsSettings.EventType.BUTTON_ACTIVATED,
this.onAdvancedOptionsButtonActivated_.bind(this));
+
+ /* Ticket items that may be invalid. */
+ [this.printTicketStore_.copies, this.printTicketStore_.pageRange,
+ this.printTicketStore_.scaling,
+ ].forEach((item) => {
+ this.tracker.add(
+ item, print_preview.ticket_items.TicketItem.EventType.CHANGE,
+ this.onTicketChange_.bind(this));
+ });
},
/** @override */
@@ -465,9 +478,9 @@ cr.define('print_preview', function() {
*/
setIsEnabled_: function(isEnabled) {
if ($('system-dialog-link'))
- $('system-dialog-link').classList.toggle('disabled', !isEnabled);
+ $('system-dialog-link').disabled = !isEnabled;
if ($('open-pdf-in-preview-link'))
- $('open-pdf-in-preview-link').classList.toggle('disabled', !isEnabled);
+ $('open-pdf-in-preview-link').disabled = !isEnabled;
this.printHeader_.isEnabled = isEnabled;
this.destinationSettings_.isEnabled = isEnabled;
this.pageSettings_.isEnabled = isEnabled;
@@ -584,7 +597,7 @@ cr.define('print_preview', function() {
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF);
// Save as PDF resolves when file selection is completed or cancelled.
whenPrintDone.then(
- this.onFileSelectionComplete_.bind(this),
+ this.close_.bind(this, false),
this.onFileSelectionCancel_.bind(this));
}
@@ -645,13 +658,13 @@ cr.define('print_preview', function() {
// The following components must be initialized in this order.
this.appState_.init(settings.serializedAppStateStr);
this.documentInfo_.init(
- settings.isDocumentModifiable, settings.documentTitle,
+ settings.previewModifiable, settings.documentTitle,
settings.documentHasSelection);
this.printTicketStore_.init(
settings.thousandsDelimeter, settings.decimalDelimeter,
- settings.unitType, settings.selectionOnly);
+ settings.unitType, settings.shouldPrintSelectionOnly);
this.destinationStore_.init(
- settings.isInAppKioskMode, settings.systemDefaultDestinationId,
+ settings.isInAppKioskMode, settings.printerName,
settings.serializedDefaultDestinationSelectionRulesStr);
this.appState_.setInitialized();
@@ -735,20 +748,6 @@ cr.define('print_preview', function() {
},
/**
- * Called from the native layer when save-to-pdf file selection is complete.
- * @private
- */
- onFileSelectionComplete_: function() {
- assert(
- this.uiState_ == PrintPreviewUiState_.FILE_SELECTION,
- 'File selection completed when not in file-selection state: ' +
- this.uiState_);
- this.previewArea_.showCustomMessage(
- loadTimeData.getString('printingToPDFInProgress'));
- this.uiState_ = PrintPreviewUiState_.PRINTING;
- },
-
- /**
* Called after successfully submitting a job to Google Cloud Print.
* @param {!Event} event Contains the ID of the submitted print job.
* @private
@@ -927,6 +926,17 @@ cr.define('print_preview', function() {
},
/**
+ * Called when the destination store fails to fetch capabilities for the
+ * selected printer.
+ * @private
+ */
+ onSelectedDestinationInvalid_: function() {
+ this.previewArea_.showCustomMessage(
+ loadTimeData.getString('invalidPrinterSettings'));
+ this.onSettingsInvalid_();
+ },
+
+ /**
* Called when native layer receives invalid settings for a print request.
* @private
*/
@@ -937,6 +947,21 @@ cr.define('print_preview', function() {
},
/**
+ * Called when a ticket item that can be invalid is updated. Updates the
+ * enabled state of the system dialog link on Windows and the open pdf in
+ * preview link on Mac.
+ * @private
+ */
+ onTicketChange_: function() {
+ this.printHeader_.onTicketChange();
+ var disable = !this.printHeader_.isPrintButtonEnabled;
+ if (cr.isWindows && $('system-dialog-link'))
+ $('system-dialog-link').disabled = disable;
+ if ($('open-pdf-in-preview-link'))
+ $('open-pdf-in-preview-link').disabled = disable;
+ },
+
+ /**
* Called when the destination settings' change button is activated.
* Displays the destination search component.
* @private
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview_utils.js b/chromium/chrome/browser/resources/print_preview/print_preview_utils.js
index 7836ad7956d..bfd199c3801 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview_utils.js
+++ b/chromium/chrome/browser/resources/print_preview/print_preview_utils.js
@@ -152,7 +152,7 @@ function pageRangeTextToPageRanges(pageRangeText, opt_totalPageCount) {
function pageRangeTextToPageList(pageRangeText, totalPageCount) {
var pageRanges = pageRangeTextToPageRanges(pageRangeText, totalPageCount);
var pageList = [];
- if (pageRanges instanceof Array) {
+ if (Array.isArray(pageRanges)) {
for (var i = 0; i < pageRanges.length; ++i) {
for (var j = pageRanges[i].from;
j <= Math.min(pageRanges[i].to, totalPageCount); ++j) {
diff --git a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js
index d925eef5bda..b52b4938cbd 100644
--- a/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js
+++ b/chromium/chrome/browser/resources/print_preview/search/destination_list_item.js
@@ -140,6 +140,7 @@ cr.define('print_preview', function() {
updateUi_: function() {
var iconImg = this.getChildElement('.destination-list-item-icon');
iconImg.src = this.destination_.iconUrl;
+ iconImg.srcset = this.destination_.srcSet;
var nameEl = this.getChildElement('.destination-list-item-name');
var textContent = this.destination_.displayName;
diff --git a/chromium/chrome/browser/resources/print_preview/settings/copies_settings.css b/chromium/chrome/browser/resources/print_preview/settings/copies_settings.css
deleted file mode 100644
index e2e1b6f9848..00000000000
--- a/chromium/chrome/browser/resources/print_preview/settings/copies_settings.css
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-#copies-settings .collate-container {
- -webkit-padding-start: 16px;
- display: inline-block;
-}
-
-#copies-settings .collate-container label {
- padding: 0;
-}
diff --git a/chromium/chrome/browser/resources/print_preview/settings/destination_settings.js b/chromium/chrome/browser/resources/print_preview/settings/destination_settings.js
index f9941182b45..54d1994e9c8 100644
--- a/chromium/chrome/browser/resources/print_preview/settings/destination_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/settings/destination_settings.js
@@ -131,6 +131,7 @@ cr.define('print_preview', function() {
var iconEl = this.getElement().getElementsByClassName(
print_preview.DestinationSettingsClasses_.ICON)[0];
iconEl.src = destination.iconUrl;
+ iconEl.srcset = destination.srcSet;
var hint = destination.hint;
var locationEl = this.getElement().getElementsByClassName(
diff --git a/chromium/chrome/browser/resources/print_preview/settings/page_settings.js b/chromium/chrome/browser/resources/print_preview/settings/page_settings.js
index fe589e1ad3f..edbd64c3e23 100644
--- a/chromium/chrome/browser/resources/print_preview/settings/page_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/settings/page_settings.js
@@ -32,28 +32,35 @@ cr.define('print_preview', function() {
/**
* Custom page range input.
- * @type {HTMLInputElement}
+ * @type {?HTMLInputElement}
* @private
*/
this.customInput_ = null;
/**
* Custom page range radio button.
- * @type {HTMLInputElement}
+ * @type {?HTMLInputElement}
* @private
*/
this.customRadio_ = null;
/**
+ * Custom page range label.
+ * @type {?HTMLElement}
+ * @private
+ */
+ this.customLabel_ = null;
+
+ /**
* All page rage radio button.
- * @type {HTMLInputElement}
+ * @type {?HTMLInputElement}
* @private
*/
this.allRadio_ = null;
/**
* Container of a hint to show when the custom page range is invalid.
- * @type {HTMLElement}
+ * @type {?HTMLElement}
* @private
*/
this.customHintEl_ = null;
@@ -68,6 +75,7 @@ cr.define('print_preview', function() {
ALL_RADIO: 'page-settings-all-radio',
CUSTOM_HINT: 'page-settings-custom-hint',
CUSTOM_INPUT: 'page-settings-custom-input',
+ CUSTOM_LABEL: 'page-settings-print-pages-div',
CUSTOM_RADIO: 'page-settings-custom-radio'
};
@@ -106,7 +114,7 @@ cr.define('print_preview', function() {
assert(this.allRadio_), 'click', this.onAllRadioClick_.bind(this));
this.tracker.add(
assert(this.customRadio_), 'click',
- this.onCustomRadioClick_.bind(this));
+ this.focusCustomInput_.bind(this));
this.tracker.add(customInput, 'blur', this.onCustomInputBlur_.bind(this));
this.tracker.add(
customInput, 'focus', this.onCustomInputFocus_.bind(this));
@@ -115,6 +123,9 @@ cr.define('print_preview', function() {
this.tracker.add(
customInput, 'input', this.onCustomInputChange_.bind(this));
this.tracker.add(
+ assert(this.customLabel_), 'focus',
+ this.focusCustomInput_.bind(this));
+ this.tracker.add(
this.pageRangeTicketItem_,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onPageRangeTicketItemChange_.bind(this));
@@ -139,6 +150,8 @@ cr.define('print_preview', function() {
PageSettings.Classes_.CUSTOM_RADIO)[0];
this.customHintEl_ = this.getElement().getElementsByClassName(
PageSettings.Classes_.CUSTOM_HINT)[0];
+ this.customLabel_ = this.getElement().getElementsByClassName(
+ PageSettings.Classes_.CUSTOM_LABEL)[0];
},
/**
@@ -179,10 +192,11 @@ cr.define('print_preview', function() {
},
/**
- * Called when the custom radio button is clicked. Updates the print ticket.
+ * Focuses the custom input. Called when the custom radio button or custom
+ * input label is clicked.
* @private
*/
- onCustomRadioClick_: function() {
+ focusCustomInput_: function() {
this.customInput_.focus();
},
diff --git a/chromium/chrome/browser/resources/print_preview/settings/scaling_settings.css b/chromium/chrome/browser/resources/print_preview/settings/scaling_settings.css
deleted file mode 100644
index e39db53edd7..00000000000
--- a/chromium/chrome/browser/resources/print_preview/settings/scaling_settings.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/* Copyright 2017 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-#scaling-settings .settings-box {
- padding-top: 5px;
-}
diff --git a/chromium/chrome/browser/resources/print_preview/settings/settings_box.css b/chromium/chrome/browser/resources/print_preview/settings/settings_box.css
index cf48b061b00..b95a669f277 100644
--- a/chromium/chrome/browser/resources/print_preview/settings/settings_box.css
+++ b/chromium/chrome/browser/resources/print_preview/settings/settings_box.css
@@ -6,3 +6,14 @@
background: rgb(255, 240, 240);
color: rgb(140, 20, 20);
}
+
+.settings-box input[type='number'] {
+ -webkit-margin-end: 16px;
+ margin-bottom: 2.5px;
+ margin-top: 2.5px;
+}
+
+.settings-box {
+ align-items: center;
+ display: inline-flex;
+}
diff --git a/chromium/chrome/browser/resources/print_preview/settings/settings_section_select.js b/chromium/chrome/browser/resources/print_preview/settings/settings_section_select.js
index 62ec25c45a3..ab8b1d59fc0 100644
--- a/chromium/chrome/browser/resources/print_preview/settings/settings_section_select.js
+++ b/chromium/chrome/browser/resources/print_preview/settings/settings_section_select.js
@@ -8,15 +8,21 @@ cr.define('print_preview', function() {
/**
* Base class for the printer option element visualizing the generic selection
* based option.
- * @param {!print_preview.ticket_items.TicketItem} ticketItem Ticket item
- * visualized by this component.
+ * @param {(!print_preview.ticket_items.Dpi |
+ * !print_preview.ticket_items.MediaSize)} ticketItem
+ * Ticket item visualized by this component. Must have a defined
+ * capability() getter.
* @constructor
* @extends {print_preview.SettingsSection}
*/
function SettingsSectionSelect(ticketItem) {
print_preview.SettingsSection.call(this);
- /** @private {!print_preview.ticket_items.TicketItem} */
+ /**
+ * {(!print_preview.ticket_items.Dpi |
+ * !print_preview.ticket_items.MediaSize)}
+ * @private
+ */
this.ticketItem_ = ticketItem;
}
diff --git a/chromium/chrome/browser/resources/profiler/OWNERS b/chromium/chrome/browser/resources/profiler/OWNERS
deleted file mode 100644
index 601500194e3..00000000000
--- a/chromium/chrome/browser/resources/profiler/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-eroman@chromium.org
-jar@chromium.org
-
-# COMPONENT: Internals>Metrics
diff --git a/chromium/chrome/browser/resources/profiler/profiler.html b/chromium/chrome/browser/resources/profiler/profiler.html
deleted file mode 100644
index cc5638f36cc..00000000000
--- a/chromium/chrome/browser/resources/profiler/profiler.html
+++ /dev/null
@@ -1,164 +0,0 @@
-<!doctype html>
-<html>
-<head>
-<meta charset="utf-8">
-<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
-<script src="chrome://resources/js/load_time_data.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<script src="chrome://profiler/strings.js"></script>
-<script src="chrome://profiler/profiler.js"></script>
-
-<style>
-
-body {
- font-size: 80%;
-}
-
-/*
- * The following styles are for a TABLE that uses a thin collapsed border, and
- * has a blue heading. When you hover over rows, they turn yellow.
- */
-table.results-table {
- border-collapse: collapse;
-}
-
-table.results-table,
-.results-table th,
-.results-table td {
- border: 1px solid #777;
- padding-left: 4px;
- padding-right: 4px;
-}
-
-.results-table th {
- background: rgb(224,236,255);
-}
-
-.results-table tbody tr:hover {
- background-color: rgb(255, 255, 187);
-}
-
-/*
- * Make the column headers change the mouse to a "hand" cursor, sine they are
- * clickable.
- */
-.results-table th {
- cursor: pointer;
-}
-
-/*
- * This is row which displays aggregate totals for each column.
- */
-.results-table .aggregator-row {
- background: rgb(255, 204, 153);
-}
-
-/*
- * This is the row at the end of tables which explains how many rows were shown,
- * and how many were hidden.
- */
-.results-table .truncation-row {
- background: #eee;
-}
-
-/*---------------------------------------------------------------------------*/
-
-/*
- * When grouping data, the table for each bucket is wrapped in a DIV with this
- * class. Used to add a bit of spacing between groups.
- */
-.group-container {
- margin-bottom: 2ex;
- margin-top: 2ex;
-}
-
-/*
- * The title for each group is enclosed in a DIV of the following class.
- */
-.group-title-container {
- font-size: 140%;
- margin-bottom: 1ex;
-}
-
-/* Styling to make a span look like a clickable link */
-.pseudo-link {
- color: blue;
- cursor: pointer;
- text-decoration: underline;
-}
-
-.selected-snapshot {
- color: purple;
- font-weight: bold;
-}
-
-#snapshot-selection-summary {
- color: green;
- font-style: italic;
- font-weight: bold;
- margin-top: 1ex;
-}
-
-.errormsg {
- color: red;
-}
-
-</style>
-</head>
-<body>
- <table width=100%>
- <tr>
- <td>
- <b>Save:</b><button id=save-snapshots-button>Save</button>
- <b>Restore:</b> <input type=file id=snapshot-file-loader>
- <span id=file-load-error hidden class=errormsg></span>
- </td>
- <td align=right>
- <a target="_blank"
- href="https://sites.google.com/a/chromium.org/dev/developers/threaded-task-tracking">
- Profiler Documentation
- </a>
- </td>
- </tr>
- </table>
- <hr>
- <table width=100%>
- <tr>
- <td>
- <b>Group by: </b> <span id=group-by-container></span>
- <b>Sort by: </b> <span id=sort-by-container></span>
- </td>
- <td align=right>
- <span id=snapshots-link class=pseudo-link>[snapshots]</span>
- <span id=edit-columns-link class=pseudo-link>[columns]</span>
- <input type='search' incremental id='filter-search'>
- </td>
- </tr>
- <tr id=edit-columns-row style='display:none'>
- <td colspan=2>
- <div>
- <b>Merge: </b><span id=column-merge-toggles-container></span>
- <label><input type=checkbox id='merge-similar-threads-checkbox' checked>
- Merge similar threads.</label>
- </div>
- <div>
- <b>Show: </b><span id=column-toggles-container></span>
- </div>
- </td>
- </tr>
- <tr id=snapshots-row style='display:none'>
- <td colspan=2>
- <button id=take-snapshot-button>Add snapshot</button>
- <table><tbody id=snapshots-tbody></tbody></table>
- <div id=snapshot-selection-summary></div>
- </td>
- </tr>
- </table>
-
- <hr>
-
- <div id='results-div'></div>
-
- <a style="display: none" id="download-anchor" download="profile.json"></a>
-</body>
-</html>
diff --git a/chromium/chrome/browser/resources/profiler/profiler.js b/chromium/chrome/browser/resources/profiler/profiler.js
deleted file mode 100644
index 81b1250b8aa..00000000000
--- a/chromium/chrome/browser/resources/profiler/profiler.js
+++ /dev/null
@@ -1,2371 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var g_browserBridge;
-var g_mainView;
-
-// TODO(eroman): The handling of "max" across snapshots is not correct.
-// For starters the browser needs to be aware to generate new maximums.
-// Secondly, we need to take into account the "max" of intermediary snapshots,
-// not just the terminal ones.
-
-/**
- * Main entry point called once the page has loaded.
- */
-function onLoad() {
- g_browserBridge = new BrowserBridge();
- g_mainView = new MainView();
-}
-
-document.addEventListener('DOMContentLoaded', onLoad);
-
-/**
- * This class provides a "bridge" for communicating between the javascript and
- * the browser. Used as a singleton.
- */
-var BrowserBridge = (function() {
- 'use strict';
-
- /**
- * @constructor
- */
- function BrowserBridge() {}
-
- BrowserBridge.prototype = {
- //--------------------------------------------------------------------------
- // Messages sent to the browser
- //--------------------------------------------------------------------------
-
- sendGetData: function() {
- chrome.send('getData');
- },
-
- //--------------------------------------------------------------------------
- // Messages received from the browser.
- //--------------------------------------------------------------------------
-
- receivedData: function(data) {
- // TODO(eroman): The browser should give an indication of which snapshot
- // this data belongs to. For now we always assume it is for the latest.
- g_mainView.addDataToSnapshot(data);
- },
- };
-
- return BrowserBridge;
-})();
-
-/**
- * This class handles the presentation of our profiler view. Used as a
- * singleton.
- */
-var MainView = (function() {
- 'use strict';
-
- // --------------------------------------------------------------------------
- // Important IDs in the HTML document
- // --------------------------------------------------------------------------
-
- // The search box to filter results.
- var FILTER_SEARCH_ID = 'filter-search';
-
- // The container node to put all the "Group by" dropdowns into.
- var GROUP_BY_CONTAINER_ID = 'group-by-container';
-
- // The container node to put all the "Sort by" dropdowns into.
- var SORT_BY_CONTAINER_ID = 'sort-by-container';
-
- // The DIV to put all the tables into.
- var RESULTS_DIV_ID = 'results-div';
-
- // The container node to put all the column (visibility) checkboxes into.
- var COLUMN_TOGGLES_CONTAINER_ID = 'column-toggles-container';
-
- // The container node to put all the column (merge) checkboxes into.
- var COLUMN_MERGE_TOGGLES_CONTAINER_ID = 'column-merge-toggles-container';
-
- // The anchor which toggles visibility of column checkboxes.
- var EDIT_COLUMNS_LINK_ID = 'edit-columns-link';
-
- // The container node to show/hide when toggling the column checkboxes.
- var EDIT_COLUMNS_ROW = 'edit-columns-row';
-
- // The checkbox which controls whether things like "Worker Threads" and
- // "PAC threads" will be merged together.
- var MERGE_SIMILAR_THREADS_CHECKBOX_ID = 'merge-similar-threads-checkbox';
-
- var TOGGLE_SNAPSHOTS_LINK_ID = 'snapshots-link';
- var SNAPSHOTS_ROW = 'snapshots-row';
- var SNAPSHOT_SELECTION_SUMMARY_ID = 'snapshot-selection-summary';
- var TAKE_SNAPSHOT_BUTTON_ID = 'take-snapshot-button';
-
- var SAVE_SNAPSHOTS_BUTTON_ID = 'save-snapshots-button';
- var SNAPSHOT_FILE_LOADER_ID = 'snapshot-file-loader';
- var LOAD_ERROR_ID = 'file-load-error';
-
- var DOWNLOAD_ANCHOR_ID = 'download-anchor';
-
- // --------------------------------------------------------------------------
- // Row keys
- // --------------------------------------------------------------------------
-
- // Each row of our data is an array of values rather than a dictionary. This
- // avoids some overhead from repeating the key string multiple times, and
- // speeds up the property accesses a bit. The following keys are well-known
- // indexes into the array for various properties.
- //
- // Note that the declaration order will also define the default display order.
-
- var BEGIN_KEY = 1; // Start at 1 rather than 0 to simplify sorting code.
- var END_KEY = BEGIN_KEY;
-
- var KEY_COUNT = END_KEY++;
- var KEY_RUN_TIME = END_KEY++;
- var KEY_AVG_RUN_TIME = END_KEY++;
- var KEY_MAX_RUN_TIME = END_KEY++;
- var KEY_QUEUE_TIME = END_KEY++;
- var KEY_AVG_QUEUE_TIME = END_KEY++;
- var KEY_MAX_QUEUE_TIME = END_KEY++;
- if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) {
- var KEY_MEMORY_AVG_ALLOC_OPS = END_KEY++;
- var KEY_MEMORY_AVG_FREE_OPS = END_KEY++;
- var KEY_MEMORY_AVG_NET_BYTES = END_KEY++;
- var KEY_MEMORY_MAX_ALLOCATED_BYTES = END_KEY++;
- var KEY_MEMORY_ALLOC_OPS = END_KEY++;
- var KEY_MEMORY_FREE_OPS = END_KEY++;
- var KEY_MEMORY_ALLOCATED_BYTES = END_KEY++;
- var KEY_MEMORY_FREED_BYTES = END_KEY++;
- var KEY_MEMORY_ALLOC_OVERHEAD_BYTES = END_KEY++;
- }
- var KEY_BIRTH_THREAD = END_KEY++;
- var KEY_DEATH_THREAD = END_KEY++;
- var KEY_PROCESS_TYPE = END_KEY++;
- var KEY_PROCESS_ID = END_KEY++;
- var KEY_FUNCTION_NAME = END_KEY++;
- var KEY_SOURCE_LOCATION = END_KEY++;
- var KEY_FILE_NAME = END_KEY++;
- var KEY_LINE_NUMBER = END_KEY++;
-
- var NUM_KEYS = END_KEY - BEGIN_KEY;
-
- // --------------------------------------------------------------------------
- // Aggregators
- // --------------------------------------------------------------------------
-
- // To generalize computing/displaying the aggregate "counts" for each column,
- // we specify an optional "Aggregator" class to use with each property.
-
- // The following are actually "Aggregator factories". They create an
- // aggregator instance by calling 'create()'. The instance is then fed
- // each row one at a time via the 'consume()' method. After all rows have
- // been consumed, the 'getValueAsText()' method will return the aggregated
- // value.
-
- /**
- * This aggregator counts the number of unique values that were fed to it.
- */
- var UniquifyAggregator = (function() {
- function Aggregator(key) {
- this.key_ = key;
- this.valuesSet_ = {};
- }
-
- Aggregator.prototype = {
- consume: function(e) {
- this.valuesSet_[e[this.key_]] = true;
- },
-
- getValueAsText: function() {
- return getDictionaryKeys(this.valuesSet_).length + ' unique';
- },
- };
-
- return {
- create: function(key) {
- return new Aggregator(key);
- }
- };
- })();
-
- /**
- * This aggregator sums a numeric field.
- */
- var SumAggregator = (function() {
- function Aggregator(key) {
- this.key_ = key;
- this.sum_ = 0;
- }
-
- Aggregator.prototype = {
- consume: function(e) {
- this.sum_ += e[this.key_];
- },
-
- getValue: function() {
- return this.sum_;
- },
-
- getValueAsText: function() {
- return formatNumberAsText(this.getValue());
- },
- };
-
- return {
- create: function(key) {
- return new Aggregator(key);
- }
- };
- })();
-
- /**
- * This aggregator computes an average by summing two
- * numeric fields, and then dividing the totals.
- */
- var AvgAggregator = (function() {
- function Aggregator(numeratorKey, divisorKey) {
- this.numeratorKey_ = numeratorKey;
- this.divisorKey_ = divisorKey;
-
- this.numeratorSum_ = 0;
- this.divisorSum_ = 0;
- }
-
- Aggregator.prototype = {
- consume: function(e) {
- this.numeratorSum_ += e[this.numeratorKey_];
- this.divisorSum_ += e[this.divisorKey_];
- },
-
- getValue: function() {
- return this.numeratorSum_ / this.divisorSum_;
- },
-
- getValueAsText: function() {
- return formatNumberAsText(this.getValue());
- },
- };
-
- return {
- create: function(numeratorKey, divisorKey) {
- return {
- create: function(key) {
- return new Aggregator(numeratorKey, divisorKey);
- },
- };
- }
- };
- })();
-
- /**
- * This aggregator computes an average by summing the difference of two
- * numeric fields, summing a count, and then dividing the totals.
- */
- var AvgDiffAggregator = (function() {
- function Aggregator(numeratorPosKey, numeratorNegKey, divisorKey) {
- this.numeratorPosKey_ = numeratorPosKey;
- this.numeratorNegKey_ = numeratorNegKey;
- this.divisorKey_ = divisorKey;
-
- this.numeratorSum_ = 0;
- this.divisorSum_ = 0;
- }
-
- Aggregator.prototype = {
- consume: function(e) {
- this.numeratorSum_ +=
- e[this.numeratorPosKey_] - e[this.numeratorNegKey_];
- this.divisorSum_ += e[this.divisorKey_];
- },
-
- getValue: function() {
- return this.numeratorSum_ / this.divisorSum_;
- },
-
- getValueAsText: function() {
- return formatNumberAsText(this.getValue());
- },
- };
-
- return {
- create: function(numeratorPosKey, numeratorNegKey, divisorKey) {
- return {
- create: function(key) {
- return new Aggregator(numeratorPosKey, numeratorNegKey, divisorKey);
- },
- };
- }
- };
- })();
-
- /**
- * This aggregator finds the maximum for a numeric field.
- */
- var MaxAggregator = (function() {
- function Aggregator(key) {
- this.key_ = key;
- this.max_ = -Infinity;
- }
-
- Aggregator.prototype = {
- consume: function(e) {
- this.max_ = Math.max(this.max_, e[this.key_]);
- },
-
- getValue: function() {
- return this.max_;
- },
-
- getValueAsText: function() {
- return formatNumberAsText(this.getValue());
- },
- };
-
- return {
- create: function(key) {
- return new Aggregator(key);
- }
- };
- })();
-
- // --------------------------------------------------------------------------
- // Key properties
- // --------------------------------------------------------------------------
-
- // Custom comparator for thread names (sorts main thread and IO thread
- // higher than would happen lexicographically.)
- var threadNameComparator = createLexicographicComparatorWithExceptions([
- 'CrBrowserMain',
- 'Chrome_IOThread',
- 'Chrome_FileThread',
- 'Chrome_HistoryThread',
- 'Chrome_DBThread',
- 'Still_Alive',
- ]);
-
- function diffFuncForCount(a, b) {
- return b - a;
- }
-
- function diffFuncForMax(a, b) {
- return b;
- }
-
- /**
- * Enumerates information about various keys. Such as whether their data is
- * expected to be numeric or is a string, a descriptive name (title) for the
- * property, and what function should be used to aggregate the property when
- * displayed in a column.
- *
- * --------------------------------------
- * The following properties are required:
- * --------------------------------------
- *
- * [name]: This is displayed as the column's label.
- * [aggregator]: Aggregator factory that is used to compute an aggregate
- * value for this column.
- *
- * --------------------------------------
- * The following properties are optional:
- * --------------------------------------
- *
- * [inputJsonKey]: The corresponding key for this property in the original
- * JSON dictionary received from the browser. If this is
- * present, values for this key will be automatically
- * populated during import.
- * [comparator]: A comparator function for sorting this column.
- * [textPrinter]: A function that transforms values into the user-displayed
- * text shown in the UI. If unspecified, will default to the
- * "toString()" function.
- * [cellAlignment]: The horizonal alignment to use for columns of this
- * property (for instance 'right'). If unspecified will
- * default to left alignment.
- * [sortDescending]: When first clicking on this column, we will default to
- * sorting by |comparator| in ascending order. If this
- * property is true, we will reverse that to descending.
- * [diff]: Function to call to compute a "difference" value between
- * parameters (a, b). This is used when calculating the difference
- * between two snapshots. Diffing numeric quantities generally
- * involves subtracting, but some fields like max may need to do
- * something different.
- */
- var KEY_PROPERTIES = [];
-
- KEY_PROPERTIES[KEY_PROCESS_ID] = {
- name: 'PID',
- cellAlignment: 'right',
- aggregator: UniquifyAggregator,
- };
-
- KEY_PROPERTIES[KEY_PROCESS_TYPE] = {
- name: 'Process type',
- aggregator: UniquifyAggregator,
- };
-
- KEY_PROPERTIES[KEY_BIRTH_THREAD] = {
- name: 'Birth thread',
- inputJsonKey: 'birth_thread',
- aggregator: UniquifyAggregator,
- comparator: threadNameComparator,
- };
-
- KEY_PROPERTIES[KEY_DEATH_THREAD] = {
- name: 'Exec thread',
- inputJsonKey: 'death_thread',
- aggregator: UniquifyAggregator,
- comparator: threadNameComparator,
- };
-
- KEY_PROPERTIES[KEY_FUNCTION_NAME] = {
- name: 'Function name',
- inputJsonKey: 'birth_location.function_name',
- aggregator: UniquifyAggregator,
- };
-
- KEY_PROPERTIES[KEY_FILE_NAME] = {
- name: 'File name',
- inputJsonKey: 'birth_location.file_name',
- aggregator: UniquifyAggregator,
- };
-
- KEY_PROPERTIES[KEY_LINE_NUMBER] = {
- name: 'Line number',
- cellAlignment: 'right',
- inputJsonKey: 'birth_location.line_number',
- aggregator: UniquifyAggregator,
- };
-
- KEY_PROPERTIES[KEY_COUNT] = {
- name: 'Count',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.count',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- KEY_PROPERTIES[KEY_QUEUE_TIME] = {
- name: 'Total queue time',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.queue_ms',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- KEY_PROPERTIES[KEY_MAX_QUEUE_TIME] = {
- name: 'Max queue time',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.queue_ms_max',
- aggregator: MaxAggregator,
- diff: diffFuncForMax,
- };
-
- KEY_PROPERTIES[KEY_RUN_TIME] = {
- name: 'Total run time',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.run_ms',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) {
- KEY_PROPERTIES[KEY_MEMORY_AVG_ALLOC_OPS] = {
- name: 'Avg Allocations',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- aggregator: AvgAggregator.create(KEY_MEMORY_ALLOC_OPS, KEY_COUNT),
- };
-
- KEY_PROPERTIES[KEY_MEMORY_AVG_FREE_OPS] = {
- name: 'Avg Frees',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- aggregator: AvgAggregator.create(KEY_MEMORY_FREE_OPS, KEY_COUNT),
- };
-
- KEY_PROPERTIES[KEY_MEMORY_AVG_NET_BYTES] = {
- name: 'Avg Net Bytes',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- aggregator: AvgDiffAggregator.create(
- KEY_MEMORY_ALLOCATED_BYTES, KEY_MEMORY_FREED_BYTES, KEY_COUNT),
- };
-
- KEY_PROPERTIES[KEY_MEMORY_ALLOC_OPS] = {
- name: 'Allocation count',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.alloc_ops',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- KEY_PROPERTIES[KEY_MEMORY_FREE_OPS] = {
- name: 'Free Count',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.free_ops',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- KEY_PROPERTIES[KEY_MEMORY_ALLOCATED_BYTES] = {
- name: 'Allocated bytes',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.allocated_bytes',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- KEY_PROPERTIES[KEY_MEMORY_FREED_BYTES] = {
- name: 'Freed bytes',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.freed_bytes',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- KEY_PROPERTIES[KEY_MEMORY_ALLOC_OVERHEAD_BYTES] = {
- name: 'Overhead bytes',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.alloc_overhead_bytes',
- aggregator: SumAggregator,
- diff: diffFuncForCount,
- };
-
- KEY_PROPERTIES[KEY_MEMORY_MAX_ALLOCATED_BYTES] = {
- name: 'Max allocated (outstanding) bytes',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.max_allocated_bytes',
- aggregator: MaxAggregator,
- diff: diffFuncForMax,
- };
- }
-
- KEY_PROPERTIES[KEY_AVG_RUN_TIME] = {
- name: 'Avg run time',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- aggregator: AvgAggregator.create(KEY_RUN_TIME, KEY_COUNT),
- };
-
- KEY_PROPERTIES[KEY_MAX_RUN_TIME] = {
- name: 'Max run time',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- inputJsonKey: 'death_data.run_ms_max',
- aggregator: MaxAggregator,
- diff: diffFuncForMax,
- };
-
- KEY_PROPERTIES[KEY_AVG_QUEUE_TIME] = {
- name: 'Avg queue time',
- cellAlignment: 'right',
- sortDescending: true,
- textPrinter: formatNumberAsText,
- aggregator: AvgAggregator.create(KEY_QUEUE_TIME, KEY_COUNT),
- };
-
- KEY_PROPERTIES[KEY_SOURCE_LOCATION] = {
- name: 'Source location',
- type: 'string',
- aggregator: UniquifyAggregator,
- };
-
- /**
- * Returns the string name for |key|.
- */
- function getNameForKey(key) {
- var props = KEY_PROPERTIES[key];
- if (props == undefined)
- throw 'Did not define properties for key: ' + key;
- return props.name;
- }
-
- /**
- * Ordered list of all keys. This is the order we generally want
- * to display the properties in. Default to declaration order.
- */
- var ALL_KEYS = [];
- for (var k = BEGIN_KEY; k < END_KEY; ++k)
- ALL_KEYS.push(k);
-
- // --------------------------------------------------------------------------
- // Default settings
- // --------------------------------------------------------------------------
-
- /**
- * List of keys for those properties which we want to initially omit
- * from the table. (They can be re-enabled by clicking [Edit columns]).
- */
- var INITIALLY_HIDDEN_KEYS = [
- KEY_FILE_NAME,
- KEY_LINE_NUMBER,
- KEY_QUEUE_TIME,
- ];
-
- if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) {
- INITIALLY_HIDDEN_KEYS = INITIALLY_HIDDEN_KEYS.concat([
- KEY_MEMORY_ALLOC_OPS,
- KEY_MEMORY_FREE_OPS,
- KEY_MEMORY_ALLOCATED_BYTES,
- KEY_MEMORY_FREED_BYTES,
- KEY_MEMORY_ALLOC_OVERHEAD_BYTES,
- ]);
- }
-
- /**
- * The ordered list of grouping choices to expose in the "Group by"
- * dropdowns. We don't include the numeric properties, since they
- * leads to awkward bucketing.
- */
- var GROUPING_DROPDOWN_CHOICES = [
- KEY_PROCESS_TYPE,
- KEY_PROCESS_ID,
- KEY_BIRTH_THREAD,
- KEY_DEATH_THREAD,
- KEY_FUNCTION_NAME,
- KEY_SOURCE_LOCATION,
- KEY_FILE_NAME,
- KEY_LINE_NUMBER,
- ];
-
- /**
- * The ordered list of sorting choices to expose in the "Sort by"
- * dropdowns.
- */
- var SORT_DROPDOWN_CHOICES = ALL_KEYS;
-
- /**
- * The ordered list of all columns that can be displayed in the tables (not
- * including whatever has been hidden via [Edit Columns]).
- */
- var ALL_TABLE_COLUMNS = ALL_KEYS;
-
- /**
- * The initial keys to sort by when loading the page (can be changed later).
- */
- var INITIAL_SORT_KEYS = [-KEY_COUNT];
-
- /**
- * The default sort keys to use when nothing has been specified.
- */
- var DEFAULT_SORT_KEYS = [-KEY_COUNT];
-
- /**
- * The initial keys to group by when loading the page (can be changed later).
- */
- var INITIAL_GROUP_KEYS = [];
-
- /**
- * The columns to give the option to merge on.
- */
- var MERGEABLE_KEYS = [
- KEY_PROCESS_ID,
- KEY_PROCESS_TYPE,
- KEY_BIRTH_THREAD,
- KEY_DEATH_THREAD,
- ];
-
- /**
- * The columns to merge by default.
- */
- var INITIALLY_MERGED_KEYS = [];
-
- /**
- * The full set of columns which define the "identity" for a row. A row is
- * considered equivalent to another row if it matches on all of these
- * fields. This list is used when merging the data, to determine which rows
- * should be merged together. The remaining columns not listed in
- * IDENTITY_KEYS will be aggregated.
- */
- var IDENTITY_KEYS = [
- KEY_BIRTH_THREAD,
- KEY_DEATH_THREAD,
- KEY_PROCESS_TYPE,
- KEY_PROCESS_ID,
- KEY_FUNCTION_NAME,
- KEY_SOURCE_LOCATION,
- KEY_FILE_NAME,
- KEY_LINE_NUMBER,
- ];
-
- /**
- * The time (in milliseconds) to wait after receiving new data before
- * re-drawing it to the screen. The reason we wait a bit is to avoid
- * repainting repeatedly during the loading phase (which can slow things
- * down). Note that this only slows down the addition of new data. It does
- * not impact the latency of user-initiated operations like sorting or
- * merging.
- */
- var PROCESS_DATA_DELAY_MS = 500;
-
- /**
- * The initial number of rows to display (the rest are hidden) when no
- * grouping is selected. We use a higher limit than when grouping is used
- * since there is a lot of vertical real estate.
- */
- var INITIAL_UNGROUPED_ROW_LIMIT = 30;
-
- /**
- * The initial number of rows to display (rest are hidden) for each group.
- */
- var INITIAL_GROUP_ROW_LIMIT = 10;
-
- /**
- * The number of extra rows to show/hide when clicking the "Show more" or
- * "Show less" buttons.
- */
- var LIMIT_INCREMENT = 10;
-
- // --------------------------------------------------------------------------
- // General utility functions
- // --------------------------------------------------------------------------
-
- /**
- * Returns a list of all the keys in |dict|.
- */
- function getDictionaryKeys(dict) {
- var keys = [];
- for (var key in dict) {
- keys.push(key);
- }
- return keys;
- }
-
- /**
- * Formats the number |x| as a decimal integer. Strips off any decimal parts,
- * and comma separates the number every 3 characters.
- */
- function formatNumberAsText(x) {
- var orig = x.toFixed(0);
-
- var parts = [];
- for (var end = orig.length; end > 0;) {
- var chunk = Math.min(end, 3);
- parts.push(orig.substr(end - chunk, chunk));
- end -= chunk;
- }
- return parts.reverse().join(',');
- }
-
- /**
- * Simple comparator function which works for both strings and numbers.
- */
- function simpleCompare(a, b) {
- if (a == b)
- return 0;
- if (a < b)
- return -1;
- return 1;
- }
-
- /**
- * Returns a comparator function that compares values lexicographically,
- * but special-cases the values in |orderedList| to have a higher
- * rank.
- */
- function createLexicographicComparatorWithExceptions(orderedList) {
- var valueToRankMap = {};
- for (var i = 0; i < orderedList.length; ++i)
- valueToRankMap[orderedList[i]] = i;
-
- function getCustomRank(x) {
- var rank = valueToRankMap[x];
- if (rank == undefined)
- rank = Infinity; // Unmatched.
- return rank;
- }
-
- return function(a, b) {
- var aRank = getCustomRank(a);
- var bRank = getCustomRank(b);
-
- // Not matched by any of our exceptions.
- if (aRank == bRank)
- return simpleCompare(a, b);
-
- if (aRank < bRank)
- return -1;
- return 1;
- };
- }
-
- /**
- * Returns dict[key]. Note that if |key| contains periods (.), they will be
- * interpreted as meaning a sub-property.
- */
- function getPropertyByPath(dict, key) {
- var cur = dict;
- var parts = key.split('.');
- for (var i = 0; i < parts.length; ++i) {
- if (cur == undefined)
- return undefined;
- cur = cur[parts[i]];
- }
- return cur;
- }
-
- /**
- * Creates and appends a DOM node of type |tagName| to |parent|. Optionally,
- * sets the new node's text to |opt_text|. Returns the newly created node.
- */
- function addNode(parent, tagName, opt_text) {
- var n = parent.ownerDocument.createElement(tagName);
- parent.appendChild(n);
- if (opt_text != undefined) {
- addText(n, opt_text);
- }
- return n;
- }
-
- /**
- * Adds |text| to |parent|.
- */
- function addText(parent, text) {
- var textNode = parent.ownerDocument.createTextNode(text);
- parent.appendChild(textNode);
- return textNode;
- }
-
- /**
- * Deletes all the strings in |array| which appear in |valuesToDelete|.
- */
- function deleteValuesFromArray(array, valuesToDelete) {
- var valueSet = arrayToSet(valuesToDelete);
- for (var i = 0; i < array.length;) {
- if (valueSet[array[i]]) {
- array.splice(i, 1);
- } else {
- i++;
- }
- }
- }
-
- /**
- * Deletes all the repeated ocurrences of strings in |array|.
- */
- function deleteDuplicateStringsFromArray(array) {
- // Build up set of each entry in array.
- var seenSoFar = {};
-
- for (var i = 0; i < array.length;) {
- var value = array[i];
- if (seenSoFar[value]) {
- array.splice(i, 1);
- } else {
- seenSoFar[value] = true;
- i++;
- }
- }
- }
-
- /**
- * Builds a map out of the array |list|.
- */
- function arrayToSet(list) {
- var set = {};
- for (var i = 0; i < list.length; ++i)
- set[list[i]] = true;
- return set;
- }
-
- function trimWhitespace(text) {
- var m = /^\s*(.*)\s*$/.exec(text);
- return m[1];
- }
-
- /**
- * Selects the option in |select| which has a value of |value|.
- */
- function setSelectedOptionByValue(select, value) {
- for (var i = 0; i < select.options.length; ++i) {
- if (select.options[i].value == value) {
- select.options[i].selected = true;
- return true;
- }
- }
- return false;
- }
-
- /**
- * Adds a checkbox to |parent|. The checkbox will have a label on its right
- * with text |label|. Returns the checkbox input node.
- */
- function addLabeledCheckbox(parent, label) {
- var labelNode = addNode(parent, 'label');
- var checkbox = addNode(labelNode, 'input');
- checkbox.type = 'checkbox';
- addText(labelNode, label);
- return checkbox;
- }
-
- /**
- * Return the last component in a path which is separated by either forward
- * slashes or backslashes.
- */
- function getFilenameFromPath(path) {
- var lastSlash = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
- if (lastSlash == -1)
- return path;
-
- return path.substr(lastSlash + 1);
- }
-
- /**
- * Returns the current time in milliseconds since unix epoch.
- */
- function getTimeMillis() {
- return (new Date()).getTime();
- }
-
- /**
- * Toggle a node between hidden/invisible.
- */
- function toggleNodeDisplay(n) {
- if (n.style.display == '') {
- n.style.display = 'none';
- } else {
- n.style.display = '';
- }
- }
-
- /**
- * Set the visibility state of a node.
- */
- function setNodeDisplay(n, visible) {
- if (visible) {
- n.style.display = '';
- } else {
- n.style.display = 'none';
- }
- }
-
- // --------------------------------------------------------------------------
- // Functions that augment, bucket, and compute aggregates for the input data.
- // --------------------------------------------------------------------------
-
- /**
- * Adds new derived properties to row. Mutates the provided dictionary |e|.
- */
- function augmentDataRow(e) {
- computeDataRowAverages(e);
- e[KEY_SOURCE_LOCATION] = e[KEY_FILE_NAME] + ' [' + e[KEY_LINE_NUMBER] + ']';
- }
-
- function computeDataRowAverages(e) {
- e[KEY_AVG_QUEUE_TIME] = e[KEY_QUEUE_TIME] / e[KEY_COUNT];
- e[KEY_AVG_RUN_TIME] = e[KEY_RUN_TIME] / e[KEY_COUNT];
-
- if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) {
- e[KEY_MEMORY_AVG_ALLOC_OPS] = e[KEY_MEMORY_ALLOC_OPS] / e[KEY_COUNT];
- e[KEY_MEMORY_AVG_FREE_OPS] = e[KEY_MEMORY_FREE_OPS] / e[KEY_COUNT];
- e[KEY_MEMORY_AVG_NET_BYTES] =
- (e[KEY_MEMORY_ALLOCATED_BYTES] - e[KEY_MEMORY_FREED_BYTES]) /
- e[KEY_COUNT];
- }
- }
-
- /**
- * Creates and initializes an aggregator object for each key in |columns|.
- * Returns an array whose keys are values from |columns|, and whose
- * values are Aggregator instances.
- */
- function initializeAggregates(columns) {
- var aggregates = [];
-
- for (var i = 0; i < columns.length; ++i) {
- var key = columns[i];
- var aggregatorFactory = KEY_PROPERTIES[key].aggregator;
- aggregates[key] = aggregatorFactory.create(key);
- }
-
- return aggregates;
- }
-
- function consumeAggregates(aggregates, row) {
- for (var key in aggregates)
- aggregates[key].consume(row);
- }
-
- function bucketIdenticalRows(rows, identityKeys, propertyGetterFunc) {
- var identicalRows = {};
- for (var i = 0; i < rows.length; ++i) {
- var r = rows[i];
-
- var rowIdentity = [];
- for (var j = 0; j < identityKeys.length; ++j)
- rowIdentity.push(propertyGetterFunc(r, identityKeys[j]));
- rowIdentity = rowIdentity.join('\n');
-
- var l = identicalRows[rowIdentity];
- if (!l) {
- l = [];
- identicalRows[rowIdentity] = l;
- }
- l.push(r);
- }
- return identicalRows;
- }
-
- /**
- * Merges the rows in |origRows|, by collapsing the columns listed in
- * |mergeKeys|. Returns an array with the merged rows (in no particular
- * order).
- *
- * If |mergeSimilarThreads| is true, then threads with a similar name will be
- * considered equivalent. For instance, "WorkerThread-1" and "WorkerThread-2"
- * will be remapped to "WorkerThread-*".
- *
- * If |outputAsDictionary| is false then the merged rows will be returned as a
- * flat list. Otherwise the result will be a dictionary, where each row
- * has a unique key.
- */
- function mergeRows(
- origRows, mergeKeys, mergeSimilarThreads, outputAsDictionary) {
- // Define a translation function for each property. Normally we copy over
- // properties as-is, but if we have been asked to "merge similar threads" we
- // we will remap the thread names that end in a numeric suffix.
- var propertyGetterFunc;
-
- if (mergeSimilarThreads) {
- propertyGetterFunc = function(row, key) {
- var value = row[key];
- // If the property is a thread name, try to remap it.
- if (key == KEY_BIRTH_THREAD || key == KEY_DEATH_THREAD) {
- var m = /^(.*[^\d])(\d+)$/.exec(value);
- if (m)
- value = m[1] + '*';
- }
- return value;
- };
- } else {
- propertyGetterFunc = function(row, key) {
- return row[key];
- };
- }
-
- // Determine which sets of properties a row needs to match on to be
- // considered identical to another row.
- var identityKeys = IDENTITY_KEYS.slice(0);
- deleteValuesFromArray(identityKeys, mergeKeys);
-
- // Set |aggregateKeys| to everything else, since we will be aggregating
- // their value as part of the merge.
- var aggregateKeys = ALL_KEYS.slice(0);
- deleteValuesFromArray(aggregateKeys, IDENTITY_KEYS);
- deleteValuesFromArray(aggregateKeys, mergeKeys);
-
- // Group all the identical rows together, bucketed into |identicalRows|.
- var identicalRows =
- bucketIdenticalRows(origRows, identityKeys, propertyGetterFunc);
-
- var mergedRows = outputAsDictionary ? {} : [];
-
- // Merge the rows and save the results to |mergedRows|.
- for (var k in identicalRows) {
- // We need to smash the list |l| down to a single row...
- var l = identicalRows[k];
-
- var newRow = [];
-
- if (outputAsDictionary) {
- mergedRows[k] = newRow;
- } else {
- mergedRows.push(newRow);
- }
-
- // Copy over all the identity columns to the new row (since they
- // were the same for each row matched).
- for (var i = 0; i < identityKeys.length; ++i)
- newRow[identityKeys[i]] = propertyGetterFunc(l[0], identityKeys[i]);
-
- // Compute aggregates for the other columns.
- var aggregates = initializeAggregates(aggregateKeys);
-
- // Feed the rows to the aggregators.
- for (var i = 0; i < l.length; ++i)
- consumeAggregates(aggregates, l[i]);
-
- // Suck out the data generated by the aggregators.
- for (var aggregateKey in aggregates)
- newRow[aggregateKey] = aggregates[aggregateKey].getValue();
- }
-
- return mergedRows;
- }
-
- /**
- * Takes two dictionaries data1 and data2, and returns a new flat list which
- * represents the difference between them. The exact meaning of "difference"
- * is column specific, but for most numeric fields (like the count, or total
- * time), it is found by subtracting.
- *
- * Rows in data1 and data2 are expected to use the same scheme for the keys.
- * In other words, data1[k] is considered the analagous row to data2[k].
- */
- function subtractSnapshots(data1, data2, columnsToExclude) {
- // These columns are computed from the other columns. We won't bother
- // diffing/aggregating these, but rather will derive them again from the
- // final row.
- var COMPUTED_AGGREGATE_KEYS = [KEY_AVG_QUEUE_TIME, KEY_AVG_RUN_TIME];
- if (loadTimeData.getBoolean('enableMemoryTaskProfiler')) {
- COMPUTED_AGGREGATE_KEYS = COMPUTED_AGGREGATE_KEYS.concat([
- KEY_MEMORY_AVG_ALLOC_OPS, KEY_MEMORY_AVG_FREE_OPS,
- KEY_MEMORY_AVG_NET_BYTES
- ]);
- }
-
- // These are the keys which determine row equality. Since we are not doing
- // any merging yet at this point, it is simply the list of all identity
- // columns.
- var identityKeys = IDENTITY_KEYS.slice(0);
- deleteValuesFromArray(identityKeys, columnsToExclude);
-
- // The columns to compute via aggregation is everything else.
- var aggregateKeys = ALL_KEYS.slice(0);
- deleteValuesFromArray(aggregateKeys, IDENTITY_KEYS);
- deleteValuesFromArray(aggregateKeys, COMPUTED_AGGREGATE_KEYS);
- deleteValuesFromArray(aggregateKeys, columnsToExclude);
-
- var diffedRows = [];
-
- for (var rowId in data2) {
- var row1 = data1[rowId];
- var row2 = data2[rowId];
-
- var newRow = [];
-
- // Copy over all the identity columns to the new row (since they
- // were the same for each row matched).
- for (var i = 0; i < identityKeys.length; ++i)
- newRow[identityKeys[i]] = row2[identityKeys[i]];
-
- // Diff the two rows.
- if (row1) {
- for (var i = 0; i < aggregateKeys.length; ++i) {
- var aggregateKey = aggregateKeys[i];
- var a = row1[aggregateKey];
- var b = row2[aggregateKey];
-
- var diffFunc = KEY_PROPERTIES[aggregateKey].diff;
- newRow[aggregateKey] = diffFunc(a, b);
- }
- } else {
- // If the the row doesn't appear in snapshot1, then there is nothing to
- // diff, so just copy row2 as is.
- for (var i = 0; i < aggregateKeys.length; ++i) {
- var aggregateKey = aggregateKeys[i];
- newRow[aggregateKey] = row2[aggregateKey];
- }
- }
-
- if (newRow[KEY_COUNT] == 0) {
- // If a row's count has gone to zero, it means there were no new
- // occurrences of it in the second snapshot, so remove it.
- continue;
- }
-
- // Since we excluded the averages during the diffing phase, re-compute
- // them using the diffed totals.
- computeDataRowAverages(newRow);
- diffedRows.push(newRow);
- }
-
- return diffedRows;
- }
-
- // --------------------------------------------------------------------------
- // HTML drawing code
- // --------------------------------------------------------------------------
-
- function getTextValueForProperty(key, value) {
- if (value == undefined) {
- // A value may be undefined as a result of having merging rows. We
- // won't actually draw it, but this might be called by the filter.
- return '';
- }
-
- var textPrinter = KEY_PROPERTIES[key].textPrinter;
- if (textPrinter)
- return textPrinter(value);
- return value.toString();
- }
-
- /**
- * Renders the property value |value| into cell |td|. The name of this
- * property is |key|.
- */
- function drawValueToCell(td, key, value) {
- // Get a text representation of the value.
- var text = getTextValueForProperty(key, value);
-
- // Apply the desired cell alignment.
- var cellAlignment = KEY_PROPERTIES[key].cellAlignment;
- if (cellAlignment)
- td.align = cellAlignment;
-
- if (key == KEY_SOURCE_LOCATION) {
- // Linkify the source column so it jumps to the source code. This doesn't
- // take into account the particular code this build was compiled from, or
- // local edits to source. It should however work correctly for top of tree
- // builds.
- var m = /^(.*) \[(\d+)\]$/.exec(text);
- if (m) {
- var filepath = m[1];
- var filename = getFilenameFromPath(filepath);
- var linenumber = m[2];
-
- var link = addNode(td, 'a', filename + ' [' + linenumber + ']');
-
- link.href = 'https://code.google.com/p/chromium/codesearch#search/&q=' +
- encodeURIComponent(filename) + ':' + linenumber +
- '&sq=package:chromium&type=cs';
- link.target = '_blank';
- return;
- }
- }
-
- // String values can get pretty long. If the string contains no spaces, then
- // CSS fails to wrap it, and it overflows the cell causing the table to get
- // really big. We solve this using a hack: insert a <wbr> element after
- // every single character. This will allow the rendering engine to wrap the
- // value, and hence avoid it overflowing!
- var kMinLengthBeforeWrap = 20;
-
- addText(td, text.substr(0, kMinLengthBeforeWrap));
- for (var i = kMinLengthBeforeWrap; i < text.length; ++i) {
- addNode(td, 'wbr');
- addText(td, text.substr(i, 1));
- }
- }
-
- // --------------------------------------------------------------------------
- // Helper code for handling the sort and grouping dropdowns.
- // --------------------------------------------------------------------------
-
- function addOptionsForGroupingSelect(select) {
- // Add "no group" choice.
- addNode(select, 'option', '---').value = '';
-
- for (var i = 0; i < GROUPING_DROPDOWN_CHOICES.length; ++i) {
- var key = GROUPING_DROPDOWN_CHOICES[i];
- var option = addNode(select, 'option', getNameForKey(key));
- option.value = key;
- }
- }
-
- function addOptionsForSortingSelect(select) {
- // Add "no sort" choice.
- addNode(select, 'option', '---').value = '';
-
- // Add a divider.
- addNode(select, 'optgroup').label = '';
-
- for (var i = 0; i < SORT_DROPDOWN_CHOICES.length; ++i) {
- var key = SORT_DROPDOWN_CHOICES[i];
- addNode(select, 'option', getNameForKey(key)).value = key;
- }
-
- // Add a divider.
- addNode(select, 'optgroup').label = '';
-
- // Add the same options, but for descending.
- for (var i = 0; i < SORT_DROPDOWN_CHOICES.length; ++i) {
- var key = SORT_DROPDOWN_CHOICES[i];
- var n = addNode(select, 'option', getNameForKey(key) + ' (DESC)');
- n.value = reverseSortKey(key);
- }
- }
-
- /**
- * Helper function used to update the sorting and grouping lists after a
- * dropdown changes.
- */
- function updateKeyListFromDropdown(list, i, select) {
- // Update the list.
- if (i < list.length) {
- list[i] = select.value;
- } else {
- list.push(select.value);
- }
-
- // Normalize the list, so setting 'none' as primary zeros out everything
- // else.
- for (var i = 0; i < list.length; ++i) {
- if (list[i] == '') {
- list.splice(i, list.length - i);
- break;
- }
- }
- }
-
- /**
- * Comparator for property |key|, having values |value1| and |value2|.
- * If the key has defined a custom comparator use it. Otherwise use a
- * default "less than" comparison.
- */
- function compareValuesForKey(key, value1, value2) {
- var comparator = KEY_PROPERTIES[key].comparator;
- if (comparator)
- return comparator(value1, value2);
- return simpleCompare(value1, value2);
- }
-
- function reverseSortKey(key) {
- return -key;
- }
-
- function sortKeyIsReversed(key) {
- return key < 0;
- }
-
- function sortKeysMatch(key1, key2) {
- return Math.abs(key1) == Math.abs(key2);
- }
-
- function getKeysForCheckedBoxes(checkboxes) {
- var keys = [];
- for (var k in checkboxes) {
- if (checkboxes[k].checked)
- keys.push(k);
- }
- return keys;
- }
-
- // --------------------------------------------------------------------------
-
- /**
- * @constructor
- */
- function MainView() {
- // Make sure we have a definition for each key.
- for (var k = BEGIN_KEY; k < END_KEY; ++k) {
- if (!KEY_PROPERTIES[k])
- throw 'KEY_PROPERTIES[] not defined for key: ' + k;
- }
-
- this.init_();
- }
-
- MainView.prototype = {
- addDataToSnapshot: function(data) {
- // TODO(eroman): We need to know which snapshot this data belongs to!
- // For now we assume it is the most recent snapshot.
- var snapshotIndex = this.snapshots_.length - 1;
-
- var snapshot = this.snapshots_[snapshotIndex];
-
- var pid = data.process_id;
- var ptype = data.process_type;
-
- // Save the browser's representation of the data
- snapshot.origData.push(data);
-
- // Augment each data row with the process information.
- var rows = data.list;
- for (var i = 0; i < rows.length; ++i) {
- // Transform the data from a dictionary to an array. This internal
- // representation is more compact and faster to access.
- var origRow = rows[i];
- var newRow = [];
-
- newRow[KEY_PROCESS_ID] = pid;
- newRow[KEY_PROCESS_TYPE] = ptype;
-
- // Copy over the known properties which have a 1:1 mapping with JSON.
- for (var k = BEGIN_KEY; k < END_KEY; ++k) {
- var inputJsonKey = KEY_PROPERTIES[k].inputJsonKey;
- if (inputJsonKey != undefined) {
- newRow[k] = getPropertyByPath(origRow, inputJsonKey);
- }
- }
-
- if (newRow[KEY_COUNT] == 0) {
- // When resetting the data, it is possible for the backend to give us
- // counts of "0". There is no point adding these rows (in fact they
- // will cause us to do divide by zeros when calculating averages and
- // stuff), so we skip past them.
- continue;
- }
-
- // Add our computed properties.
- augmentDataRow(newRow);
-
- snapshot.flatData.push(newRow);
- }
-
- if (!arrayToSet(this.getSelectedSnapshotIndexes_())[snapshotIndex]) {
- // Optimization: If this snapshot is not a data dependency for the
- // current display, then don't bother updating anything.
- return;
- }
-
- // We may end up calling addDataToSnapshot_() repeatedly (once for each
- // process). To avoid this from slowing us down we do bulk updates on a
- // timer.
- this.updateMergedDataSoon_();
- },
-
- updateMergedDataSoon_: function() {
- if (this.updateMergedDataPending_) {
- // If a delayed task has already been posted to re-merge the data,
- // then we don't need to do anything extra.
- return;
- }
-
- // Otherwise schedule updateMergedData_() to be called later. We want it
- // to be called no more than once every PROCESS_DATA_DELAY_MS
- // milliseconds.
-
- if (this.lastUpdateMergedDataTime_ == undefined)
- this.lastUpdateMergedDataTime_ = 0;
-
- var timeSinceLastMerge = getTimeMillis() - this.lastUpdateMergedDataTime_;
- var timeToWait = Math.max(0, PROCESS_DATA_DELAY_MS - timeSinceLastMerge);
-
- var functionToRun = function() {
- // Do the actual update.
- this.updateMergedData_();
- // Keep track of when we last ran.
- this.lastUpdateMergedDataTime_ = getTimeMillis();
- this.updateMergedDataPending_ = false;
- }.bind(this);
-
- this.updateMergedDataPending_ = true;
- window.setTimeout(functionToRun, timeToWait);
- },
-
- /**
- * Returns a list of the currently selected snapshots. This list is
- * guaranteed to be of length 1 or 2.
- */
- getSelectedSnapshotIndexes_: function() {
- var indexes = this.getSelectedSnapshotBoxes_();
- for (var i = 0; i < indexes.length; ++i)
- indexes[i] = indexes[i].__index;
- return indexes;
- },
-
- /**
- * Same as getSelectedSnapshotIndexes_(), only it returns the actual
- * checkbox input DOM nodes rather than the snapshot ID.
- */
- getSelectedSnapshotBoxes_: function() {
- // Figure out which snapshots to use for our data.
- var boxes = [];
- for (var i = 0; i < this.snapshots_.length; ++i) {
- var box = this.getSnapshotCheckbox_(i);
- if (box.checked)
- boxes.push(box);
- }
- return boxes;
- },
-
- /**
- * Re-draw the description that explains which snapshots are currently
- * selected (if two snapshots were selected we explain that the *difference*
- * between them is being displayed).
- */
- updateSnapshotSelectionSummaryDiv_: function() {
- var summaryDiv = $(SNAPSHOT_SELECTION_SUMMARY_ID);
-
- var selectedSnapshots = this.getSelectedSnapshotIndexes_();
- if (selectedSnapshots.length == 0) {
- // This can occur during an attempt to load a file or following file
- // load failure. We just ignore it and move on.
- } else if (selectedSnapshots.length == 1) {
- // If only one snapshot is chosen then we will display that snapshot's
- // data in its entirety.
- this.flatData_ = this.snapshots_[selectedSnapshots[0]].flatData;
-
- // Don't bother displaying any text when just 1 snapshot is selected,
- // since it is obvious what this should do.
- summaryDiv.innerText = '';
- } else if (selectedSnapshots.length == 2) {
- // Otherwise if two snapshots were chosen, show the difference between
- // them.
- var snapshot1 = this.snapshots_[selectedSnapshots[0]];
- var snapshot2 = this.snapshots_[selectedSnapshots[1]];
-
- var timeDeltaInSeconds =
- ((snapshot2.time - snapshot1.time) / 1000).toFixed(0);
-
- // Explain that what is being shown is the difference between two
- // snapshots.
- summaryDiv.innerText = 'Showing the difference between snapshots #' +
- selectedSnapshots[0] + ' and #' + selectedSnapshots[1] + ' (' +
- timeDeltaInSeconds + ' seconds worth of data)';
- } else {
- // This shouldn't be possible...
- throw 'Unexpected number of selected snapshots';
- }
- },
-
- updateMergedData_: function() {
- // Retrieve the merge options.
- var mergeColumns = this.getMergeColumns_();
- var shouldMergeSimilarThreads = this.shouldMergeSimilarThreads_();
-
- var selectedSnapshots = this.getSelectedSnapshotIndexes_();
-
- // We do merges a bit differently depending if we are displaying the diffs
- // between two snapshots, or just displaying a single snapshot.
- if (selectedSnapshots.length == 1) {
- var snapshot = this.snapshots_[selectedSnapshots[0]];
- this.mergedData_ = mergeRows(
- snapshot.flatData, mergeColumns, shouldMergeSimilarThreads, false);
-
- } else if (selectedSnapshots.length == 2) {
- var snapshot1 = this.snapshots_[selectedSnapshots[0]];
- var snapshot2 = this.snapshots_[selectedSnapshots[1]];
-
- // Merge the data for snapshot1.
- var mergedRows1 = mergeRows(
- snapshot1.flatData, mergeColumns, shouldMergeSimilarThreads, true);
-
- // Merge the data for snapshot2.
- var mergedRows2 = mergeRows(
- snapshot2.flatData, mergeColumns, shouldMergeSimilarThreads, true);
-
- // Do a diff between the two snapshots.
- this.mergedData_ =
- subtractSnapshots(mergedRows1, mergedRows2, mergeColumns);
- } else {
- throw 'Unexpected number of selected snapshots';
- }
-
- // Recompute filteredData_ (since it is derived from mergedData_)
- this.updateFilteredData_();
- },
-
- updateFilteredData_: function() {
- // Recompute filteredData_.
- this.filteredData_ = [];
- var filterFunc = this.getFilterFunction_();
- for (var i = 0; i < this.mergedData_.length; ++i) {
- var r = this.mergedData_[i];
- if (!filterFunc(r)) {
- // Not matched by our filter, discard.
- continue;
- }
- this.filteredData_.push(r);
- }
-
- // Recompute groupedData_ (since it is derived from filteredData_)
- this.updateGroupedData_();
- },
-
- updateGroupedData_: function() {
- // Recompute groupedData_.
- var groupKeyToData = {};
- var entryToGroupKeyFunc = this.getGroupingFunction_();
- for (var i = 0; i < this.filteredData_.length; ++i) {
- var r = this.filteredData_[i];
-
- var groupKey = entryToGroupKeyFunc(r);
-
- var groupData = groupKeyToData[groupKey];
- if (!groupData) {
- groupData = {
- key: JSON.parse(groupKey),
- aggregates: initializeAggregates(ALL_KEYS),
- rows: [],
- };
- groupKeyToData[groupKey] = groupData;
- }
-
- // Add the row to our list.
- groupData.rows.push(r);
-
- // Update aggregates for each column.
- consumeAggregates(groupData.aggregates, r);
- }
- this.groupedData_ = groupKeyToData;
-
- // Figure out a display order for the groups themselves.
- this.sortedGroupKeys_ = getDictionaryKeys(groupKeyToData);
- this.sortedGroupKeys_.sort(this.getGroupSortingFunction_());
-
- // Sort the group data.
- this.sortGroupedData_();
- },
-
- sortGroupedData_: function() {
- var sortingFunc = this.getSortingFunction_();
- for (var k in this.groupedData_)
- this.groupedData_[k].rows.sort(sortingFunc);
-
- // Every cached data dependency is now up to date, all that is left is
- // to actually draw the result.
- this.redrawData_();
- },
-
- getVisibleColumnKeys_: function() {
- // Figure out what columns to include, based on the selected checkboxes.
- var columns = this.getSelectionColumns_();
- columns = columns.slice(0);
-
- // Eliminate columns which we are merging on.
- deleteValuesFromArray(columns, this.getMergeColumns_());
-
- // Eliminate columns which we are grouped on.
- if (this.sortedGroupKeys_.length > 0) {
- // The grouping will be the the same for each so just pick the first.
- var randomGroupKey = this.groupedData_[this.sortedGroupKeys_[0]].key;
-
- // The grouped properties are going to be the same for each row in our,
- // table, so avoid drawing them in our table!
- var keysToExclude = [];
-
- for (var i = 0; i < randomGroupKey.length; ++i)
- keysToExclude.push(randomGroupKey[i].key);
- deleteValuesFromArray(columns, keysToExclude);
- }
-
- // If we are currently showing a "diff", hide the max columns, since we
- // are not populating it correctly. See the TODO at the top of this file.
- if (this.getSelectedSnapshotIndexes_().length > 1)
- deleteValuesFromArray(columns, [KEY_MAX_RUN_TIME, KEY_MAX_QUEUE_TIME]);
-
- return columns;
- },
-
- redrawData_: function() {
- // Clear the results div, sine we may be overwriting older data.
- var parent = $(RESULTS_DIV_ID);
- parent.innerHTML = '';
-
- var columns = this.getVisibleColumnKeys_();
-
- // Draw each group.
- for (var i = 0; i < this.sortedGroupKeys_.length; ++i) {
- var k = this.sortedGroupKeys_[i];
- this.drawGroup_(parent, k, columns);
- }
- },
-
- /**
- * Renders the information for a particular group.
- */
- drawGroup_: function(parent, groupKey, columns) {
- var groupData = this.groupedData_[groupKey];
-
- var div = addNode(parent, 'div');
- div.className = 'group-container';
-
- this.drawGroupTitle_(div, groupData.key);
-
- var table = addNode(div, 'table');
-
- this.drawDataTable_(table, groupData, columns, groupKey);
- },
-
- /**
- * Draws a title into |parent| that describes |groupKey|.
- */
- drawGroupTitle_: function(parent, groupKey) {
- if (groupKey.length == 0) {
- // Empty group key means there was no grouping.
- return;
- }
-
- var parent = addNode(parent, 'div');
- parent.className = 'group-title-container';
-
- // Each component of the group key represents the "key=value" constraint
- // for this group. Show these as an AND separated list.
- for (var i = 0; i < groupKey.length; ++i) {
- if (i > 0)
- addNode(parent, 'i', ' and ');
- var e = groupKey[i];
- addNode(parent, 'b', getNameForKey(e.key) + ' = ');
- addNode(parent, 'span', e.value);
- }
- },
-
- /**
- * Renders a table which summarizes all |column| fields for |data|.
- */
- drawDataTable_: function(table, data, columns, groupKey) {
- table.className = 'results-table';
- var thead = addNode(table, 'thead');
- var tbody = addNode(table, 'tbody');
-
- var displaySettings = this.getGroupDisplaySettings_(groupKey);
- var limit = displaySettings.limit;
-
- this.drawAggregateRow_(thead, data.aggregates, columns);
- this.drawTableHeader_(thead, columns);
- this.drawTableBody_(tbody, data.rows, columns, limit);
- this.drawTruncationRow_(
- tbody, data.rows.length, limit, columns.length, groupKey);
- },
-
- drawTableHeader_: function(thead, columns) {
- var tr = addNode(thead, 'tr');
- for (var i = 0; i < columns.length; ++i) {
- var key = columns[i];
- var th = addNode(tr, 'th', getNameForKey(key));
- th.onclick = this.onClickColumn_.bind(this, key);
-
- // Draw an indicator if we are currently sorted on this column.
- // TODO(eroman): Should use an icon instead of asterisk!
- for (var j = 0; j < this.currentSortKeys_.length; ++j) {
- if (sortKeysMatch(this.currentSortKeys_[j], key)) {
- var sortIndicator = addNode(th, 'span', '*');
- sortIndicator.style.color = 'red';
- if (sortKeyIsReversed(this.currentSortKeys_[j])) {
- // Use double-asterisk for descending columns.
- addText(sortIndicator, '*');
- }
- break;
- }
- }
- }
- },
-
- drawTableBody_: function(tbody, rows, columns, limit) {
- for (var i = 0; i < rows.length && i < limit; ++i) {
- var e = rows[i];
-
- var tr = addNode(tbody, 'tr');
-
- for (var c = 0; c < columns.length; ++c) {
- var key = columns[c];
- var value = e[key];
-
- var td = addNode(tr, 'td');
- drawValueToCell(td, key, value);
- }
- }
- },
-
- /**
- * Renders a row that describes all the aggregate values for |columns|.
- */
- drawAggregateRow_: function(tbody, aggregates, columns) {
- var tr = addNode(tbody, 'tr');
- tr.className = 'aggregator-row';
-
- for (var i = 0; i < columns.length; ++i) {
- var key = columns[i];
- var td = addNode(tr, 'td');
-
- // Most of our outputs are numeric, so we want to align them to the
- // right. However for the unique counts we will center.
- if (KEY_PROPERTIES[key].aggregator == UniquifyAggregator) {
- td.align = 'center';
- } else {
- td.align = 'right';
- }
-
- var aggregator = aggregates[key];
- if (aggregator)
- td.innerText = aggregator.getValueAsText();
- }
- },
-
- /**
- * Renders a row which describes how many rows the table has, how many are
- * currently hidden, and a set of buttons to show more.
- */
- drawTruncationRow_: function(tbody, numRows, limit, numColumns, groupKey) {
- var numHiddenRows = Math.max(numRows - limit, 0);
- var numVisibleRows = numRows - numHiddenRows;
-
- var tr = addNode(tbody, 'tr');
- tr.className = 'truncation-row';
- var td = addNode(tr, 'td');
- td.colSpan = numColumns;
-
- addText(td, numRows + ' rows');
- if (numHiddenRows > 0) {
- var s = addNode(td, 'span', ' (' + numHiddenRows + ' hidden) ');
- s.style.color = 'red';
- }
-
- if (numVisibleRows > LIMIT_INCREMENT) {
- addNode(td, 'button', 'Show less').onclick =
- this.changeGroupDisplayLimit_.bind(
- this, groupKey, -LIMIT_INCREMENT);
- }
- if (numVisibleRows > 0) {
- addNode(td, 'button', 'Show none').onclick =
- this.changeGroupDisplayLimit_.bind(this, groupKey, -Infinity);
- }
-
- if (numHiddenRows > 0) {
- addNode(td, 'button', 'Show more').onclick =
- this.changeGroupDisplayLimit_.bind(this, groupKey, LIMIT_INCREMENT);
- addNode(td, 'button', 'Show all').onclick =
- this.changeGroupDisplayLimit_.bind(this, groupKey, Infinity);
- }
- },
-
- /**
- * Adjusts the row limit for group |groupKey| by |delta|.
- */
- changeGroupDisplayLimit_: function(groupKey, delta) {
- // Get the current settings for this group.
- var settings = this.getGroupDisplaySettings_(groupKey, true);
-
- // Compute the adjusted limit.
- var newLimit = settings.limit;
- var totalNumRows = this.groupedData_[groupKey].rows.length;
- newLimit = Math.min(totalNumRows, newLimit);
- newLimit += delta;
- newLimit = Math.max(0, newLimit);
-
- // Update the settings with the new limit.
- settings.limit = newLimit;
-
- // TODO(eroman): It isn't necessary to redraw *all* the data. Really we
- // just need to insert the missing rows (everything else stays the same)!
- this.redrawData_();
- },
-
- /**
- * Returns the rendering settings for group |groupKey|. This includes things
- * like how many rows to display in the table.
- */
- getGroupDisplaySettings_: function(groupKey, opt_create) {
- var settings = this.groupDisplaySettings_[groupKey];
- if (!settings) {
- // If we don't have any settings for this group yet, create some
- // default ones.
- if (groupKey == '[]') {
- // (groupKey of '[]' is what we use for ungrouped data).
- settings = {limit: INITIAL_UNGROUPED_ROW_LIMIT};
- } else {
- settings = {limit: INITIAL_GROUP_ROW_LIMIT};
- }
- if (opt_create)
- this.groupDisplaySettings_[groupKey] = settings;
- }
- return settings;
- },
-
- init_: function() {
- this.snapshots_ = [];
-
- // Start fetching the data from the browser; this will be our snapshot #0.
- this.takeSnapshot_();
-
- // Data goes through the following pipeline:
- // (1) Raw data received from browser, and transformed into our own
- // internal row format (where properties are indexed by KEY_*
- // constants.)
- // (2) We "augment" each row by adding some extra computed columns
- // (like averages).
- // (3) The rows are merged using current merge settings.
- // (4) The rows that don't match current search expression are
- // tossed out.
- // (5) The rows are organized into "groups" based on current settings,
- // and aggregate values are computed for each resulting group.
- // (6) The rows within each group are sorted using current settings.
- // (7) The grouped rows are drawn to the screen.
- this.mergedData_ = [];
- this.filteredData_ = [];
- this.groupedData_ = {};
- this.sortedGroupKeys_ = [];
-
- this.groupDisplaySettings_ = {};
-
- this.fillSelectionCheckboxes_($(COLUMN_TOGGLES_CONTAINER_ID));
- this.fillMergeCheckboxes_($(COLUMN_MERGE_TOGGLES_CONTAINER_ID));
-
- $(FILTER_SEARCH_ID).onsearch = this.onChangedFilter_.bind(this);
-
- this.currentSortKeys_ = INITIAL_SORT_KEYS.slice(0);
- this.currentGroupingKeys_ = INITIAL_GROUP_KEYS.slice(0);
-
- this.fillGroupingDropdowns_();
- this.fillSortingDropdowns_();
-
- $(EDIT_COLUMNS_LINK_ID).onclick =
- toggleNodeDisplay.bind(null, $(EDIT_COLUMNS_ROW));
-
- $(TOGGLE_SNAPSHOTS_LINK_ID).onclick =
- toggleNodeDisplay.bind(null, $(SNAPSHOTS_ROW));
-
- $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).onchange =
- this.onMergeSimilarThreadsCheckboxChanged_.bind(this);
-
- $(TAKE_SNAPSHOT_BUTTON_ID).onclick = this.takeSnapshot_.bind(this);
-
- $(SAVE_SNAPSHOTS_BUTTON_ID).onclick = this.saveSnapshots_.bind(this);
- $(SNAPSHOT_FILE_LOADER_ID).onchange = this.loadFileChanged_.bind(this);
- },
-
- takeSnapshot_: function() {
- // Start a new empty snapshot. Make note of the current time, so we know
- // when the snapshot was taken.
- this.snapshots_.push({flatData: [], origData: [], time: getTimeMillis()});
-
- // Update the UI to reflect the new snapshot.
- this.addSnapshotToList_(this.snapshots_.length - 1);
-
- // Ask the browser for the profiling data. We will receive the data
- // later through a callback to addDataToSnapshot_().
- g_browserBridge.sendGetData();
- },
-
- saveSnapshots_: function() {
- var snapshots = [];
- for (var i = 0; i < this.snapshots_.length; ++i) {
- snapshots.push({
- data: this.snapshots_[i].origData,
- timestamp: Math.floor(this.snapshots_[i].time / 1000)
- });
- }
-
- var dump = {
- 'userAgent': navigator.userAgent,
- 'version': 1,
- 'snapshots': snapshots
- };
-
- var dumpText = JSON.stringify(dump, null, ' ');
- var textBlob =
- new Blob([dumpText], {type: 'octet/stream', endings: 'native'});
- var blobUrl = window.URL.createObjectURL(textBlob);
- $(DOWNLOAD_ANCHOR_ID).href = blobUrl;
- $(DOWNLOAD_ANCHOR_ID).click();
- },
-
- loadFileChanged_: function() {
- this.loadSnapshots_($(SNAPSHOT_FILE_LOADER_ID).files[0]);
- },
-
- loadSnapshots_: function(file) {
- if (file) {
- var fileReader = new FileReader();
-
- fileReader.onload = this.onLoadSnapshotsFile_.bind(this, file);
- fileReader.onerror = this.onLoadSnapshotsFileError_.bind(this, file);
-
- fileReader.readAsText(file);
- }
- },
-
- onLoadSnapshotsFile_: function(file, event) {
- try {
- var parsed = null;
- parsed = JSON.parse(event.target.result);
-
- if (parsed.version != 1) {
- throw new Error('Unrecognized version: ' + parsed.version);
- }
-
- if (parsed.snapshots.length < 1) {
- throw new Error('File contains no data');
- }
-
- this.displayLoadedFile_(file, parsed);
- this.hideFileLoadError_();
- } catch (error) {
- this.displayFileLoadError_('File load failure: ' + error.message);
- }
- },
-
- clearExistingSnapshots_: function() {
- var tbody = $('snapshots-tbody');
- this.snapshots_ = [];
- tbody.innerHTML = '';
- this.updateMergedDataSoon_();
- },
-
- displayLoadedFile_: function(file, content) {
- this.clearExistingSnapshots_();
- $(TAKE_SNAPSHOT_BUTTON_ID).disabled = true;
- $(SAVE_SNAPSHOTS_BUTTON_ID).disabled = true;
-
- if (content.snapshots.length > 1) {
- setNodeDisplay($(SNAPSHOTS_ROW), true);
- }
-
- for (var i = 0; i < content.snapshots.length; ++i) {
- var snapshot = content.snapshots[i];
- this.snapshots_.push(
- {flatData: [], origData: [], time: snapshot.timestamp * 1000});
- this.addSnapshotToList_(this.snapshots_.length - 1);
- var snapshotData = snapshot.data;
- for (var j = 0; j < snapshotData.length; ++j) {
- this.addDataToSnapshot(snapshotData[j]);
- }
- }
- this.redrawData_();
- },
-
- onLoadSnapshotsFileError_: function(file, filedata) {
- this.displayFileLoadError_('Error loading ' + file.name);
- },
-
- displayFileLoadError_: function(message) {
- $(LOAD_ERROR_ID).textContent = message;
- $(LOAD_ERROR_ID).hidden = false;
- },
-
- hideFileLoadError_: function() {
- $(LOAD_ERROR_ID).textContent = '';
- $(LOAD_ERROR_ID).hidden = true;
- },
-
- getSnapshotCheckbox_: function(i) {
- return $(this.getSnapshotCheckboxId_(i));
- },
-
- getSnapshotCheckboxId_: function(i) {
- return 'snapshotCheckbox-' + i;
- },
-
- addSnapshotToList_: function(i) {
- var tbody = $('snapshots-tbody');
-
- var tr = addNode(tbody, 'tr');
-
- var id = this.getSnapshotCheckboxId_(i);
-
- var checkboxCell = addNode(tr, 'td');
- var checkbox = addNode(checkboxCell, 'input');
- checkbox.type = 'checkbox';
- checkbox.id = id;
- checkbox.__index = i;
- checkbox.onclick = this.onSnapshotCheckboxChanged_.bind(this);
-
- addNode(tr, 'td', '#' + i);
-
- var labelCell = addNode(tr, 'td');
- var l = addNode(labelCell, 'label');
-
- var dateString = new Date(this.snapshots_[i].time).toLocaleString();
- addText(l, dateString);
- l.htmlFor = id;
-
- // If we are on snapshot 0, make it the default.
- if (i == 0) {
- checkbox.checked = true;
- checkbox.__time = getTimeMillis();
- this.updateSnapshotCheckboxStyling_();
- }
- },
-
- updateSnapshotCheckboxStyling_: function() {
- for (var i = 0; i < this.snapshots_.length; ++i) {
- var checkbox = this.getSnapshotCheckbox_(i);
- checkbox.parentNode.parentNode.className =
- checkbox.checked ? 'selected-snapshot' : '';
- }
- },
-
- onSnapshotCheckboxChanged_: function(event) {
- // Keep track of when we clicked this box (for when we need to uncheck
- // older boxes).
- event.target.__time = getTimeMillis();
-
- // Find all the checked boxes. Either 1 or 2 can be checked. If a third
- // was just checked, then uncheck one of the earlier ones so we only have
- // 2.
- var checked = this.getSelectedSnapshotBoxes_();
- checked.sort(function(a, b) {
- return b.__time - a.__time;
- });
- if (checked.length > 2) {
- for (var i = 2; i < checked.length; ++i)
- checked[i].checked = false;
- checked.length = 2;
- }
-
- // We should always have at least 1 selection. Prevent the user from
- // unselecting the final box.
- if (checked.length == 0)
- event.target.checked = true;
-
- this.updateSnapshotCheckboxStyling_();
- this.updateSnapshotSelectionSummaryDiv_();
-
- // Recompute mergedData_ (since it is derived from selected snapshots).
- this.updateMergedData_();
- },
-
- fillSelectionCheckboxes_: function(parent) {
- this.selectionCheckboxes_ = {};
-
- var onChangeFunc = this.onSelectCheckboxChanged_.bind(this);
-
- for (var i = 0; i < ALL_TABLE_COLUMNS.length; ++i) {
- var key = ALL_TABLE_COLUMNS[i];
- var checkbox = addLabeledCheckbox(parent, getNameForKey(key));
- checkbox.checked = true;
- checkbox.onchange = onChangeFunc;
- addText(parent, ' ');
- this.selectionCheckboxes_[key] = checkbox;
- }
-
- for (var i = 0; i < INITIALLY_HIDDEN_KEYS.length; ++i) {
- this.selectionCheckboxes_[INITIALLY_HIDDEN_KEYS[i]].checked = false;
- }
- },
-
- getSelectionColumns_: function() {
- return getKeysForCheckedBoxes(this.selectionCheckboxes_);
- },
-
- getMergeColumns_: function() {
- return getKeysForCheckedBoxes(this.mergeCheckboxes_);
- },
-
- shouldMergeSimilarThreads_: function() {
- return $(MERGE_SIMILAR_THREADS_CHECKBOX_ID).checked;
- },
-
- fillMergeCheckboxes_: function(parent) {
- this.mergeCheckboxes_ = {};
-
- var onChangeFunc = this.onMergeCheckboxChanged_.bind(this);
-
- for (var i = 0; i < MERGEABLE_KEYS.length; ++i) {
- var key = MERGEABLE_KEYS[i];
- var checkbox = addLabeledCheckbox(parent, getNameForKey(key));
- checkbox.onchange = onChangeFunc;
- addText(parent, ' ');
- this.mergeCheckboxes_[key] = checkbox;
- }
-
- for (var i = 0; i < INITIALLY_MERGED_KEYS.length; ++i) {
- this.mergeCheckboxes_[INITIALLY_MERGED_KEYS[i]].checked = true;
- }
- },
-
- fillGroupingDropdowns_: function() {
- var parent = $(GROUP_BY_CONTAINER_ID);
- parent.innerHTML = '';
-
- for (var i = 0; i <= this.currentGroupingKeys_.length; ++i) {
- // Add a dropdown.
- var select = addNode(parent, 'select');
- select.onchange = this.onChangedGrouping_.bind(this, select, i);
-
- addOptionsForGroupingSelect(select);
-
- if (i < this.currentGroupingKeys_.length) {
- var key = this.currentGroupingKeys_[i];
- setSelectedOptionByValue(select, key);
- }
- }
- },
-
- fillSortingDropdowns_: function() {
- var parent = $(SORT_BY_CONTAINER_ID);
- parent.innerHTML = '';
-
- for (var i = 0; i <= this.currentSortKeys_.length; ++i) {
- // Add a dropdown.
- var select = addNode(parent, 'select');
- select.onchange = this.onChangedSorting_.bind(this, select, i);
-
- addOptionsForSortingSelect(select);
-
- if (i < this.currentSortKeys_.length) {
- var key = this.currentSortKeys_[i];
- setSelectedOptionByValue(select, key);
- }
- }
- },
-
- onChangedGrouping_: function(select, i) {
- updateKeyListFromDropdown(this.currentGroupingKeys_, i, select);
- this.fillGroupingDropdowns_();
- this.updateGroupedData_();
- },
-
- onChangedSorting_: function(select, i) {
- updateKeyListFromDropdown(this.currentSortKeys_, i, select);
- this.fillSortingDropdowns_();
- this.sortGroupedData_();
- },
-
- onSelectCheckboxChanged_: function() {
- this.redrawData_();
- },
-
- onMergeCheckboxChanged_: function() {
- this.updateMergedData_();
- },
-
- onMergeSimilarThreadsCheckboxChanged_: function() {
- this.updateMergedData_();
- },
-
- onChangedFilter_: function() {
- this.updateFilteredData_();
- },
-
- /**
- * When left-clicking a column, change the primary sort order to that
- * column. If we were already sorted on that column then reverse the order.
- *
- * When alt-clicking, add a secondary sort column. Similarly, if
- * alt-clicking a column which was already being sorted on, reverse its
- * order.
- */
- onClickColumn_: function(key, event) {
- // If this property wants to start off in descending order rather then
- // ascending, flip it.
- if (KEY_PROPERTIES[key].sortDescending)
- key = reverseSortKey(key);
-
- // Scan through our sort order and see if we are already sorted on this
- // key. If so, reverse that sort ordering.
- var foundIndex = -1;
- for (var i = 0; i < this.currentSortKeys_.length; ++i) {
- var curKey = this.currentSortKeys_[i];
- if (sortKeysMatch(curKey, key)) {
- this.currentSortKeys_[i] = reverseSortKey(curKey);
- foundIndex = i;
- break;
- }
- }
-
- if (event.altKey) {
- if (foundIndex == -1) {
- // If we weren't already sorted on the column that was alt-clicked,
- // then add it to our sort.
- this.currentSortKeys_.push(key);
- }
- } else {
- if (foundIndex != 0 ||
- !sortKeysMatch(this.currentSortKeys_[foundIndex], key)) {
- // If the column we left-clicked wasn't already our primary column,
- // make it so.
- this.currentSortKeys_ = [key];
- } else {
- // If the column we left-clicked was already our primary column (and
- // we just reversed it), remove any secondary sorts.
- this.currentSortKeys_.length = 1;
- }
- }
-
- this.fillSortingDropdowns_();
- this.sortGroupedData_();
- },
-
- getSortingFunction_: function() {
- var sortKeys = this.currentSortKeys_.slice(0);
-
- // Eliminate the empty string keys (which means they were unspecified).
- deleteValuesFromArray(sortKeys, ['']);
-
- // If no sort is specified, use our default sort.
- if (sortKeys.length == 0)
- sortKeys = [DEFAULT_SORT_KEYS];
-
- return function(a, b) {
- for (var i = 0; i < sortKeys.length; ++i) {
- var key = Math.abs(sortKeys[i]);
- var factor = sortKeys[i] < 0 ? -1 : 1;
-
- var propA = a[key];
- var propB = b[key];
-
- var comparison = compareValuesForKey(key, propA, propB);
- comparison *= factor; // Possibly reverse the ordering.
-
- if (comparison != 0)
- return comparison;
- }
-
- // Tie breaker.
- return simpleCompare(JSON.stringify(a), JSON.stringify(b));
- };
- },
-
- getGroupSortingFunction_: function() {
- return function(a, b) {
- var groupKey1 = JSON.parse(a);
- var groupKey2 = JSON.parse(b);
-
- for (var i = 0; i < groupKey1.length; ++i) {
- var comparison = compareValuesForKey(
- groupKey1[i].key, groupKey1[i].value, groupKey2[i].value);
-
- if (comparison != 0)
- return comparison;
- }
-
- // Tie breaker.
- return simpleCompare(a, b);
- };
- },
-
- getFilterFunction_: function() {
- var searchStr = $(FILTER_SEARCH_ID).value;
-
- // Normalize the search expression.
- searchStr = trimWhitespace(searchStr);
- searchStr = searchStr.toLowerCase();
-
- return function(x) {
- // Match everything when there was no filter.
- if (searchStr == '')
- return true;
-
- // Treat the search text as a LOWERCASE substring search.
- for (var k = BEGIN_KEY; k < END_KEY; ++k) {
- var propertyText = getTextValueForProperty(k, x[k]);
- if (propertyText.toLowerCase().indexOf(searchStr) != -1)
- return true;
- }
-
- return false;
- };
- },
-
- getGroupingFunction_: function() {
- var groupings = this.currentGroupingKeys_.slice(0);
-
- // Eliminate the empty string groupings (which means they were
- // unspecified).
- deleteValuesFromArray(groupings, ['']);
-
- // Eliminate duplicate primary/secondary group by directives, since they
- // are redundant.
- deleteDuplicateStringsFromArray(groupings);
-
- return function(e) {
- var groupKey = [];
-
- for (var i = 0; i < groupings.length; ++i) {
- var entry = {key: groupings[i], value: e[groupings[i]]};
- groupKey.push(entry);
- }
-
- return JSON.stringify(groupKey);
- };
- },
- };
-
- return MainView;
-})();
diff --git a/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
index 5f61c4745d6..4fd285afc89 100644
--- a/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
+++ b/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -8,7 +8,7 @@
##
## Top level settings
##
-version_id: 12
+version_id: 13
sampled_ping_probability: 0.01
default_file_type {
uma_value: 18
@@ -2217,6 +2217,36 @@ file_types {
}
}
file_types {
+ # Similar to "html". Added for https://crbug.com/762702
+ extension: "xht"
+ uma_value: 286
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Similar to "html". Added for https://crbug.com/762702
+ extension: "xhtm"
+ uma_value: 287
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
+ # Similar to "html". Added for https://crbug.com/762702
+ extension: "xhtml"
+ uma_value: 288
+ ping_setting: FULL_PING
+ platform_settings {
+ danger_level: NOT_DANGEROUS
+ auto_open_hint: ALLOW_AUTO_OPEN
+ }
+}
+file_types {
# Microsoft Exchange Public Folder Shortcut
extension: "xnk"
uma_value: 127
diff --git a/chromium/chrome/browser/resources/settings/BUILD.gn b/chromium/chrome/browser/resources/settings/BUILD.gn
index af4bf1d57d2..cd940c9f689 100644
--- a/chromium/chrome/browser/resources/settings/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/BUILD.gn
@@ -1,11 +1,11 @@
-import("../vulcanize.gni")
+import("../optimize_webui.gni")
import("//tools/grit/grit_rule.gni")
import("//chrome/common/features.gni")
settings_pak_file = "settings_resources.pak"
unpak_folder = "settings_resources.unpak"
-vulcanize("build") {
+optimize_webui("build") {
host = "settings"
html_in_files = [
"settings.html",
@@ -15,7 +15,7 @@ vulcanize("build") {
"vulcanized.html",
"lazy_load.vulcanized.html",
]
- insert_in_head = "<base href=\"chrome://\$i18n{hostname}\">"
+ insert_in_head = "<base href=\"chrome://settings\">"
input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
js_out_files = [
"crisper.js",
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.html b/chromium/chrome/browser/resources/settings/about_page/about_page.html
index 903457b27f5..bc42399d48f 100644
--- a/chromium/chrome/browser/resources/settings/about_page/about_page.html
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.html
@@ -22,6 +22,7 @@
<link rel="import" href="detailed_build_info.html">
<link rel="import" href="update_warning_dialog.html">
<link rel="import" href="../settings_page/settings_subpage.html">
+<link rel="import" href="../reset_page/powerwash_dialog.html">
</if>
<if expr="_google_chrome and is_macosx">
@@ -142,6 +143,25 @@
</if>
</span>
</div>
+<if expr="chromeos">
+ <div id="aboutTPMFirmwareUpdate" class="settings-box two-line"
+ hidden$="[[!showTPMFirmwareUpdateLineItem_]]"
+ on-tap="onTPMFirmwareUpdateTap_" actionable>
+ <div class="start">
+ <div>$i18n{aboutTPMFirmwareUpdateTitle}</div>
+ <div class="secondary">
+ $i18n{aboutTPMFirmwareUpdateDescription}
+ <a href="$i18n{aboutTPMFirmwareUpdateLearnMoreURL}"
+ target="_blank" on-tap="onLearnMoreTap_">
+ $i18n{learnMore}
+ </a>
+ </div>
+ </div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-labelledby="aboutTPMFirmwareUpdate">
+ </button>
+ </div>
+</if>
<if expr="_google_chrome and is_macosx">
<template is="dom-if" if="[[!promoteUpdaterStatus_.hidden]]">
<div id="promoteUpdater" class="settings-box"
@@ -229,6 +249,12 @@
on-close="onUpdateWarningDialogClose_">
</settings-update-warning-dialog>
</template>
+ <template is="dom-if" if="[[showTPMFirmwareUpdateDialog_]]"
+ restamp>
+ <settings-powerwash-dialog request-tpm-firmware-update
+ on-close="onPowerwashDialogClose_">
+ </settings-powerwash-dialog>
+ </template>
</if>
</template>
<script src="about_page.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.js b/chromium/chrome/browser/resources/settings/about_page/about_page.js
index 4270abf92a8..5ddfb82ce1f 100644
--- a/chromium/chrome/browser/resources/settings/about_page/about_page.js
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.js
@@ -96,6 +96,12 @@ Polymer({
value: false,
},
+ /** @private */
+ showTPMFirmwareUpdateLineItem_: Boolean,
+
+ /** @private */
+ showTPMFirmwareUpdateDialog_: Boolean,
+
/** @private {!AboutPageUpdateInfo|undefined} */
updateInfo_: Object,
// </if>
@@ -168,6 +174,12 @@ Polymer({
this.onPromoteUpdaterStatusChanged_.bind(this));
// </if>
this.aboutBrowserProxy_.refreshUpdateStatus();
+ // <if expr="chromeos">
+ this.addWebUIListener(
+ 'tpm-firmware-update-status-changed',
+ this.onTPMFirmwareUpdateStatusChanged_.bind(this));
+ this.aboutBrowserProxy_.refreshTPMFirmwareUpdateStatus();
+ // </if>
},
/**
@@ -206,6 +218,7 @@ Polymer({
return;
this.aboutBrowserProxy_.promoteUpdater();
},
+ // </if>
/**
* @param {!Event} event
@@ -216,7 +229,6 @@ Polymer({
// actionable items won't trigger action.
event.stopPropagation();
},
- // </if>
/** @private */
onHelpTap_: function() {
@@ -443,6 +455,24 @@ Polymer({
// dialog and then intends to check for update again.
this.hasCheckedForUpdates_ = false;
},
+
+ /**
+ * @param {!TPMFirmwareUpdateStatusChangedEvent} event
+ * @private
+ */
+ onTPMFirmwareUpdateStatusChanged_: function(event) {
+ this.showTPMFirmwareUpdateLineItem_ = event.updateAvailable;
+ },
+
+ /** @private */
+ onTPMFirmwareUpdateTap_: function() {
+ this.showTPMFirmwareUpdateDialog_ = true;
+ },
+
+ /** @private */
+ onPowerwashDialogClose_: function() {
+ this.showTPMFirmwareUpdateDialog_ = false;
+ },
// </if>
/** @private */
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
index df85fd8c99e..ecd5043689c 100644
--- 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
@@ -52,6 +52,13 @@ var BrowserChannel = {
DEV: 'dev-channel',
STABLE: 'stable-channel',
};
+
+/**
+ * @typedef {{
+ * updateAvailable: boolean,
+ * }}
+ */
+var TPMFirmwareUpdateStatusChangedEvent;
// </if>
/**
@@ -190,6 +197,11 @@ cr.define('settings', function() {
/** @return {!Promise<?RegulatoryInfo>} */
getRegulatoryInfo() {}
+ /**
+ * Request TPM firmware update status from the browser. It results in one or
+ * more 'tpm-firmware-update-status-changed' WebUI events.
+ */
+ refreshTPMFirmwareUpdateStatus() {}
// </if>
// <if expr="_google_chrome and is_macosx">
@@ -265,6 +277,11 @@ cr.define('settings', function() {
getRegulatoryInfo() {
return cr.sendWithPromise('getRegulatoryInfo');
}
+
+ /** @override */
+ refreshTPMFirmwareUpdateStatus() {
+ chrome.send('refreshTPMFirmwareUpdateStatus');
+ }
// </if>
}
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 da28035f148..7ac5845998d 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
@@ -36,51 +37,46 @@
};
width: 100%; /* Pushes policy indicators to end. */
}
+
+ /* The theme mixes a link and a paper-button divided by a separator with
+ * grit expressions and dom-if templates. That leads to a tricky thing
+ * to style correctly, these are a workaround. */
+ #themeRow paper-button {
+ -webkit-margin-end: 8px;
+ }
+
+ #themeRow .separator {
+ -webkit-margin-start: 0;
+ }
+
+ #useSystem {
+ -webkit-margin-start: calc(var(--cr-button-edge-spacing) * -1);
+ }
</style>
<settings-animated-pages id="pages" section="appearance"
focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<if expr="chromeos">
- <div class="settings-box first two-line" id="wallpaperButton"
- on-tap="openWallpaperManager_" actionable
- hidden="[[!pageVisibility.setWallpaper]]">
- <div class="start">
- $i18n{setWallpaper}
- <div class="secondary" id="wallpaperSecondary">
- $i18n{openWallpaperApp}
- </div>
- </div>
+ <button icon-class="icon-external" id="wallpaperButton"
+ is="cr-link-row"
+ hidden="[[!pageVisibility.setWallpaper]]"
+ on-tap="openWallpaperManager_"
+ label="$i18n{setWallpaper}" sub-label="$i18n{openWallpaperApp}"
+ disabled="[[isWallpaperPolicyControlled_]]">
<template is="dom-if" if="[[isWallpaperPolicyControlled_]]">
<cr-policy-indicator id="wallpaperPolicyIndicator"
indicator-type="devicePolicy">
</cr-policy-indicator>
</template>
- <button class="icon-external" id="showWallpaperManager"
- is="paper-icon-button-light" aria-label="$i18n{setWallpaper}"
- disabled="[[isWallpaperPolicyControlled_]]"
- aria-describedby="wallpaperSecondary">
- </button>
- </div>
- <div class="settings-box two-line"
- hidden="[[!pageVisibility.setTheme]]">
+ </button>
+ <div class="hr"></div>
</if>
-<if expr="not chromeos">
- <div class="settings-box two-line first"
+ <div class="settings-row continuation" id="themeRow"
hidden="[[!pageVisibility.setTheme]]">
-</if>
- <a class="start two-line inherit-color no-outline" tabindex="-1"
- target="_blank" href$="[[getThemeHref_(themeUrl_)]]">
- <div class="flex">
- $i18n{themes}
- <div class="secondary" id="themesSecondary">
- [[themeSublabel_]]
- </div>
- </div>
- <button class="icon-external" is="paper-icon-button-light"
- actionable aria-label="$i18n{themes}"
- aria-describedby="themesSecondary">
- </button>
- </a>
+ <button class="first" icon-class="icon-external" is="cr-link-row"
+ hidden="[[!pageVisibility.setTheme]]"
+ label="$i18n{themes}" sub-label="[[themeSublabel_]]"
+ on-tap="openThemeUrl_"></button>
<if expr="not is_linux or chromeos">
<template is="dom-if" if="[[prefs.extensions.theme.id.value]]">
<div class="separator"></div>
@@ -91,7 +87,8 @@
</template>
</if>
<if expr="is_linux and not chromeos">
- <div class="settings-row" hidden="[[!showThemesSecondary_(
+ <div class="settings-row continuation"
+ hidden="[[!showThemesSecondary_(
prefs.extensions.theme.id.value, useSystemTheme_)]]"
id="themesSecondaryActions">
<div class="separator"></div>
@@ -169,14 +166,10 @@
menu-options="[[fontSizeOptions_]]">
</settings-dropdown-menu>
</div>
- <div id="customize-fonts-subpage-trigger" class="settings-box"
- on-tap="onCustomizeFontsTap_" actionable>
- <div class="start">
- $i18n{customizeFonts}
- </div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{customizeFonts}"></button>
- </div>
+ <button class="hr" is="cr-link-row"
+ icon-class="subpage-arrow" id="customize-fonts-subpage-trigger"
+ label="$i18n{customizeFonts}" on-tap="onCustomizeFontsTap_">
+ </button>
<div class="settings-box" hidden="[[!pageVisibility.pageZoom]]">
<div id="pageZoom" class="start">$i18n{pageZoom}</div>
<div class="md-select-wrapper">
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 be01b65fc12..e3c34ea3b66 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -104,8 +104,7 @@ Polymer({
var map = new Map();
if (settings.routes.FONTS) {
map.set(
- settings.routes.FONTS.path,
- '#customize-fonts-subpage-trigger .subpage-arrow');
+ settings.routes.FONTS.path, '#customize-fonts-subpage-trigger');
}
return map;
},
@@ -198,12 +197,11 @@ Polymer({
},
/**
- * URL for either current theme or the theme gallery.
- * @return {string}
+ * Open URL for either current theme or the theme gallery.
* @private
*/
- getThemeHref_: function() {
- return this.themeUrl_ || loadTimeData.getString('themesGalleryUrl');
+ openThemeUrl_: function() {
+ window.open(this.themeUrl_ || loadTimeData.getString('themesGalleryUrl'));
},
// <if expr="chromeos">
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 f622ff71a9e..cb5157281cf 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -162,7 +162,16 @@
<template is="dom-if" if="[[showPage_(pageVisibility.search)]]" restamp>
<settings-section page-title="$i18n{searchPageTitle}"
section="search">
+<if expr="chromeos">
+ <settings-search-page prefs="{{prefs}}"
+ arc-enabled="[[prefs.arc.enabled.value]]"
+ voice-interaction-value-prop-accepted="[[
+ prefs.arc.voice_interaction_value_prop.accepted.value]]">
+ </settings-search-page>
+</if>
+<if expr="not chromeos">
<settings-search-page prefs="{{prefs}}"></settings-search-page>
+</if>
</settings-section>
</template>
<if expr="chromeos">
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 da7f5f65ebe..36b2b7f6423 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -39,10 +39,7 @@ Polymer({
showChangePassword: {
type: Boolean,
- value: function() {
- return loadTimeData.valueExists('changePasswordEnabled') &&
- loadTimeData.getBoolean('changePasswordEnabled');
- },
+ value: false,
},
/**
@@ -99,6 +96,10 @@ Polymer({
currentRoute_: Object,
},
+ hostAttributes: {
+ role: 'main',
+ },
+
listeners: {
'subpage-expand': 'onSubpageExpanded_',
},
@@ -107,16 +108,24 @@ Polymer({
attached: function() {
this.currentRoute_ = settings.getCurrentRoute();
- this.addEventListener('chrome-cleanup-dismissed', e => {
+ // <if expr="is_win">
+ this.addEventListener('chrome-cleanup-dismissed', () => {
this.showChromeCleanup = false;
});
+ // </if>
- this.addEventListener('change-password-clicked', e => {
+ this.addEventListener('change-password-dismissed', () => {
this.showChangePassword = false;
});
+ this.addWebUIListener('change-password-visibility', visibility => {
+ this.showChangePassword = visibility;
+ });
+ settings.ChangePasswordBrowserProxyImpl.getInstance()
+ .initializeChangePasswordHandler();
+
if (settings.AndroidAppsBrowserProxyImpl) {
- cr.addWebUIListener(
+ this.addWebUIListener(
'android-apps-info-update', this.androidAppsInfoUpdate_.bind(this));
settings.AndroidAppsBrowserProxyImpl.getInstance()
.requestAndroidAppsInfo();
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 2a6445caf7c..dd816a8810d 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -206,10 +206,10 @@ Polymer({
this.bluetoothToggleDisabled_ = true;
this.bluetoothPrivate.setAdapterState(
{powered: this.bluetoothToggleState_}, () => {
- var error = chrome.runtime.lastError;
- if (error && error != 'Error setting adapter properties: powered') {
- console.error('Error enabling bluetooth: ' + error.message);
- return;
+ if (chrome.runtime.lastError) {
+ console.error(
+ 'Error enabling bluetooth: ' +
+ chrome.runtime.lastError.message);
}
this.setPrefValue(
'ash.user.bluetooth.adapter_enabled',
diff --git a/chromium/chrome/browser/resources/settings/change_password_page/change_password_browser_proxy.js b/chromium/chrome/browser/resources/settings/change_password_page/change_password_browser_proxy.js
index d7b545532fb..8118cd8ccaa 100644
--- a/chromium/chrome/browser/resources/settings/change_password_page/change_password_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/change_password_page/change_password_browser_proxy.js
@@ -5,11 +5,8 @@
cr.define('settings', function() {
/** @interface */
class ChangePasswordBrowserProxy {
- /**
- * Inform PasswordProtectionService that the change password card is
- * showing.
- */
- onChangePasswordPageShown() {}
+ /** Initialize the change password handler.*/
+ initializeChangePasswordHandler() {}
/**
* Initiate the change password process. e.g., for Gmail users, it
@@ -24,8 +21,8 @@ cr.define('settings', function() {
*/
class ChangePasswordBrowserProxyImpl {
/** @override */
- onChangePasswordPageShown() {
- chrome.send('onChangePasswordPageShown');
+ initializeChangePasswordHandler() {
+ chrome.send('initializeChangePasswordHandler');
}
/** @override */
diff --git a/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html b/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html
index 8efd4112cde..deb22750820 100644
--- a/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html
+++ b/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html
@@ -7,6 +7,7 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.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-styles/color.html">
diff --git a/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.js b/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.js
index a17ece0fecc..def50ad1000 100644
--- a/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.js
+++ b/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.js
@@ -10,30 +10,10 @@
Polymer({
is: 'settings-change-password-page',
- properties: {
- /**
- * Preferences state.
- */
- prefs: {
- type: Object,
- notify: true,
- },
- },
-
- /** @private {?settings.ChangePasswordBrowserProxy} */
- browserProxy_: null,
-
- /** @override */
- attached: function() {
- this.browserProxy_ = settings.ChangePasswordBrowserProxyImpl.getInstance();
- this.browserProxy_.onChangePasswordPageShown();
- },
-
/** @private */
changePassword_: function() {
listenOnce(this, 'transitionend', () => {
- this.browserProxy_.changePassword();
+ settings.ChangePasswordBrowserProxyImpl.getInstance().changePassword();
});
- this.fire('change-password-clicked');
},
});
diff --git a/chromium/chrome/browser/resources/settings/change_password_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/change_password_page/compiled_resources2.gyp
index fea6ac8f461..64476e15c62 100644
--- a/chromium/chrome/browser/resources/settings/change_password_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/change_password_page/compiled_resources2.gyp
@@ -17,6 +17,7 @@
'<(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:util',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'<(EXTERNS_GYP):settings_private',
'change_password_browser_proxy',
],
diff --git a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
index cc7eee42195..d2c2fc0ae4f 100644
--- a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
+++ b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -129,11 +129,11 @@
<div class="start">
$i18n{chromeCleanupLinkShowFiles}
</div>
- <cr-expand-button expanded="{{showFilesToRemove_}}"
+ <cr-expand-button expanded="{{filesToRemoveListExpanded_}}"
alt="$i18n{chromeCleanupLinkShowFiles}">
</cr-expand-button>
</div>
- <iron-collapse opened="[[showFilesToRemove_]]">
+ <iron-collapse opened="[[filesToRemoveListExpanded_]]">
<div id="files-to-remove-container">
<ul id="files-to-remove-list" class="secondary">
<template is="dom-repeat" items="[[filesToRemove_]]" as="fileName">
diff --git a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
index 9ff10384a20..caaf5da8706 100644
--- a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
+++ b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
@@ -31,6 +31,57 @@ settings.ChromeCleanupDismissSource = {
};
/**
+ * The possible states for the cleanup card.
+ * @enum {string}
+ */
+settings.ChromeCleanerCardState = {
+ HIDDEN_CARD: 'hidden_card',
+ CLEANUP_OFFERED: 'cleanup_offered',
+ CLEANING: 'cleaning',
+ REBOOT_REQUIRED: 'reboot_required',
+ CLEANUP_SUCCEEDED: 'cleanup_succeeded',
+ CLEANING_FAILED: 'cleanup_failed',
+};
+
+/**
+ * Boolean properties for a cleanup card state.
+ * @enum {number}
+ */
+settings.ChromeCleanupCardFlags = {
+ NONE: 0,
+ SHOW_DETAILS: 1 << 0,
+ SHOW_LOGS_PERMISSIONS: 1 << 1,
+ SHOW_LEARN_MORE: 1 << 2,
+ IS_REMOVING: 1 << 3,
+};
+
+/**
+ * @typedef {{
+ * statusIcon: string,
+ * statusIconClassName: string,
+ * }}
+ */
+settings.ChromeCleanupCardIcon;
+
+/**
+ * @typedef {{
+ * label: string,
+ * doAction: !function(),
+ * }}
+ */
+settings.ChromeCleanupCardActionButton;
+
+/**
+ * @typedef {{
+ * title: ?string,
+ * icon: ?settings.ChromeCleanupCardIcon,
+ * actionButton: ?settings.ChromeCleanupCardActionButton,
+ * flags: number,
+ * }}
+ */
+settings.ChromeCleanupCardComponents;
+
+/**
* @fileoverview
* 'settings-chrome-cleanup-page' is the settings page containing Chrome
* Cleanup settings.
@@ -95,10 +146,10 @@ Polymer({
},
/** @private */
- showFilesToRemove_: {
+ filesToRemoveListExpanded_: {
type: Boolean,
value: false,
- observer: 'showFilesToRemoveChanged_',
+ observer: 'filesToRemoveListExpandedChanged_',
},
/** @private */
@@ -143,9 +194,14 @@ Polymer({
/** @private {?function()} */
doAction_: null,
+ /** @private {?Map<settings.ChromeCleanerCardState,
+ * !settings.ChromeCleanupCardComponents>} */
+ cardStateToComponentsMap_: null,
+
/** @override */
attached: function() {
this.browserProxy_ = settings.ChromeCleanupProxyImpl.getInstance();
+ this.cardStateToComponentsMap_ = this.buildCardStateToComponentsMap_();
this.addWebUIListener('chrome-cleanup-on-idle', this.onIdle_.bind(this));
this.addWebUIListener(
@@ -198,12 +254,11 @@ Polymer({
* Notify Chrome that the details section was opened or closed.
* @private
*/
- showFilesToRemoveChanged_: function() {
+ filesToRemoveListExpandedChanged_: function() {
if (this.browserProxy_)
- this.browserProxy_.notifyShowDetails(this.showFilesToRemove_);
+ this.browserProxy_.notifyShowDetails(this.filesToRemoveListExpanded_);
},
-
/**
* Notfies Chrome that the "learn more" link was clicked.
* @private
@@ -217,7 +272,7 @@ Polymer({
* @private
*/
showPoweredBy_: function() {
- return this.showFilesToRemove_ && this.isPartnerPowered_;
+ return this.filesToRemoveListExpanded_ && this.isPartnerPowered_;
},
/**
@@ -227,76 +282,48 @@ Polymer({
*/
onIdle_: function(idleReason) {
if (idleReason == settings.ChromeCleanupIdleReason.CLEANING_SUCCEEDED) {
- this.title_ = this.i18n('chromeCleanupTitleRemoved');
- this.enableActionButton_(
- this.i18n('chromeCleanupDoneButtonLabel'),
- this.dismiss_.bind(
- this,
- settings.ChromeCleanupDismissSource.CLEANUP_SUCCESS_DONE_BUTTON));
- this.setIconDone_();
- this.showLearnMore_ = false;
+ this.renderCleanupCard_(
+ settings.ChromeCleanerCardState.CLEANUP_SUCCEEDED, []);
} else if (idleReason == settings.ChromeCleanupIdleReason.INITIAL) {
this.dismiss_(settings.ChromeCleanupDismissSource.OTHER);
} else {
// Scanning-related idle reasons are unexpected. Show an error message for
// all reasons other than |CLEANING_SUCCEEDED| and |INITIAL|.
- this.title_ = this.i18n('chromeCleanupTitleErrorCantRemove');
- this.enableActionButton_(
- this.i18n('chromeCleanupDoneButtonLabel'),
- this.dismiss_.bind(
- this,
- settings.ChromeCleanupDismissSource.CLEANUP_FAILURE_DONE_BUTTON));
- this.setIconWarning_();
- this.showLearnMore_ = true;
+ this.renderCleanupCard_(
+ settings.ChromeCleanerCardState.CLEANING_FAILED, []);
}
-
- this.isRemoving_ = false;
- this.disableDetails_();
},
/**
* Listener of event 'chrome-cleanup-on-scanning'.
- * No UI will be shown in the Settings page on that state, so we simply hide
- * the card and cleanup this element's fields.
+ * No UI will be shown in the Settings page on that state, simply hide the
+ * card and cleanup this element's fields.
* @private
*/
onScanning_: function() {
- this.title_ = '';
- this.isRemoving_ = false;
- this.disableActionButton_();
- this.disableDetails_();
+ this.renderCleanupCard_(settings.ChromeCleanerCardState.HIDDEN_CARD, []);
},
/**
* Listener of event 'chrome-cleanup-on-infected'.
* Offers a cleanup to the user and enables presenting files to be removed.
- * @param {!Array<!string>} files The list of files to present to the user.
+ * @param {!Array<string>} files The list of files to present to the user.
* @private
*/
onInfected_: function(files) {
- this.title_ = this.i18n('chromeCleanupTitleRemove');
- this.isRemoving_ = false;
- this.setIconRemove_();
- this.enableActionButton_(
- this.i18n('chromeCleanupRemoveButtonLabel'),
- this.startCleanup_.bind(this));
- this.enableDetails_(files);
+ this.renderCleanupCard_(
+ settings.ChromeCleanerCardState.CLEANUP_OFFERED, files);
},
/**
* Listener of event 'chrome-cleanup-on-cleaning'.
* Shows a spinner indicating that an on-going action and enables presenting
* files to be removed.
- * @param {!Array<!string>} files The list of files to present to the user.
+ * @param {!Array<string>} files The list of files to present to the user.
* @private
*/
onCleaning_: function(files) {
- this.title_ = this.i18n('chromeCleanupTitleRemoving');
- this.isRemoving_ = true;
- this.resetIcon_();
- this.disableActionButton_();
- this.enableDetails_(files);
- this.showLogsPermission_ = false;
+ this.renderCleanupCard_(settings.ChromeCleanerCardState.CLEANING, files);
},
/**
@@ -306,100 +333,123 @@ Polymer({
* @private
*/
onRebootRequired_: function() {
- this.title_ = this.i18n('chromeCleanupTitleRestart');
- this.isRemoving_ = false;
- this.showLearnMore_ = false;
- this.setIconDone_();
- this.enableActionButton_(
- this.i18n('chromeCleanupRestartButtonLabel'),
- this.restartComputer_.bind(this));
- this.disableDetails_();
+ this.renderCleanupCard_(
+ settings.ChromeCleanerCardState.REBOOT_REQUIRED, []);
},
/**
- * Listener of event 'chrome-cleanup-dismiss'.
- * Hides the Cleanup card.
+ * Renders the cleanup card given the state and list of files.
+ * @param {!settings.ChromeCleanerCardState} state The card state to be
+ * rendered.
+ * @param {!Array<string>} files The list of files to present to the user.
* @private
*/
- onDismiss_: function() {
- this.fire('chrome-cleanup-dismissed');
+ renderCleanupCard_: function(state, files) {
+ var components = this.cardStateToComponentsMap_.get(state);
+ assert(components);
+
+ this.filesToRemove_ = files;
+ this.title_ = components.title || '';
+ this.updateIcon_(components.icon);
+ this.updateActionButton_(components.actionButton);
+ this.updateCardFlags_(components.flags);
},
/**
- * @param {boolean} enabled Whether logs upload is enabled.
+ * Updates the icon on the cleanup card to show the current state.
+ * @param {?settings.ChromeCleanupCardIcon} icon The icon to
+ * render, or null if no icon should be shown.
* @private
*/
- onUploadPermissionChange_: function(enabled) {
- this.logsUploadPref_ = {
- key: '',
- type: chrome.settingsPrivate.PrefType.BOOLEAN,
- value: enabled,
- };
+ updateIcon_: function(icon) {
+ if (!icon) {
+ this.statusIcon_ = '';
+ this.statusIconClassName_ = '';
+ } else {
+ this.statusIcon_ = icon.statusIcon;
+ this.statusIconClassName_ = icon.statusIconClassName;
+ }
},
/**
- * @param {boolean} enabled Whether to enable logs upload.
+ * Updates the action button on the cleanup card as the action expected for
+ * the current state.
+ * @param {?settings.ChromeCleanupCardActionButton} actionButton
+ * The button to render, or null if no button should be shown.
* @private
*/
- changeLogsPermission_: function(enabled) {
- var enabled = this.$.chromeCleanupLogsUploadControl.checked;
- this.browserProxy_.setLogsUploadPermission(enabled);
+ updateActionButton_: function(actionButton) {
+ if (!actionButton) {
+ this.showActionButton_ = false;
+ this.actionButtonLabel_ = '';
+ this.doAction_ = null;
+ } else {
+ this.showActionButton_ = true;
+ this.actionButtonLabel_ = actionButton.label;
+ this.doAction_ = actionButton.doAction;
+ }
},
/**
- * Dismiss the card.
- * @param {number} source
+ * Updates boolean flags corresponding to optional components to be rendered
+ * on the card.
+ * @param {number} flags Flags indicating optional components to be rendered.
* @private
*/
- dismiss_: function(source) {
- this.browserProxy_.dismissCleanupPage(source);
+ updateCardFlags_: function(flags) {
+ this.showDetails_ =
+ (flags & settings.ChromeCleanupCardFlags.SHOW_DETAILS) != 0;
+ this.showLogsPermission_ =
+ (flags & settings.ChromeCleanupCardFlags.SHOW_LOGS_PERMISSIONS) != 0;
+ this.showLearnMore_ =
+ (flags & settings.ChromeCleanupCardFlags.SHOW_LEARN_MORE) != 0;
+ this.isRemoving_ =
+ (flags & settings.ChromeCleanupCardFlags.IS_REMOVING) != 0;
+
+ // Files to remove list should only be expandable if details are being
+ // shown, otherwise it will add extra padding at the bottom of the card.
+ if (!this.showDetails_)
+ this.filesToRemoveListExpanded_ = false;
},
/**
- * Hides the action button in the card when no action is available.
+ * Listener of event 'chrome-cleanup-dismiss'.
+ * Hides the Cleanup card.
* @private
*/
- disableActionButton_: function() {
- this.showActionButton_ = false;
- this.actionButtonLabel_ = '';
- this.doAction_ = null;
+ onDismiss_: function() {
+ this.fire('chrome-cleanup-dismissed');
},
/**
- * Shows the action button in the card with an associated label and action
- * function.
- * @param {!string} buttonLabel The label for the action button.
- * @param {!function()} action The function associated with the on-tap event.
+ * @param {boolean} enabled Whether logs upload is enabled.
* @private
*/
- enableActionButton_: function(buttonLabel, action) {
- this.showActionButton_ = true;
- this.actionButtonLabel_ = buttonLabel;
- this.doAction_ = action;
+ onUploadPermissionChange_: function(enabled) {
+ this.logsUploadPref_ = {
+ key: '',
+ type: chrome.settingsPrivate.PrefType.BOOLEAN,
+ value: enabled,
+ };
},
/**
- * Disables the details section on the card.
+ * @param {boolean} enabled Whether to enable logs upload.
* @private
*/
- disableDetails_: function() {
- this.showDetails_ = false;
- this.showLogsPermission_ = false;
- this.showFilesToRemove_ = false;
- this.filesToRemove_ = [];
+ changeLogsPermission_: function(enabled) {
+ var enabled = this.$.chromeCleanupLogsUploadControl.checked;
+ this.browserProxy_.setLogsUploadPermission(enabled);
},
/**
- * Enables the details section on the card.
- * @param {!Array<!string>} files The list of files to present to the user.
+ * Dismiss the card.
+ * @param {settings.ChromeCleanupDismissSource} source
* @private
*/
- enableDetails_: function(files) {
- this.showDetails_ = true;
- this.showLogsPermission_ = true;
- this.showLearnMore_ = true;
- // Note: doesn't change the state of this.showFilesToRemove_.
- this.filesToRemove_ = files;
+ dismiss_: function(source) {
+ this.renderCleanupCard_(settings.ChromeCleanerCardState.HIDDEN_CARD, []);
+ this.browserProxy_.dismissCleanupPage(source);
},
/**
@@ -420,38 +470,120 @@ Polymer({
},
/**
- * Sets the card's icon as the cleanup offered indication.
+ * Returns the map of card states to components to be rendered.
+ * @return {!Map<settings.ChromeCleanerCardState,
+ * !settings.ChromeCleanupCardComponents>}
* @private
*/
- setIconRemove_: function() {
- this.statusIcon_ = 'settings:security';
- this.statusIconClassName_ = 'status-icon-remove';
- },
+ buildCardStateToComponentsMap_: function() {
+ /**
+ * The icons to show on the card.
+ * @enum {settings.ChromeCleanupCardIcon}
+ */
+ var icons = {
+ // Card's icon indicates a cleanup offer.
+ REMOVE: {
+ statusIcon: 'settings:security',
+ statusIconClassName: 'status-icon-remove',
+ },
- /**
- * Sets the card's icon as a warning (in case of failure).
- * @private
- */
- setIconWarning_: function() {
- this.statusIcon_ = 'settings:error';
- this.statusIconClassName_ = 'status-icon-warning';
- },
+ // Card's icon indicates a warning (in case of failure).
+ WARNING: {
+ statusIcon: 'settings:error',
+ statusIconClassName: 'status-icon-warning',
+ },
- /**
- * Sets the card's icon as a completed or reboot required indication.
- * @private
- */
- setIconDone_: function() {
- this.statusIcon_ = 'settings:check-circle';
- this.statusIconClassName_ = 'status-icon-done';
- },
+ // Card's icon indicates completion or reboot required.
+ DONE: {
+ statusIcon: 'settings:check-circle',
+ statusIconClassName: 'status-icon-done',
+ },
+ };
- /**
- * Resets the card's icon.
- * @private
- */
- resetIcon_: function() {
- this.statusIcon_ = '';
- this.statusIconClassName_ = '';
+ /**
+ * The action buttons to show on the card.
+ * @enum {settings.ChromeCleanupCardActionButton}
+ */
+ var actionButtons = {
+ REMOVE: {
+ label: this.i18n('chromeCleanupRemoveButtonLabel'),
+ doAction: this.startCleanup_.bind(this),
+ },
+
+ RESTART_COMPUTER: {
+ label: this.i18n('chromeCleanupRestartButtonLabel'),
+ doAction: this.restartComputer_.bind(this),
+ },
+
+ DISMISS_CLEANUP_SUCCESS: {
+ label: this.i18n('chromeCleanupDoneButtonLabel'),
+ doAction: this.dismiss_.bind(
+ this,
+ settings.ChromeCleanupDismissSource.CLEANUP_SUCCESS_DONE_BUTTON),
+ },
+
+ DISMISS_CLEANUP_FAILURE: {
+ label: this.i18n('chromeCleanupDoneButtonLabel'),
+ doAction: this.dismiss_.bind(
+ this,
+ settings.ChromeCleanupDismissSource.CLEANUP_FAILURE_DONE_BUTTON),
+ },
+ };
+
+ return new Map([
+ [
+ settings.ChromeCleanerCardState.HIDDEN_CARD, {
+ title: null,
+ icon: null,
+ actionButton: null,
+ flags: settings.ChromeCleanupCardFlags.NONE,
+ }
+ ],
+ [
+ settings.ChromeCleanerCardState.CLEANUP_OFFERED, {
+ title: this.i18n('chromeCleanupTitleRemove'),
+ icon: icons.REMOVE,
+ actionButton: actionButtons.REMOVE,
+ flags: settings.ChromeCleanupCardFlags.SHOW_DETAILS |
+ settings.ChromeCleanupCardFlags.SHOW_LOGS_PERMISSIONS |
+ settings.ChromeCleanupCardFlags.SHOW_LEARN_MORE,
+ }
+ ],
+ [
+ settings.ChromeCleanerCardState.CLEANING, {
+ title: this.i18n('chromeCleanupTitleRemoving'),
+ icon: null,
+ actionButton: null,
+ flags: settings.ChromeCleanupCardFlags.SHOW_DETAILS |
+ settings.ChromeCleanupCardFlags.IS_REMOVING |
+ settings.ChromeCleanupCardFlags.SHOW_LEARN_MORE,
+ }
+ ],
+ [
+ settings.ChromeCleanerCardState.REBOOT_REQUIRED, {
+ title: this.i18n('chromeCleanupTitleRestart'),
+ icon: icons.DONE,
+ actionButton: actionButtons.RESTART_COMPUTER,
+ flags: settings.ChromeCleanupCardFlags.NONE,
+ }
+ ],
+ [
+ settings.ChromeCleanerCardState.CLEANUP_SUCCEEDED, {
+ title: this.i18n('chromeCleanupTitleRemoved'),
+ icon: icons.DONE,
+ actionButton: actionButtons.DISMISS_CLEANUP_SUCCESS,
+ flags: settings.ChromeCleanupCardFlags.NONE,
+ }
+ ],
+ [
+ settings.ChromeCleanerCardState.CLEANING_FAILED, {
+ title: this.i18n('chromeCleanupTitleErrorCantRemove'),
+ icon: icons.WARNING,
+ actionButton: actionButtons.DISMISS_CLEANUP_FAILURE,
+ flags: settings.ChromeCleanupCardFlags.SHOW_LEARN_MORE |
+ settings.ChromeCleanupCardFlags.NONE,
+ }
+ ],
+ ]);
},
});
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 c78b9dd84d7..6bf142aac63 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
@@ -99,7 +99,8 @@ Polymer({
/** @override */
ready: function() {
this.$.clearFrom.menuOptions = this.clearFromOptions_;
- this.addWebUIListener('update-footer', this.updateFooter_.bind(this));
+ this.addWebUIListener(
+ 'update-sync-state', this.updateSyncState_.bind(this));
this.addWebUIListener(
'update-counter-text', this.updateCounterText_.bind(this));
},
@@ -122,12 +123,13 @@ Polymer({
/**
* Updates the footer to show only those sentences that are relevant to this
* user.
+ * @param {boolean} signedIn Whether the user is signed in.
* @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) {
+ updateSyncState_: function(signedIn, syncing, otherFormsOfBrowsingHistory) {
this.$.googleFooter.hidden = !otherFormsOfBrowsingHistory;
this.$.syncedDataSentence.hidden = !syncing;
this.$.clearBrowsingDataDialog.classList.add('fully-rendered');
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html
index b991c9986fe..502eac00064 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.html
@@ -2,8 +2,10 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.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-spinner/paper-spinner.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tabs.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="clear_browsing_data_browser_proxy.html">
<link rel="import" href="history_deletion_dialog.html">
@@ -12,12 +14,31 @@
<link rel="import" href="../controls/settings_dropdown_menu.html">
<link rel="import" href="../icons.html">
<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="../settings_vars_css.html">
<!-- This file is a fork of clear_browsing_data_dialog.html until the new CBD
UI is launched. -->
<dom-module id="settings-clear-browsing-data-dialog-tabs">
<template>
<style include="settings-shared">
+ :host {
+ /* Fixed height to allow multiple tabs with different height.
+ * The last entry in the advanced tab should show half an entry.
+ * crbug.com/652027 */
+ --body-container-height: 322px;
+ }
+
+ #clearBrowsingDataDialog {
+ --cr-dialog-top-container-min-height: 42px;
+ --cr-dialog-title: {
+ padding-bottom: 8px;
+ };
+ --cr-dialog-body-container: {
+ border-top: 1px solid var(--paper-grey-300);
+ height: var(--body-container-height);
+ };
+ }
+
#clearBrowsingDataDialog:not(.fully-rendered) {
visibility: hidden;
}
@@ -26,6 +47,16 @@
color: var(--paper-grey-600);
}
+ #clearBrowsingDataDialog [slot=body] {
+ padding-top: 8px;
+ }
+
+ #importantSitesDialog {
+ --cr-dialog-body-container: {
+ height: var(--body-container-height);
+ };
+ }
+
.row {
align-items: center;
display: flex;
@@ -43,55 +74,36 @@
--settings-row-two-line-min-height: 48px;
--settings-checkbox-label: {
line-height: 1.25rem;
- };
- }
-
- #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;
- }
-
- [slot=footer] iron-icon {
- margin: auto;
+ }
}
- .clear-browsing-data-footer {
- -webkit-padding-start: 4px;
- align-items: flex-start;
- display: flex;
- line-height: 1.538em; /* 20px/13px */
+ #basic-tab settings-checkbox + settings-checkbox {
+ --settings-checkbox-margin-top: 12px;
}
- .clear-browsing-data-footer .footer-text {
- -webkit-margin-start: 16px;
+ paper-tabs {
+ --paper-tabs-selection-bar-color: var(--google-blue-500);
+ --paper-tabs: {
+ font-size: 100%;
+ height: 40px;
+ }
}
- .clear-browsing-data-footer iron-icon {
- flex-shrink: 0;
+ paper-tab {
+ --paper-tab-content: {
+ color: var(--google-blue-700);
+ };
+ --paper-tab-content-unselected: {
+ opacity: 1;
+ color: var(--paper-grey-600);
+ };
}
- .clear-browsing-data-footer a {
- text-decoration: none;
+ .time-range-row {
+ margin-bottom: 12px;
}
- #clearFrom {
+ .time-range-select {
-webkit-margin-start: 0.5em;
/* Adjust for md-select-underline and 1px additional bottom padding
* to keep md-select's text (without the underline) aligned with
@@ -103,87 +115,141 @@
font-size: calc(13 / 15 * 100%);
padding-top: 8px;
}
-
- /* Cap the height on smaller screens to avoid unfavorable clipping.
- * Replace the bottom margin with padding to avoid the gap between
- * the scrollbar and the bottom separator. */
- @media all and (max-height: 724px) {
- #clearBrowsingDataDialog {
- /* crbug.com/652027: Show four and a *half* items in the list. */
- --cr-dialog-body-container: {
- max-height: 280px;
- };
- }
- }
</style>
<dialog is="cr-dialog" id="clearBrowsingDataDialog"
on-close="onClearBrowsingDataDialogClose_"
- close-text="$i18n{close}" ignore-popstate>
- <div slot="title">$i18n{clearBrowsingData} - NEW UI</div>
+ close-text="$i18n{close}" ignore-popstate has-tabs>
+ <div slot="title">
+ <div>$i18n{clearBrowsingData}</div>
+ </div>
+ <div slot="header">
+ <paper-tabs noink on-selected-changed="recordTabChange_"
+ selected="{{prefs.browser.last_clear_browsing_data_tab.value}}">
+ <paper-tab>$i18n{basicPageTitle}</paper-tab>
+ <paper-tab>$i18n{advancedPageTitle}</paper-tab>
+ </paper-tabs>
+ </div>
<div slot="body">
- <div class="row">
- $i18n{clearFollowingItemsFrom}
- <settings-dropdown-menu id="clearFrom"
- label="$i18n{clearFollowingItemsFrom}"
- pref="{{prefs.browser.clear_data.time_period}}"
- menu-options="[[clearFromOptions_]]">
- </settings-dropdown-menu>
- </div>
- <!-- Note: whether these checkboxes are checked are ignored if deleting
- history is disabled (i.e. supervised users, policy), so it's OK to
- have a hidden checkbox that's also checked (as the C++ accounts for
- whether a user is allowed to delete history independently). -->
- <settings-checkbox id="browsingCheckbox" class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.browsing_history}}"
- label="$i18n{clearBrowsingHistory}"
- sub-label="[[counters_.browsing_history]]"
- disabled="[[clearingInProgress_]]"
- hidden="[[isSupervised_]]">
- </settings-checkbox>
- <settings-checkbox id="downloadCheckbox" class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.download_history}}"
- label="$i18n{clearDownloadHistory}"
- sub-label="[[counters_.download_history]]"
- disabled="[[clearingInProgress_]]"
- hidden="[[isSupervised_]]">
- </settings-checkbox>
- <settings-checkbox id="cacheCheckbox" class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.cache}}"
- label="$i18n{clearCache}"
- sub-label="[[counters_.cache]]"
- disabled="[[clearingInProgress_]]">
- </settings-checkbox>
- <settings-checkbox id="cookiesCheckbox" class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.cookies}}"
- label="$i18n{clearCookies}"
- sub-label="$i18n{clearCookiesCounter}"
- disabled="[[clearingInProgress_]]">
- </settings-checkbox>
- <settings-checkbox class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.passwords}}"
- label="$i18n{clearPasswords}"
- sub-label="[[counters_.passwords]]"
- disabled="[[clearingInProgress_]]">
- </settings-checkbox>
- <settings-checkbox class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.form_data}}"
- label="$i18n{clearFormData}"
- sub-label="[[counters_.form_data]]"
- disabled="[[clearingInProgress_]]">
- </settings-checkbox>
- <settings-checkbox class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.hosted_apps_data}}"
- label="$i18n{clearHostedAppData}"
- sub-label="[[counters_.hosted_apps_data]]"
- disabled="[[clearingInProgress_]]">
- </settings-checkbox>
- <settings-checkbox class="browsing-data-checkbox"
- pref="{{prefs.browser.clear_data.media_licenses}}"
- label="$i18n{clearMediaLicenses}"
- sub-label="[[counters_.media_licenses]]"
- disabled="[[clearingInProgress_]]">
- </settings-checkbox>
+ <iron-pages id="tabs"
+ selected="[[prefs.browser.last_clear_browsing_data_tab.value]]">
+ <div id="basic-tab">
+ <div class="row time-range-row">
+ <span class="time-range-label">
+ $i18n{clearTimeRange}
+ </span>
+ <settings-dropdown-menu id="clearFromBasic"
+ class="time-range-select"
+ label="$i18n{clearTimeRange}"
+ pref="{{prefs.browser.clear_data.time_period_basic}}"
+ menu-options="[[clearFromOptions_]]">
+ </settings-dropdown-menu>
+ </div>
+ <!-- Note: whether these checkboxes are checked are ignored if
+ deleting history is disabled (i.e. supervised users, policy),
+ so it's OK to have a hidden checkbox that's also checked (as
+ the C++ accounts for whether a user is allowed to delete
+ history independently). -->
+ <settings-checkbox id="browsingCheckboxBasic"
+ pref="{{prefs.browser.clear_data.browsing_history_basic}}"
+ label="$i18n{clearBrowsingHistory}"
+ sub-label-html="[[browsingCheckboxLabel_(
+ isSignedIn_, isSyncingHistory_,
+ '$i18nPolymer{clearBrowsingHistorySummary}',
+ '$i18nPolymer{clearBrowsingHistorySummarySignedIn}',
+ '$i18nPolymer{clearBrowsingHistorySummarySynced}')]]"
+ disabled="[[clearingInProgress_]]"
+ hidden="[[isSupervised_]]">
+ </settings-checkbox>
+ <settings-checkbox id="cookiesCheckboxBasic"
+ class="cookies-checkbox"
+ pref="{{prefs.browser.clear_data.cookies_basic}}"
+ label="$i18n{clearCookies}"
+ sub-label="$i18n{clearCookiesSummary}"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ <settings-checkbox id="cacheCheckboxBasic"
+ class="cache-checkbox"
+ pref="{{prefs.browser.clear_data.cache_basic}}"
+ label="$i18n{clearCache}"
+ sub-label="[[counters_.cache_basic]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ </div>
+ <div id="advanced-tab">
+ <div class="row time-range-row">
+ <span class="time-range-label">
+ $i18n{clearTimeRange}
+ </span>
+ <settings-dropdown-menu id="clearFrom"
+ class="time-range-select"
+ label="$i18n{clearTimeRange}"
+ pref="{{prefs.browser.clear_data.time_period}}"
+ menu-options="[[clearFromOptions_]]">
+ </settings-dropdown-menu>
+ </div>
+ <settings-checkbox id="browsingCheckbox"
+ pref="{{prefs.browser.clear_data.browsing_history}}"
+ label="$i18n{clearBrowsingHistory}"
+ sub-label="[[counters_.browsing_history]]"
+ disabled="[[clearingInProgress_]]"
+ hidden="[[isSupervised_]]">
+ </settings-checkbox>
+ <settings-checkbox id="downloadCheckbox"
+ pref="{{prefs.browser.clear_data.download_history}}"
+ label="$i18n{clearDownloadHistory}"
+ sub-label="[[counters_.download_history]]"
+ disabled="[[clearingInProgress_]]"
+ hidden="[[isSupervised_]]">
+ </settings-checkbox>
+ <settings-checkbox id="cookiesCheckbox"
+ class="cookies-checkbox"
+ pref="{{prefs.browser.clear_data.cookies}}"
+ label="$i18n{clearCookies}"
+ sub-label="[[counters_.cookies]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ <settings-checkbox id="cacheCheckbox"
+ class="cache-checkbox"
+ pref="{{prefs.browser.clear_data.cache}}"
+ label="$i18n{clearCache}"
+ sub-label="[[counters_.cache]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ <settings-checkbox
+ pref="{{prefs.browser.clear_data.passwords}}"
+ label="$i18n{clearPasswords}"
+ sub-label="[[counters_.passwords]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ <settings-checkbox
+ pref="{{prefs.browser.clear_data.form_data}}"
+ label="$i18n{clearFormData}"
+ sub-label="[[counters_.form_data]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ <settings-checkbox
+ pref="{{prefs.browser.clear_data.site_settings}}"
+ label="[[siteSettingsLabel_(
+ '$i18nPolymer{siteSettings}',
+ '$i18nPolymer{contentSettings}')]]"
+ sub-label="[[counters_.site_settings]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ <settings-checkbox
+ pref="{{prefs.browser.clear_data.hosted_apps_data}}"
+ label="$i18n{clearHostedAppData}"
+ sub-label="[[counters_.hosted_apps_data]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ <settings-checkbox
+ pref="{{prefs.browser.clear_data.media_licenses}}"
+ label="$i18n{clearMediaLicenses}"
+ sub-label="[[counters_.media_licenses]]"
+ disabled="[[clearingInProgress_]]">
+ </settings-checkbox>
+ </div>
+ </iron-pages>
</div>
<div slot="button-container">
<paper-spinner active="[[clearingInProgress_]]"></paper-spinner>
@@ -192,25 +258,9 @@
<paper-button id="clearBrowsingDataConfirm"
class="action-button" disabled="[[clearingInProgress_]]"
on-tap="onClearBrowsingDataTap_">
- $i18n{clearBrowsingData}
+ $i18n{clearData}
</paper-button>
</div>
- <div slot="footer">
- <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>
</dialog>
<template is="dom-if" if="[[showImportantSitesDialog_]]">
@@ -219,13 +269,12 @@
<div slot="title">
$i18n{clearBrowsingData}
<div class="secondary">
- <template is="dom-if"
- if="[[!prefs.browser.clear_data.cache.value]]">
+ <span hidden$="[[showImportantSitesCacheSubtitle_]]">
$i18n{importantSitesSubtitleCookies}
- </template>
- <template is="dom-if" if="[[prefs.browser.clear_data.cache.value]]">
+ </span>
+ <span hidden$="[[!showImportantSitesCacheSubtitle_]]">
$i18n{importantSitesSubtitleCookiesAndCache}
- </template>
+ </span>
</div>
</div>
<div slot="body">
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.js b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.js
index b0c9479add2..b3f5ea698f8 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.js
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_tabs.js
@@ -12,7 +12,7 @@
Polymer({
is: 'settings-clear-browsing-data-dialog-tabs',
- behaviors: [WebUIListenerBehavior],
+ behaviors: [WebUIListenerBehavior, settings.RouteObserverBehavior],
properties: {
/**
@@ -45,11 +45,11 @@ Polymer({
readOnly: true,
type: Array,
value: [
- {value: 0, name: loadTimeData.getString('clearDataHour')},
- {value: 1, name: loadTimeData.getString('clearDataDay')},
- {value: 2, name: loadTimeData.getString('clearDataWeek')},
- {value: 3, name: loadTimeData.getString('clearData4Weeks')},
- {value: 4, name: loadTimeData.getString('clearDataEverything')},
+ {value: 0, name: loadTimeData.getString('clearPeriodHour')},
+ {value: 1, name: loadTimeData.getString('clearPeriod24Hours')},
+ {value: 2, name: loadTimeData.getString('clearPeriod7Days')},
+ {value: 3, name: loadTimeData.getString('clearPeriod4Weeks')},
+ {value: 4, name: loadTimeData.getString('clearPeriodEverything')},
],
},
@@ -73,6 +73,18 @@ Polymer({
value: false,
},
+ /** @private */
+ isSignedIn_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private */
+ isSyncingHistory_: {
+ type: Boolean,
+ value: false,
+ },
+
/** @private {!Array<ImportantSite>} */
importantSites_: {
type: Array,
@@ -90,7 +102,25 @@ Polymer({
},
/** @private */
- showImportantSitesDialog_: {type: Boolean, value: false},
+ showImportantSitesDialog_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private */
+ showImportantSitesCacheSubtitle_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Time in ms, when the dialog was opened.
+ * @private
+ */
+ dialogOpenedTime_: {
+ type: Number,
+ value: 0,
+ }
},
/** @private {settings.ClearBrowsingDataBrowserProxy} */
@@ -98,8 +128,8 @@ Polymer({
/** @override */
ready: function() {
- this.$.clearFrom.menuOptions = this.clearFromOptions_;
- this.addWebUIListener('update-footer', this.updateFooter_.bind(this));
+ this.addWebUIListener(
+ 'update-sync-state', this.updateSyncState_.bind(this));
this.addWebUIListener(
'update-counter-text', this.updateCounterText_.bind(this));
},
@@ -108,6 +138,7 @@ Polymer({
attached: function() {
this.browserProxy_ =
settings.ClearBrowsingDataBrowserProxyImpl.getInstance();
+ this.dialogOpenedTime_ = Date.now();
this.browserProxy_.initialize().then(() => {
this.$.clearBrowsingDataDialog.showModal();
});
@@ -120,20 +151,69 @@ Polymer({
},
/**
- * Updates the footer to show only those sentences that are relevant to this
- * user.
- * @param {boolean} syncing Whether the user is syncing data.
+ * Record visits to the CBD dialog.
+ *
+ * settings.RouteObserverBehavior
+ * @param {!settings.Route} currentRoute
+ * @protected
+ */
+ currentRouteChanged: function(currentRoute) {
+ if (currentRoute == settings.routes.CLEAR_BROWSER_DATA) {
+ chrome.metricsPrivate.recordUserAction('ClearBrowsingData_DialogCreated');
+ this.dialogOpenedTime_ = Date.now();
+ }
+ },
+
+ /**
+ * Updates the history description to show the relevant information
+ * depending on sync and signin state.
+ *
+ * @param {boolean} signedIn Whether the user is signed in.
+ * @param {boolean} syncing Whether the user is syncing history.
* @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;
+ updateSyncState_: function(signedIn, syncing, otherFormsOfBrowsingHistory) {
+ this.isSignedIn_ = signedIn;
+ this.isSyncingHistory_ = syncing;
this.$.clearBrowsingDataDialog.classList.add('fully-rendered');
},
/**
+ * Choose a summary checkbox label.
+ * @param {boolean} isSignedIn
+ * @param {boolean} isSyncingHistory
+ * @param {string} historySummary
+ * @param {string} historySummarySigned
+ * @param {string} historySummarySynced
+ * @return {string}
+ * @private
+ */
+ browsingCheckboxLabel_: function(
+ isSignedIn, isSyncingHistory, historySummary, historySummarySigned,
+ historySummarySynced) {
+ if (isSyncingHistory) {
+ return historySummarySynced;
+ } else if (isSignedIn) {
+ return historySummarySigned;
+ }
+ return historySummary;
+ },
+
+ /**
+ * Choose a content/site settings label.
+ * @param {string} siteSettings
+ * @param {string} contentSettings
+ * @return {string}
+ * @private
+ */
+ siteSettingsLabel_: function(siteSettings, contentSettings) {
+ return loadTimeData.getBoolean('enableSiteSettings') ? siteSettings :
+ contentSettings;
+ },
+
+ /**
* Updates the text of a browsing data counter corresponding to the given
* preference.
* @param {string} prefName Browsing data type deletion preference.
@@ -154,8 +234,10 @@ Polymer({
shouldShowImportantSites_: function() {
if (!this.importantSitesFlagEnabled_)
return false;
- if (!this.$.cookiesCheckbox.checked)
+ var tab = this.$.tabs.selectedItem;
+ if (!tab.querySelector('.cookies-checkbox').checked) {
return false;
+ }
var haveImportantSites = this.importantSites_.length > 0;
chrome.send(
@@ -170,12 +252,13 @@ Polymer({
*/
onClearBrowsingDataTap_: function() {
if (this.shouldShowImportantSites_()) {
+ var tab = this.$.tabs.selectedItem;
this.showImportantSitesDialog_ = true;
+ this.showImportantSitesCacheSubtitle_ =
+ tab.querySelector('.cache-checkbox').checked;
this.$.clearBrowsingDataDialog.close();
// Show important sites dialog after dom-if is applied.
- this.async(function() {
- this.$$('#importantSitesDialog').showModal();
- });
+ this.async(() => this.$$('#importantSitesDialog').showModal());
} else {
this.clearBrowsingData_();
}
@@ -198,21 +281,31 @@ Polymer({
*/
clearBrowsingData_: function() {
this.clearingInProgress_ = true;
+ var tab = this.$.tabs.selectedItem;
- var checkboxes = this.root.querySelectorAll('.browsing-data-checkbox');
+ checkboxes = tab.querySelectorAll('settings-checkbox');
var dataTypes = [];
checkboxes.forEach((checkbox) => {
if (checkbox.checked)
dataTypes.push(checkbox.pref.key);
});
- var timePeriod = this.$.clearFrom.pref.value;
+ var timePeriod = tab.querySelector('.time-range-select').pref.value;
+
+ if (tab.id == 'basic-tab') {
+ chrome.metricsPrivate.recordUserAction('ClearBrowsingData_BasicTab');
+ } else {
+ chrome.metricsPrivate.recordUserAction('ClearBrowsingData_AdvancedTab');
+ }
this.browserProxy_
.clearBrowsingData(dataTypes, timePeriod, this.importantSites_)
.then(shouldShowNotice => {
this.clearingInProgress_ = false;
this.showHistoryDeletionDialog_ = shouldShowNotice;
+ chrome.metricsPrivate.recordMediumTime(
+ 'History.ClearBrowsingData.TimeSpentInDialog',
+ Date.now() - this.dialogOpenedTime_);
if (!shouldShowNotice)
this.closeDialogs_();
});
@@ -255,4 +348,20 @@ Polymer({
this.showHistoryDeletionDialog_ = false;
this.closeDialogs_();
},
+
+ /**
+ * Records an action when the user changes between the basic and advanced tab.
+ * @param {!Event} event
+ * @private
+ */
+ recordTabChange_: function(event) {
+ if (event.detail.value == 0) {
+ chrome.metricsPrivate.recordUserAction(
+ 'ClearBrowsingData_SwitchTo_BasicTab');
+ } else {
+ chrome.metricsPrivate.recordUserAction(
+ 'ClearBrowsingData_SwitchTo_AdvancedTab');
+ }
+ },
+
});
diff --git a/chromium/chrome/browser/resources/settings/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
index bec907b35a0..a0f14ce056a 100644
--- a/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/compiled_resources2.gyp
@@ -4,14 +4,6 @@
{
'targets': [
{
- 'target_name': 'direction_delegate',
- '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': 'extension_control_browser_proxy',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
index 4dca0444b47..b46ee716595 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -25,7 +25,7 @@
display: flex;
/* Additional margin in case subLabel needs more than one line. */
margin-bottom: 4px;
- margin-top: 4px;
+ margin-top: var(--settings-checkbox-margin-top, 4px);
width: 100%;
}
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
index 7776cccd157..3e6a81d6d48 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
@@ -53,7 +53,7 @@
}
</style>
<div id="outerRow" noSubLabel$="[[!subLabel]]">
- <div class="flex" id="labelWrapper" hidden="[[!label]]">
+ <div class="flex" id="labelWrapper" hidden$="[[!label]]">
<div id="label" class="label">[[label]]</div>
<div id="subLabel" class="secondary label">[[subLabel]]</div>
</div>
@@ -63,7 +63,8 @@
</cr-policy-pref-indicator>
</template>
<paper-toggle-button id="control" checked="{{checked}}"
- on-change="notifyChangedByUserInteraction" aria-labelledby="label"
+ on-change="notifyChangedByUserInteraction"
+ aria-label$="[[getAriaLabel_(label, ariaLabel)]]"
aria-describedby="subLabel" on-up="resetTrackLock_"
disabled="[[controlDisabled_(disabled, pref)]]"
on-tap="onToggleTap_">
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.js b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.js
index 1ac827c9fd8..96c789995a9 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.js
+++ b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.js
@@ -12,6 +12,13 @@ Polymer({
behaviors: [SettingsBooleanControlBehavior],
properties: {
+ ariaLabel: {
+ type: String,
+ reflectToAttribute: false, // Handled by #control.
+ observer: 'onAriaLabelSet_',
+ value: '',
+ },
+
elideLabel: {
type: Boolean,
reflectToAttribute: true,
@@ -32,6 +39,26 @@ Polymer({
},
/**
+ * Removes the aria-label attribute if it's added by $i18n{...}.
+ * @private
+ */
+ onAriaLabelSet_: function() {
+ if (this.hasAttribute('aria-label')) {
+ let ariaLabel = this.ariaLabel;
+ this.removeAttribute('aria-label');
+ this.ariaLabel = ariaLabel;
+ }
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getAriaLabel_: function() {
+ return this.label || this.ariaLabel;
+ },
+
+ /**
* Handle taps directly on the toggle (see: onLabelWrapperTap_ for non-toggle
* taps).
* @param {!Event} e
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 40a923df826..0b573e387a1 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
@@ -55,7 +55,7 @@
<settings-toggle-button class="first"
pref="{{prefs.settings.resolve_timezone_by_geolocation}}"
id="timeZoneAutoDetect"
- aria-labelledby="timezoneGeolocateToggleLabel">
+ aria-label="$i18n{timeZoneGeolocation}">
</settings-toggle-button>
</template>
</div>
diff --git a/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
index 14450adbb38..1f57d004daf 100644
--- a/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
@@ -110,6 +110,7 @@
'target_name': 'night_light_slider',
'dependencies': [
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp:paper-inky-focus-behavior-extracted',
'../prefs/compiled_resources2.gyp:prefs_behavior',
],
diff --git a/chromium/chrome/browser/resources/settings/device_page/display.html b/chromium/chrome/browser/resources/settings/device_page/display.html
index 6d2b3abf188..73d02acd988 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display.html
+++ b/chromium/chrome/browser/resources/settings/device_page/display.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
@@ -21,46 +22,43 @@
<dom-module id="settings-display">
<template>
<style include="settings-shared md-select iron-flex iron-flex-alignment">
- .settings-box.indented {
- -webkit-margin-start: 20px;
- align-self: stretch;
- padding: 0;
- }
-
- :host {
- --paper-tabs-selection-bar-color: var(--paper-blue-500);
- }
-
- .display-tabs {
- width: 100%;
- }
-
- display-layout {
- align-self: stretch;
- flex: 1 1;
- height: 300px;
- margin: 10px;
- }
-
- .textarea {
- margin: 10px 0;
- }
-
- .settings-box > paper-button:first-child {
- -webkit-padding-start: 0
- }
-
- paper-tab {
- text-transform: uppercase;
- }
-
- #controlsDiv > .settings-box:first-of-type {
- border-top: none;
- }
-
- #nightLightSlider {
- margin-top: 20px;
- }
+ .indented {
+ -webkit-margin-start: var(--cr-section-indent-padding);
+ align-self: stretch;
+ padding: 0;
+ }
+
+ .display-tabs {
+ width: 100%;
+ }
+
+ display-layout {
+ align-self: stretch;
+ flex: 1 1;
+ height: 300px;
+ margin: 10px;
+ }
+
+ .text-area {
+ margin: 10px 0;
+ }
+
+ .settings-box > paper-button:first-child {
+ -webkit-padding-start: 0
+ }
+
+ paper-tab {
+ text-transform: uppercase;
+ }
+
+ #controlsDiv > .settings-box:first-of-type {
+ border-top: none;
+ }
+
+ #nightLightSlider {
+ flex-grow: 1;
+ margin-top: 20px;
+ }
</style>
<div class="settings-box first layout vertical self-stretch">
<h2 class="layout self-start">
@@ -108,7 +106,7 @@
<div class="settings-box indented two-line">
<div class="start">
<div id="displayUnifiedDesktopCheckboxLabel">
- $i18n{displayUnfiedDesktop}
+ $i18n{displayUnifiedDesktop}
</div>
<div class="secondary">
[[getUnifiedDesktopText_(unifiedDesktopMode_)]]
@@ -141,13 +139,13 @@
</template>
<div class="settings-box indented two-line">
- <div class="start textarea layout vertical">
+ <div class="start text-area layout vertical">
<div>$i18n{displayResolutionTitle}</div>
<div class="secondary layout self-start">
[[getResolutionText_(selectedDisplay, selectedModePref_.value)]]
</div>
</div>
- <settings-slider disabled="[[!enableSetResolution_(selectedDisplay)]]"
+ <settings-slider disabled="[[selectedDisplay.isTabletMode]]"
tick-values="[[modeValues_]]" pref="{{selectedModePref_}}"
on-change="onSelectedModeChange_">
</settings-slider>
@@ -155,11 +153,12 @@
<template is="dom-if" if="[[!unifiedDesktopMode_]]" restamp>
<div class="settings-box indented">
- <div id="displayOrientation" class="start textarea">
+ <div id="displayOrientation" class="start text-area">
$i18n{displayOrientation}
</div>
<div class="md-select-wrapper">
<select class="md-select" value="[[selectedDisplay.rotation]]"
+ disabled="[[selectedDisplay.isTabletMode]]"
aria-labelledby="displayOrientation"
on-change="onOrientationChange_">
<option value="0">$i18n{displayOrientationStandard}</option>
@@ -172,19 +171,10 @@
</div>
</template>
- <div id="overscan" class="settings-box indented two-line"
- on-tap="onOverscanTap_" hidden$="[[selectedDisplay.isInternal]]"
- actionable>
- <div class="start">
- $i18n{displayOverscanPageTitle}
- <div class="secondary" id="displayOverscanSecondary">
- $i18n{displayOverscanPageText}
- </div>
- </div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{displayOverscanPageTitle}"
- aria-describedby="displayOverscanSecondary"></button>
- </div>
+ <button is="cr-link-row" icon-class="subpage-arrow" class="indented hr"
+ id="overscan" label="$i18n{displayOverscanPageTitle}"
+ sub-label="$i18n{displayOverscanPageText}" on-tap="onOverscanTap_">
+ </button>
<settings-display-overscan-dialog id="displayOverscan"
display-id="{{overscanDisplayId}}"
@@ -219,7 +209,7 @@
class="settings-box continuation start layout vertical">
<!-- Color temperature slider -->
<div class="settings-box indented continuation">
- <div class="start textarea" id="colorTemperatureLabel">
+ <div class="start text-area" id="colorTemperatureLabel">
$i18n{displayNightLightTemperatureLabel}
</div>
<settings-slider id="colorTemperatureSlider"
@@ -231,7 +221,7 @@
</div>
<!-- Schedule settings -->
<div class="settings-box indented">
- <div id="nightLightScheduleLabel" class="start textarea">
+ <div id="nightLightScheduleLabel" class="start text-area">
$i18n{displayNightLightScheduleLabel}
</div>
<settings-dropdown-menu
@@ -244,9 +234,9 @@
<!-- Custom schedule slider -->
<div class="settings-box indented continuation">
<iron-collapse id="nightLightCustomScheduleCollapse"
- class="start textarea layout vertical"
+ class="start text-area layout vertical"
opened="[[shouldOpenCustomScheduleCollapse_]]">
- <div class="settings-box indented continuation">
+ <div class="settings-box continuation self-stretch">
<night-light-slider id="nightLightSlider" prefs="{{prefs}}">
</night-light-slider>
</div>
diff --git a/chromium/chrome/browser/resources/settings/device_page/night_light_slider.html b/chromium/chrome/browser/resources/settings/device_page/night_light_slider.html
index 247f30fa4f7..84bd90b309d 100644
--- a/chromium/chrome/browser/resources/settings/device_page/night_light_slider.html
+++ b/chromium/chrome/browser/resources/settings/device_page/night_light_slider.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-inky-focus-behavior.html">
<link rel="import" href="../prefs/prefs_behavior.html">
@@ -16,7 +17,7 @@
display: inline-block;
position: relative;
user-select: none;
- width: 570px;
+ width: 100%;
}
#sliderBar {
@@ -143,11 +144,13 @@
<div id="labelContainer">
<div id="startLabel" class="label"
aria-label="$i18n{displayNightLightStartTime}">
- [[startTime_]]
+ [[getTimeString_(prefs.ash.night_light.custom_start_time.value,
+ shouldUse24Hours_)]]
</div>
<div id="endLabel" class="label"
aria-label="$i18n{displayNightLightStopTime}">
- [[endTime_]]
+ [[getTimeString_(prefs.ash.night_light.custom_end_time.value,
+ shouldUse24Hours_)]]
</div>
</div>
<div id="sliderBar">
diff --git a/chromium/chrome/browser/resources/settings/device_page/night_light_slider.js b/chromium/chrome/browser/resources/settings/device_page/night_light_slider.js
index 84210288d1f..239a9f42f04 100644
--- a/chromium/chrome/browser/resources/settings/device_page/night_light_slider.js
+++ b/chromium/chrome/browser/resources/settings/device_page/night_light_slider.js
@@ -22,21 +22,16 @@ Polymer({
behaviors: [
PrefsBehavior,
Polymer.IronA11yKeysBehavior,
+ Polymer.IronResizableBehavior,
Polymer.PaperInkyFocusBehavior,
],
properties: {
/**
- * The start knob time as a string to be shown on the start label bubble.
+ * Whether the element is ready and fully rendered.
* @private
*/
- startTime_: String,
-
- /**
- * The end knob time as a string to be shown on the end label bubble.
- * @private
- */
- endTime_: String,
+ isReady_: Boolean,
/**
* Whether the window is in RTL locales.
@@ -52,9 +47,13 @@ Polymer({
shouldUse24Hours_: Boolean,
},
+ listeners: {
+ 'iron-resize': 'onResize_',
+ },
+
observers: [
- 'customTimesChanged_(prefs.ash.night_light.custom_start_time.*, ' +
- 'prefs.ash.night_light.custom_end_time.*)',
+ 'updateKnobs_(prefs.ash.night_light.custom_start_time.*, ' +
+ 'prefs.ash.night_light.custom_end_time.*, isRTL_, isReady_)',
'hourFormatChanged_(prefs.settings.clock.use_24hour_clock.*)',
],
@@ -72,11 +71,6 @@ Polymer({
/** @override */
attached: function() {
- this.isRTL_ = window.getComputedStyle(this).direction == 'rtl';
- },
-
- /** @override */
- ready: function() {
// Build the legend markers.
var markersContainer = this.$.markersContainer;
var width = markersContainer.offsetWidth;
@@ -86,6 +80,25 @@ Polymer({
markersContainer.appendChild(marker);
marker.style.left = (i * 100 / HOURS_PER_DAY) + '%';
}
+
+ this.isRTL_ = window.getComputedStyle(this).direction == 'rtl';
+
+ this.async(function() {
+ // This is needed to make sure that the positions of the knobs and their
+ // label bubbles are correctly updated when the display settings page is
+ // opened for the first time after login. The page need to be fully
+ // rendered.
+ this.isReady_ = true;
+ });
+ },
+
+ /**
+ * Invoked when the element is resized and the knobs positions need to be
+ * updated.
+ * @private
+ */
+ onResize_: function() {
+ this.updateKnobs_();
},
/**
@@ -96,9 +109,6 @@ Polymer({
hourFormatChanged_: function() {
this.shouldUse24Hours_ = /** @type {boolean} */ (
this.getPref('settings.clock.use_24hour_clock').value);
-
- // Refresh the slider.
- this.customTimesChanged_();
},
/**
@@ -265,28 +275,28 @@ Polymer({
* 00:00) to its language-sensitive time string representation.
* @param {number} offsetMinutes The time of day represented as the number of
* minutes from 00:00.
+ * @param {boolean} shouldUse24Hours Whether to use the 24-hour time format.
* @return {string}
* @private
*/
- offsetMinutesToTimeString_: function(offsetMinutes) {
+ getTimeString_: function(offsetMinutes, shouldUse24Hours) {
var hour = Math.floor(offsetMinutes / 60);
var minute = Math.floor(offsetMinutes % 60);
- return this.getLocaleTimeString_(hour, minute, this.shouldUse24Hours_);
+ return this.getLocaleTimeString_(hour, minute, shouldUse24Hours);
},
/**
- * Handles changes in the start and end times prefs.
+ * Using the current start and end times prefs, this function updates the
+ * knobs and their label bubbles and refreshes the slider.
* @private
*/
- customTimesChanged_: function() {
+ updateKnobs_: function() {
var startOffsetMinutes = /** @type {number} */ (
this.getPref('ash.night_light.custom_start_time').value);
- this.startTime_ = this.offsetMinutesToTimeString_(startOffsetMinutes);
this.updateKnobLeft_(this.$.startKnob, startOffsetMinutes);
var endOffsetMinutes = /** @type {number} */ (
this.getPref('ash.night_light.custom_end_time').value);
- this.endTime_ = this.offsetMinutesToTimeString_(endOffsetMinutes);
this.updateKnobLeft_(this.$.endKnob, endOffsetMinutes);
this.refresh_();
},
diff --git a/chromium/chrome/browser/resources/settings/direction_delegate.html b/chromium/chrome/browser/resources/settings/direction_delegate.html
deleted file mode 100644
index be62c99a60c..00000000000
--- a/chromium/chrome/browser/resources/settings/direction_delegate.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<link rel="import" href="i18n_setup.html">
-<link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/html/cr.html">
-<script src="direction_delegate.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/direction_delegate.js b/chromium/chrome/browser/resources/settings/direction_delegate.js
deleted file mode 100644
index 6d5275337e9..00000000000
--- a/chromium/chrome/browser/resources/settings/direction_delegate.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.exportPath('settings');
-
-cr.define('settings', function() {
- /** @interface */
- class DirectionDelegate {
- /**
- * @return {boolean} Whether the direction of the settings UI is
- * right-to-left.
- */
- isRtl() {}
- }
-
- /** @implements {settings.DirectionDelegate} */
- class DirectionDelegateImpl {
- /** @override */
- isRtl() {
- return loadTimeData.getString('textdirection') == 'rtl';
- }
- }
-
- return {
- DirectionDelegate: DirectionDelegate,
- DirectionDelegateImpl: DirectionDelegateImpl,
- };
-});
diff --git a/chromium/chrome/browser/resources/settings/icons.html b/chromium/chrome/browser/resources/settings/icons.html
index c49d8fa899c..61224dceb7b 100644
--- a/chromium/chrome/browser/resources/settings/icons.html
+++ b/chromium/chrome/browser/resources/settings/icons.html
@@ -59,6 +59,8 @@ List icons here rather than importing large sets of (e.g. Polymer) icons.
<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>
<if expr="chromeos">
<g id="computer"><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-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="devices-other"><path d="M3 6h18V4H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4v-2H3V6zm10 6H9v1.78c-.61.55-1 1.33-1 2.22s.39 1.67 1 2.22V20h4v-1.78c.61-.55 1-1.34 1-2.22s-.39-1.67-1-2.22V12zm-2 5.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.5zM22 8h-6c-.5 0-1 .5-1 1v10c0 .5.5 1 1 1h6c.5 0 1-.5 1-1V9c0-.5-.5-1-1-1zm-1 10h-4v-8h4v8z"></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>
diff --git a/chromium/chrome/browser/resources/settings/images/settings_icon_visibility.svg b/chromium/chrome/browser/resources/settings/images/settings_icon_visibility.svg
deleted file mode 100644
index af7b42a957d..00000000000
--- a/chromium/chrome/browser/resources/settings/images/settings_icon_visibility.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#757575" preserveAspectRatio="xMidYMid meet"><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></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/settings/images/settings_icon_visibility_off.svg b/chromium/chrome/browser/resources/settings/images/settings_icon_visibility_off.svg
deleted file mode 100644
index bce77739f74..00000000000
--- a/chromium/chrome/browser/resources/settings/images/settings_icon_visibility_off.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#757575" preserveAspectRatio="xMidYMid meet"><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"/></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 8cbb7f9805e..18f9191b2ff 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/internet_page/compiled_resources2.gyp
@@ -22,6 +22,7 @@
'target_name': 'internet_config',
'dependencies': [
'../compiled_resources2.gyp:route',
+ '<(DEPTH)/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp:network_config',
'<(DEPTH)/ui/webui/resources/cr_elements/chromeos/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',
@@ -71,19 +72,6 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'network_config_input',
- 'dependencies': [],
- 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'network_config_select',
- 'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
- ],
- 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
'target_name': 'network_proxy_section',
'dependencies': [
'../compiled_resources2.gyp:route',
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_config.html b/chromium/chrome/browser/resources/settings/internet_page/internet_config.html
index 6c2a1f2fdd1..fd8d716df89 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_config.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_config.html
@@ -1,14 +1,12 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_config.html">
<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_icon.html">
<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.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-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="internet_shared_css.html">
-<link rel="import" href="network_config_input.html">
-<link rel="import" href="network_config_select.html">
<dom-module id="settings-internet-config">
<template>
@@ -20,7 +18,7 @@
<div class="start layout horizontal center">
<cr-network-icon network-state="[[networkProperties_]]" is-list-item>
</cr-network-icon>
- <div class="title">[[title_]]</div>
+ <div class="title">[[getTitle_(networkProperties_.*)]]</div>
</div>
<div id="buttonDiv">
<paper-button class="secondary-button" on-tap="onCancelTap_">
@@ -28,79 +26,27 @@
</paper-button>
<template is="dom-if" if="[[guid_]]">
<paper-button class="primary-button" on-tap="onSaveTap_"
- disabled="[[!saveIsEnabled_(configProperties_.*)]]">
+ disabled="[[!enableSave_]]">
$i18n{save}
</paper-button>
</template>
<template is="dom-if" if="[[!guid_]]">
<paper-button class="primary-button" on-tap="onConnectTap_"
- disabled="[[!connectIsEnabled_(configProperties_.*)]]">
+ disabled="[[!enableConnect_]]">
$i18n{networkButtonConnect}
</paper-button>
</template>
</div>
</div>
- <!-- WiFi -->
- <template is="dom-if"
- if="[[isType_(NetworkType_.WI_FI, networkProperties_.Type)]]">
- <div class="settings-box">
- <div id="shareLabel" class="start">$i18n{networkConfigShare}</div>
- <paper-toggle-button id="share" checked="{{shareNetwork_}}"
- disabled="[[!shareIsEnabled_(guid_, configProperties_.*)]]"
- aria-labelledby="shareLabel">
- </paper-toggle-button>
- </div>
- <network-config-input id="ssid" label="$i18n{OncWiFi-SSID}"
- value="{{configProperties_.WiFi.SSID}}" disabled="[[guid_]]">
- </network-config-input>
- <network-config-select id="security" label="$i18n{OncWiFi-Security}"
- value="{{configProperties_.WiFi.Security}}" disabled="[[guid_]]"
- items="[[securityItems_]]" onc-prefix="WiFi.Security">
- </network-config-select>
- <network-config-input label="$i18n{OncWiFi-Passphrase}"
- value="{{configProperties_.WiFi.Passphrase}}"
- hidden="[[!configRequiresPassphrase_(configProperties_.*)]]">
- </network-config-input>
- </template>
-
- <!-- EAP (WiFi, WiMAX, Ethernet) -->
- <template is="dom-if" if="[[showEap_]]">
- <network-config-select id="outer" label="$i18n{OncEAP-Outer}"
- value="{{eapProperties_.Outer}}" items="[[eapOuterItems_]]"
- onc-prefix="EAP.Outer" hidden="[[!showEap_.Outer]]">
- </network-config-select>
- <network-config-select id="inner" label="$i18n{OncEAP-Inner}"
- value="{{eapProperties_.Inner}}"
- items="[[getEapInnerItems_(eapProperties_.Outer)]]"
- onc-prefix="EAP.Inner" hidden="[[!showEap_.Inner]]">
- </network-config-select>
- <network-config-input label="$i18n{OncEAP-SubjectMatch}"
- value="{{eapProperties_.SubjectMatch}}"
- hidden="[[!showEap_.SubjectMatch]]">
- </network-config-input>
- <network-config-input label="$i18n{OncEAP-Identity}"
- value="{{eapProperties_.Identity}}">
- </network-config-input>
- <network-config-input label="$i18n{OncEAP-Password}"
- value="{{eapProperties_.Password}}" hidden="[[!showEap_.Password]]">
- </network-config-input>
- <network-config-input label="$i18n{OncEAP-AnonymousIdentity}"
- value="{{eapProperties_.AnonymousIdentity}}"
- hidden="[[!showEap_.AnonymousIdentity]]">
- </network-config-input>
- <div class="settings-box">
- <div id="saveCredentialsLabel" class="start">
- $i18n{networkConfigSaveCredentials}
- </div>
- <paper-toggle-button checked="{{eapProperties_.SaveCredentials}}"
- aria-labelledby="saveCredentialsLabel">
- </paper-toggle-button>
- </div>
- </template>
-
- <!-- TODO(stevenjb): Error message for config or cert failure -->
-
+ <div class="settings-box">
+ <network-config id="networkConfig" class="flex"
+ networking-private="[[networkingPrivate]]"
+ network-properties="{{networkProperties_}}"
+ enable-connect="{{enableConnect_}}" enable-save="{{enableSave_}}"
+ on-close="close_">
+ </network-config>
+ </div>
</template>
<script src="internet_config.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_config.js b/chromium/chrome/browser/resources/settings/internet_page/internet_config.js
index 4760b53a5e0..a74aa471f2e 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_config.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_config.js
@@ -4,8 +4,7 @@
/**
* @fileoverview
- * 'settings-internet-config' provides configuration of authentication
- * properties for new and existing networks.
+ * 'settings-internet-config' is a Settings wrapper for network-config.
*/
Polymer({
is: 'settings-internet-config',
@@ -26,167 +25,21 @@ Polymer({
*/
guid_: String,
- /**
- * The current properties if an existing network being configured.
- * This will be undefined when configuring a new network.
- * @private {!chrome.networkingPrivate.NetworkProperties|undefined}
- */
- networkProperties_: Object,
-
- /** Set if |guid_| is not empty once networkProperties_ are received. */
- propertiesReceived_: Boolean,
-
- /** Set once properties have been sent; prevents multiple saves. */
- propertiesSent_: Boolean,
-
- /**
- * The configuration properties for the network. |configProperties_.Type|
- * will always be defined as the network type being configured.
- * @private {!chrome.networkingPrivate.NetworkConfigProperties}
- */
- configProperties_: Object,
-
- /**
- * Reference to the EAP properties for the current type or null if all EAP
- * properties should be hidden (e.g. WiFi networks with non EAP Security).
- * Note: even though this references an entry in configProperties_, we
- * need to send a separate notification when it changes for data binding
- * (e.g. by using 'set').
- * @private {?chrome.networkingPrivate.EAPProperties}
- */
- eapProperties_: {
- type: Object,
- value: null,
- },
-
- /**
- * The title to display (network name or type).
- * @private
- */
- title_: {
- type: String,
- computed: 'computeTitle_(networkProperties_)',
- },
-
- /**
- * Whether this network should be shared with other users of the device.
- * @private
- */
- shareNetwork_: {
- type: Boolean,
- value: true,
- },
+ /** @private */
+ enableConnect_: String,
- /**
- * Saved security value, used to detect when Security changes.
- * @private
- */
- savedSecurity_: String,
+ /** @private */
+ enableSave_: String,
/**
- * Dictionary of boolean values determining which EAP properties to show,
- * or null to hide all EAP settings.
- * @type {?{
- * Outer: boolean,
- * Inner: boolean,
- * ServerCA: boolean,
- * SubjectMatch: boolean,
- * UserCert: boolean,
- * Password: boolean,
- * AnonymousIdentity: boolean,
- * }}
- * @private
+ * The current properties if an existing network is being configured, or
+ * a minimal subset for a new network. Note: network-config may modify
+ * this (specifically .name).
+ * @private {!chrome.networkingPrivate.NetworkProperties}
*/
- showEap_: {
- type: Object,
- value: null,
- },
-
- /**
- * Object providing network type values for data binding. Note: Currently
- * we only support WiFi, but support for other types will be following
- * shortly.
- * @const
- * @private
- */
- NetworkType_: {
- type: Object,
- value: {
- ETHERNET: CrOnc.Type.ETHERNET,
- VPN: CrOnc.Type.VPN,
- WI_FI: CrOnc.Type.WI_FI,
- WI_MAX: CrOnc.Type.WI_MAX,
- },
- readOnly: true
- },
-
- /**
- * Array of values for the WiFi Security dropdown.
- * @type {!Array<string>}
- * @const
- * @private
- */
- securityItems_: {
- type: Array,
- readOnly: true,
- value: [
- CrOnc.Security.NONE, CrOnc.Security.WEP_PSK, CrOnc.Security.WPA_PSK,
- CrOnc.Security.WPA_EAP
- ],
- },
-
- /**
- * Array of values for the EAP Method (Outer) dropdown.
- * @type {!Array<string>}
- * @const
- * @private
- */
- eapOuterItems_: {
- type: Array,
- readOnly: true,
- value: [
- CrOnc.EAPType.LEAP, CrOnc.EAPType.PEAP, CrOnc.EAPType.EAP_TLS,
- CrOnc.EAPType.EAP_TTLS
- ],
- },
-
- /**
- * Array of values for the EAP EAP Phase 2 authentication (Inner) dropdown
- * when the Outer type is PEAP.
- * @type {!Array<string>}
- * @const
- * @private
- */
- eapInnerItemsPeap_: {
- type: Array,
- readOnly: true,
- value: ['Automatic', 'MD5', 'MSCHAPv2'],
- },
-
- /**
- * Array of values for the EAP EAP Phase 2 authentication (Inner) dropdown
- * when the Outer type is EAP-TTLS.
- * @type {!Array<string>}
- * @const
- * @private
- */
- eapInnerItemsTtls_: {
- type: Array,
- readOnly: true,
- value: ['Automatic', 'MD5', 'MSCHAP', 'MSCHAPv2', 'PAP', 'CHAP', 'GTC'],
- },
+ networkProperties_: Object,
},
- observers: [
- 'updateConfigProperties_(networkProperties_)',
- 'updateWiFiSecurity_(configProperties_.WiFi.Security)',
- 'updateEapOuter_(eapProperties_.Outer)',
- 'updateShowEap_(eapProperties_.*)',
- ],
-
- /** @const */
- MIN_PASSPHRASE_LENGTH: 5,
-
/**
* settings.RouteObserverBehavior
* @param {!settings.Route} route
@@ -196,10 +49,6 @@ Polymer({
if (route != settings.routes.NETWORK_CONFIG)
return;
- this.propertiesSent_ = false;
- this.savedSecurity_ = '';
- this.showEap_ = null;
-
var queryParams = settings.getQueryParameters();
this.guid_ = queryParams.get('guid') || '';
@@ -207,17 +56,24 @@ Polymer({
// configurations until the current properties are loaded.
var name = queryParams.get('name') || '';
var typeParam = queryParams.get('type');
- var type = typeParam ? CrOnc.getValidType(typeParam) : CrOnc.Type.WI_FI;
+ var type = (typeParam && CrOnc.getValidType(typeParam)) || CrOnc.Type.WI_FI;
assert(type && type != CrOnc.Type.ALL);
this.networkProperties_ = {
GUID: this.guid_,
Name: name,
Type: type,
};
- if (this.guid_) {
- this.networkingPrivate.getProperties(
- this.guid_, this.getPropertiesCallback_.bind(this));
- }
+
+ // First focus this page (which will focus a button), then init the config
+ // element which will focus an enabled element if any.
+ this.focus();
+ this.$.networkConfig.init();
+ },
+
+ focus() {
+ var e = this.$$('paper-button:not([disabled])');
+ assert(e); // The 'cancel' button should never be disabled.
+ e.focus();
},
/** @private */
@@ -227,322 +83,26 @@ Polymer({
},
/**
- * networkingPrivate.getProperties callback.
- * @param {!chrome.networkingPrivate.NetworkProperties} properties
- * @private
- */
- getPropertiesCallback_: function(properties) {
- if (!properties) {
- // If |properties| is null, the network no longer exists; close the page.
- console.error('Network no longer exists: ' + this.guid_);
- this.close_();
- return;
- }
- this.propertiesReceived_ = true;
- this.networkProperties_ = properties;
-
- // Set the current shareNetwork_ value when porperties are received.
- var source = this.networkProperties_.Source;
- this.shareNetwork_ =
- source == CrOnc.Source.DEVICE || source == CrOnc.Source.DEVICE_POLICY;
- },
-
- /**
* @return {string}
* @private
*/
- computeTitle_: function() {
+ getTitle_: function() {
return this.networkProperties_.Name ||
this.i18n('OncType' + this.networkProperties_.Type);
},
- /**
- * Updates the config properties when |this.networkProperties_| changes.
- * This gets called once when navigating to the page when default properties
- * are set, and again for existing networks when the properties are received.
- * @private
- */
- updateConfigProperties_: function() {
- var properties = this.networkProperties_;
- var configProperties =
- /** @type {chrome.networkingPrivate.NetworkConfigProperties} */ ({
- Name: properties.Name || '',
- Type: properties.Type,
- });
- if (properties.Type == CrOnc.Type.WI_FI) {
- if (properties.WiFi) {
- configProperties.WiFi = {
- AutoConnect: properties.WiFi.AutoConnect,
- EAP: Object.assign({}, properties.WiFi.EAP),
- Passphrase: properties.WiFi.Passphrase,
- SSID: properties.WiFi.SSID,
- Security: properties.WiFi.Security
- };
- } else {
- configProperties.WiFi = {
- AutoConnect: false,
- SSID: '',
- Security: CrOnc.Security.NONE,
- };
- }
- // updateWiFiSecurity_ will ensure that EAP properties are set correctly.
- } else if (properties.Type == CrOnc.Type.ETHERNET) {
- if (properties.Ethernet) {
- configProperties.Ethernet = {
- AutoConnect: properties.Ethernet.AutoConnect,
- EAP: Object.assign({}, properties.Ethernet.EAP),
- };
- configProperties.Ethernet.EAP.Outer =
- configProperties.Ethernet.EAP.Outer || CrOnc.EAPType.LEAP;
- } else {
- configProperties.Ethernet = {
- AutoConnect: false,
- };
- }
- } else if (properties.Type == CrOnc.Type.WI_MAX) {
- if (properties.WiMAX) {
- configProperties.WiMAX = {
- AutoConnect: properties.WiMAX.AutoConnect,
- EAP: Object.assign({}, properties.WiMAX.EAP),
- };
- // WiMAX has no EAP.Outer property, only Identity and Password.
- } else {
- configProperties.WiMAX = {
- AutoConnect: false,
- };
- }
- }
- this.configProperties_ = configProperties;
- this.set('eapProperties_', this.getEap_(this.configProperties_));
- if (!this.eapProperties_)
- this.showEap_ = null;
- },
-
- /**
- * Ensures that the appropriate properties are set or deleted when the
- * Security type changes.
- * @private
- */
- updateWiFiSecurity_: function() {
- if (!this.configProperties_.WiFi)
- return; // May get called when clearing the property.
- var security = this.configProperties_.WiFi.Security || CrOnc.Security.NONE;
- if (security == this.savedSecurity_)
- return;
- this.savedSecurity_ = security;
-
- if (!this.guid_) {
- // Set the default share state for new configurations.
- // TODO(stevenjb): also check login state.
- this.shareNetwork_ = security == CrOnc.Security.NONE;
- }
-
- if (security == CrOnc.Security.WPA_EAP) {
- var eap = this.configProperties_.WiFi.EAP || {};
- eap.Outer = eap.Outer || CrOnc.EAPType.LEAP;
- this.configProperties_.WiFi.EAP = eap;
- this.set('eapProperties_', this.configProperties_.WiFi.EAP);
- } else {
- delete this.configProperties_.WiFi.EAP;
- this.eapProperties_ = null;
- }
- },
-
- /**
- * Ensures that the appropriate EAP properties are created (or deleted when
- * the EAP.Outer property changes.
- * @private
- */
- updateEapOuter_: function() {
- var eap = this.eapProperties_;
- if (!eap || !eap.Outer)
- return;
- var innerItems = this.getEapInnerItems_(eap.Outer);
- if (innerItems.length > 0) {
- if (!eap.Inner || innerItems.indexOf(eap.Inner) < 0)
- this.set('eapProperties_.Inner', innerItems[0]);
- } else {
- this.set('eapProperties_.Inner', undefined);
- }
- },
-
/** @private */
- updateShowEap_: function() {
- if (!this.eapProperties_) {
- this.showEap_ = null;
- return;
- }
- var type = this.configProperties_.Type;
- var outer = this.eapProperties_.Outer;
- this.showEap_ = {
- Outer: type != CrOnc.Type.WI_MAX,
- Inner: outer == CrOnc.EAPType.PEAP || outer == CrOnc.EAPType.EAP_TTLS,
- ServerCA: type != CrOnc.Type.WI_MAX && outer != CrOnc.EAPType.LEAP,
- SubjectMatch: outer == CrOnc.EAPType.EAP_TLS,
- UserCert: outer == CrOnc.EAPType.EAP_TLS,
- Password: outer != CrOnc.EAPType.EAP_TLS,
- AnonymousIdentity:
- outer == CrOnc.EAPType.PEAP || outer == CrOnc.EAPType.EAP_TTLS,
- };
- },
-
- /**
- * @param {!chrome.networkingPrivate.NetworkConfigProperties} properties
- * @return {?chrome.networkingPrivate.EAPProperties}
- * @private
- */
- getEap_: function(properties) {
- if (properties.WiFi)
- return properties.WiFi.EAP || null;
- if (properties.Ethernet)
- return properties.Ethernet.EAP || null;
- if (properties.WiMAX)
- return properties.WiMAX.EAP || null;
- return null;
- },
-
- /**
- * @param {CrOnc.Type} type The type to compare against.
- * @param {CrOnc.Type} networkType The current network type.
- * @return {boolean} True if the network type matches 'type'.
- * @private
- */
- isType_: function(type, networkType) {
- return type == networkType;
- },
-
- /**
- * @return {boolean}
- * @private
- */
- saveIsEnabled_: function() {
- return this.propertiesReceived_ && !this.propertiesSent_;
- },
-
- /**
- * @return {boolean}
- * @private
- */
- connectIsEnabled_: function() {
- if (this.propertiesSent_)
- return false;
- if (this.configProperties_.Type == CrOnc.Type.WI_FI) {
- if (!this.get('WiFi.SSID', this.configProperties_))
- return false;
- if (this.configRequiresPassphrase_()) {
- var passphrase = this.get('WiFi.Passphrase', this.configProperties_);
- if (!passphrase || passphrase.length < this.MIN_PASSPHRASE_LENGTH)
- return false;
- }
- }
- // TODO(stevenjb): Check certificates.
- return true;
- },
-
- /**
- * @return {boolean}
- * @private
- */
- shareIsEnabled_: function() {
- if (this.networkProperties_.Source == CrOnc.Source.DEVICE ||
- this.networkProperties_.Source == CrOnc.Source.DEVICE_POLICY) {
- return false;
- }
- // TODO(stevenjb): Check login state.
-
- if (this.configProperties_.Type == CrOnc.Type.WI_FI) {
- var security = this.get('WiFi.Security', this.configProperties_);
- if (!security || security == CrOnc.Security.NONE) {
- return false;
- } else if (security == CrOnc.Security.WPA_EAP) {
- var outer = this.get('WiFi.EAP.Outer', this.configProperties_);
- if (outer == CrOnc.EAPType.EAP_TLS)
- return false;
- }
- // TODO(stevenjb): Check certificates.
- }
- return true;
+ onCancelTap_: function() {
+ this.close_();
},
/** @private */
onSaveTap_: function() {
- assert(this.guid_);
- if (this.propertiesSent_)
- return;
- this.propertiesSent_ = true;
- var propertiesToSet = Object.assign({}, this.configProperties_);
- propertiesToSet.GUID = this.guid_;
- this.networkingPrivate.setProperties(
- this.guid_, propertiesToSet, this.setPropertiesCallback_.bind(this));
- },
-
- /** @private */
- setPropertiesCallback_: function() {
- var error = chrome.runtime.lastError && chrome.runtime.lastError.message;
- if (error) {
- console.error(
- 'Error setting network properties: ' + this.guid_ + ': ' + error);
- }
- this.close_();
+ this.$.networkConfig.saveOrConnect();
},
/** @private */
onConnectTap_: function() {
- assert(!this.guid_);
- if (this.propertiesSent_)
- return;
- this.propertiesSent_ = true;
- // Create the configuration, then connect to it in the callback.
- this.networkingPrivate.createNetwork(
- this.shareNetwork_, this.configProperties_,
- this.createNetworkCallback_.bind(this));
- },
-
- /**
- * @param {string} guid
- * @private
- */
- createNetworkCallback_: function(guid) {
- var error = chrome.runtime.lastError && chrome.runtime.lastError.message;
- if (error) {
- // TODO(stevenjb): Display error message.
- console.error(
- 'Error creating network type: ' + this.networkProperties_.Type +
- ': ' + error);
- return;
- }
- this.networkProperties_.GUID = guid;
- this.fire('network-connect', {networkProperties: this.networkProperties_});
- this.close_();
- },
-
- /** @private */
- onCancelTap_: function() {
- this.close_();
- },
-
- /**
- * @return boolean
- * @private
- */
- configRequiresPassphrase_: function() {
- if (this.configProperties_.Type != CrOnc.Type.WI_FI)
- return false;
- var security = this.get('WiFi.Security', this.configProperties_);
- return security == CrOnc.Security.WEP_PSK ||
- security == CrOnc.Security.WPA_PSK;
- },
-
- /**
- * @param {string} outer
- * @return {!Array<string>}
- * @private
- */
- getEapInnerItems_: function(outer) {
- if (outer == CrOnc.EAPType.PEAP)
- return this.eapInnerItemsPeap_;
- if (outer == CrOnc.EAPType.EAP_TTLS)
- return this.eapInnerItemsTtls_;
- return [];
+ this.$.networkConfig.saveOrConnect();
},
});
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 1caee855099..ac1652041e5 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,6 +1,7 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_apnlist.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_choose_mobile.html">
<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_ip_config.html">
<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_nameservers.html">
<link rel="import" href="chrome://resources/cr_components/chromeos/network/network_property_list.html">
@@ -160,22 +161,22 @@
<!-- Choose Mobile Network (Cellular only). -->
<template is="dom-if"
if="[[showCellularChooseNetwork_(networkProperties)]]">
- <div class="settings-box">
- <div class="start">$i18n{networkChooseMobileDetail}</div>
- <paper-button on-tap="onChooseMobileTap_">
- $i18n{networkChooseMobileButton}
- </paper-button>
+ <div class="settings-box single-column stretch">
+ <network-choose-mobile networking-private="[[networkingPrivate]]"
+ network-properties="[[networkProperties]]">
+ </network-choose-mobile>
</div>
</template>
<!-- Data roaming (Cellular only). -->
<template is="dom-if" if="[[isCellular_(networkProperties)]]">
- <settings-toggle-button id="allowDataRoaming"
- pref="{{prefs.cros.signed.data_roaming_enabled}}"
- label="$i18n{networkAllowDataRoaming}">
- </settings-toggle-button>
+ <settings-toggle-button id="allowDataRoaming"
+ pref="{{prefs.cros.signed.data_roaming_enabled}}"
+ label="$i18n{networkAllowDataRoaming}">
+ </settings-toggle-button>
</template>
<!-- SIM Info (Cellular only). -->
- <template is="dom-if" if="[[showCellularSim_(networkProperties)]]">
+ <template is="dom-if" if="[[showCellularSim_(networkProperties)]]"
+ restamp>
<div class="settings-box single-column stretch">
<network-siminfo
editable on-siminfo-change="onNetworkPropertyChange_"
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 598a2369ff2..03ebf640485 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
@@ -229,11 +229,10 @@ Polymer({
if (!this.didSetFocus_) {
// Focus a button once the initial state is set.
this.didSetFocus_ = true;
- var button = this.$$('#titleDiv .primary-button:not([hidden])');
- if (!button)
- button = this.$$('#titleDiv paper-button:not([hidden])');
- assert(button); // At least one button will always be visible.
- button.focus();
+ var button = this.$$('#titleDiv .primary-button:not([hidden])') ||
+ this.$$('#titleDiv paper-button:not([hidden])');
+ if (button)
+ button.focus();
}
if (this.shouldShowConfigureWhenNetworkLoaded_ &&
@@ -371,6 +370,8 @@ Polymer({
* @private
*/
getStateText_: function(networkProperties) {
+ if (!networkProperties.ConnectionState)
+ return '';
return this.i18n('Onc' + networkProperties.ConnectionState);
},
@@ -486,14 +487,14 @@ Polymer({
if (this.connectNotAllowed_(networkProperties, globalPolicy))
return false;
var type = networkProperties.Type;
- if (type == CrOnc.Type.CELLULAR)
+ if (type == CrOnc.Type.CELLULAR || type == CrOnc.Type.TETHER)
return false;
if ((type == CrOnc.Type.WI_FI || type == CrOnc.Type.WI_MAX) &&
networkProperties.ConnectionState !=
CrOnc.ConnectionState.NOT_CONNECTED) {
return false;
}
- return this.isRemembered_(networkProperties);
+ return true;
},
/**
@@ -540,8 +541,9 @@ Polymer({
enableConnect_: function(networkProperties, defaultNetwork, globalPolicy) {
if (!this.showConnect_(networkProperties, globalPolicy))
return false;
- if (networkProperties.Type == CrOnc.Type.CELLULAR &&
- CrOnc.isSimLocked(networkProperties)) {
+ if ((networkProperties.Type == CrOnc.Type.CELLULAR) &&
+ (CrOnc.isSimLocked(networkProperties) ||
+ this.get('Cellular.Scanning', networkProperties))) {
return false;
}
if (networkProperties.Type == CrOnc.Type.VPN && !defaultNetwork)
@@ -607,12 +609,6 @@ Polymer({
this.networkingPrivate.startActivate(this.guid);
},
- /** @private */
- onChooseMobileTap_: function() {
- // TODO(stevenjb): Integrate ChooseMobileNetworkDialog with WebUI.
- chrome.send('addNetwork', [this.networkProperties.Type]);
- },
-
/** @const {string} */
CR_EXPAND_BUTTON_TAG: 'CR-EXPAND-BUTTON',
@@ -1018,8 +1014,8 @@ Polymer({
*/
showCellularSim_: function(networkProperties) {
return networkProperties.Type == CrOnc.Type.CELLULAR &&
- this.get('Cellular.Family', this.networkProperties) ==
- CrOnc.NetworkTechnology.GSM;
+ !!networkProperties.Cellular &&
+ networkProperties.Cellular.Family != 'CDMA';
},
/**
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 a213bc61188..f77ea978261 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -51,14 +51,16 @@
if="[[deviceIsEnabled_(deviceStates.WiFi)]]">
<div actionable class="list-item" on-tap="onAddWiFiTap_">
<div class="start">$i18n{internetAddWiFi}</div>
- <button class="icon-external" is="paper-icon-button-light"
+ <button class$="[[getAddNetworkClass_('WiFi')]]"
+ is="paper-icon-button-light"
aria-label="$i18n{internetAddWiFi}">
</button>
</div>
</template>
<div actionable class="list-item" on-tap="onAddVPNTap_">
<div class="start">$i18n{internetAddVPN}</div>
- <button class="icon-external" is="paper-icon-button-light"
+ <button class$="[[getAddNetworkClass_('VPN')]]"
+ is="paper-icon-button-light"
aria-label="$i18n{internetAddVPN}">
</button>
</div>
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 50000efea86..85c7a78c1c8 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -277,6 +277,20 @@ Polymer({
},
/**
+ * @param {string} type
+ * @return {string}
+ * @private
+ */
+ getAddNetworkClass_: function(type) {
+ if (loadTimeData.getBoolean('networkSettingsConfig')) {
+ if (type == CrOnc.Type.WI_FI)
+ return 'icon-add-wifi';
+ return 'icon-add-circle';
+ }
+ return 'icon-external';
+ },
+
+ /**
* @param {string} subpageType
* @param {!Object<!CrOnc.DeviceStateProperties>|undefined} deviceStates
* @return {!CrOnc.DeviceStateProperties|undefined}
@@ -325,7 +339,10 @@ Polymer({
/** @private */
onAddVPNTap_: function() {
- chrome.send('addNetwork', [CrOnc.Type.VPN]);
+ if (loadTimeData.getBoolean('networkSettingsConfig'))
+ this.showConfig_(CrOnc.Type.VPN);
+ else
+ chrome.send('addNetwork', [CrOnc.Type.VPN]);
},
/**
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html b/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html
index 8a9fbd27179..1d60703ee2c 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html
@@ -4,6 +4,10 @@
<dom-module id="internet-shared">
<template>
<style include="settings-shared">
+ :root {
+ --network-control-width: 250px;
+ }
+
cr-network-icon {
-webkit-padding-end: var(--settings-box-row-padding);
}
@@ -20,6 +24,7 @@
};
margin-bottom: 0;
margin-top: -9px;
+ width: var(--network-control-width);
}
.indented {
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
index 92870ea7316..0434b0e14c0 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -354,10 +354,12 @@ Polymer({
/** @private */
onAddButtonTap_: function() {
assert(this.deviceState);
+ var type = this.deviceState.Type;
+ assert(type != CrOnc.Type.CELLULAR);
if (loadTimeData.getBoolean('networkSettingsConfig'))
- this.fire('show-config', {GUID: '', Type: this.deviceState.Type});
+ this.fire('show-config', {GUID: '', Type: type});
else
- chrome.send('addNetwork', [this.deviceState.Type]);
+ chrome.send('addNetwork', [type]);
},
/**
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_config_input.html b/chromium/chrome/browser/resources/settings/internet_page/network_config_input.html
deleted file mode 100644
index 8ce5b88c82d..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_config_input.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
-<link rel="import" href="../settings_shared_css.html">
-
-<dom-module id="network-config-input">
- <template>
- <style include="settings-shared">
- </style>
-
- <div class="settings-box">
- <div id="label" class="start">[[label]]</div>
- <paper-input-container no-label-float>
- <input is="iron-input" value="{{value::change}}"
- disabled="[[disabled]]" aria-labelledby="label">
- </paper-input-container>
- </div>
- </template>
- <script src="network_config_input.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_config_input.js b/chromium/chrome/browser/resources/settings/internet_page/network_config_input.js
deleted file mode 100644
index 0d9aa62a1ff..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_config_input.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Polymer element for network configuration input fields.
- */
-Polymer({
- is: 'network-config-input',
-
- properties: {
- label: String,
-
- disabled: Boolean,
-
- value: {
- type: String,
- notify: true,
- }
- },
-});
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_config_select.html b/chromium/chrome/browser/resources/settings/internet_page/network_config_select.html
deleted file mode 100644
index f71400cff19..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_config_select.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="../settings_shared_css.html">
-
-<dom-module id="network-config-select">
- <template>
- <style include="settings-shared md-select">
- </style>
-
- <div class="settings-box">
- <div id="label" class="start">[[label]]</div>
- <select class="md-select" disabled="[[disabled]]"
- value="{{value::change}}" aria-labelledby="label">
- <template is="dom-repeat" items="[[items]]">
- <option value="[[item]]">
- [[getOncLabel_(item, oncPrefix)]]
- </option>
- </template>
- </select>
- </div>
-
- </template>
- <script src="network_config_select.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_config_select.js b/chromium/chrome/browser/resources/settings/internet_page/network_config_select.js
deleted file mode 100644
index 23794bb400f..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_config_select.js
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Polymer element for network configuration selection menus.
- */
-Polymer({
- is: 'network-config-select',
-
- behaviors: [I18nBehavior],
-
- properties: {
- label: String,
-
- disabled: Boolean,
-
- /**
- * Array of item values to select from.
- * @type {!Array<string>}
- */
- items: Array,
-
- /** Prefix used to look up ONC property names. */
- oncPrefix: String,
-
- /** Select item value */
- value: {
- type: String,
- notify: true,
- },
- },
-
- observers: ['updateSelected_(items, value)'],
-
- /**
- * Ensure that the <select> value is updated when |items| or |value| changes.
- * @private
- */
- updateSelected_: function() {
- // Wait for the dom-repeat to populate the <option> entries.
- this.async(function() {
- var select = this.$$('select');
- if (select.value != this.value)
- select.value = this.value;
- });
- },
-
- /**
- * @param {string} key
- * @param {string} prefix
- * @return {string} The text to display for the onc value.
- * @private
- */
- getOncLabel_: function(key, prefix) {
- var oncKey = 'Onc' + prefix.replace(/\./g, '-') + '_' + key;
- if (this.i18nExists(oncKey))
- return this.i18n(oncKey);
- assertNotReached();
- return key;
- },
-});
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html
index f4cddf4cd3d..f5d88e89c41 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html
@@ -9,7 +9,6 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="../controls/extension_controlled_indicator.html">
@@ -21,7 +20,7 @@
<dom-module id="network-proxy-section">
<template>
- <style include="internet-shared md-select cr-hidden-style iron-flex iron-flex-alignment">
+ <style include="internet-shared cr-hidden-style iron-flex iron-flex-alignment">
cr-policy-network-indicator {
-webkit-margin-end: 10px;
}
@@ -82,7 +81,9 @@
close-text="$i18n{close}" on-cancel="onAllowSharedDialogCancel_"
on-close="onAllowSharedDialogClose_">
<div slot="title">
- $i18n{networkProxyAllowSharedWarningTitle}
+ [[getAllowSharedDialogTitle_(prefs.settings.use_shared_proxies.value,
+ '$i18n{networkProxyAllowSharedEnableWarningTitle}',
+ '$i18n{networkProxyAllowSharedDisableWarningTitle}')]]
</div>
<div slot="body">
$i18n{networkProxyAllowSharedWarningMessage}
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.js b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.js
index 4a637c97d29..ce303c1a8b1 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.js
@@ -67,6 +67,17 @@ Polymer({
},
/**
+ * @param {boolean} allowShared
+ * @param {string} enableStr
+ * @param {string} disableStr
+ * @return {string}
+ * @private
+ */
+ getAllowSharedDialogTitle_: function(allowShared, enableStr, disableStr) {
+ return allowShared ? disableStr : enableStr;
+ },
+
+ /**
* @return {boolean}
* @private
*/
@@ -91,7 +102,8 @@ Polymer({
* @private
*/
shouldShowAllowShared_: function(property) {
- return !this.isControlled(property) && this.isShared_();
+ return this.isShared_() && !this.isNetworkPolicyEnforced(property) &&
+ !this.isExtensionControlled(property);
},
/**
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js
index cb0eb9cbd05..2ea134f2069 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_siminfo.js
@@ -71,6 +71,18 @@ Polymer({
sendSimLockEnabled_: false,
+ /** @override */
+ detached: function() {
+ if (this.$.enterPinDialog.open)
+ this.$.enterPinDialog.close();
+ if (this.$.changePinDialog.open)
+ this.$.changePinDialog.close();
+ if (this.$.unlockPinDialog.open)
+ this.$.unlockPinDialog.close();
+ if (this.$.unlockPukDialog.open)
+ this.$.unlockPukDialog.close();
+ },
+
/** @private */
networkPropertiesChanged_: function() {
if (!this.networkProperties || !this.networkProperties.Cellular)
@@ -135,6 +147,7 @@ Polymer({
* @private
*/
sendEnterPin_: function(event) {
+ event.stopPropagation();
var guid = (this.networkProperties && this.networkProperties.GUID) || '';
var pin = this.$.enterPin.value;
if (!this.validatePin_(pin)) {
@@ -162,9 +175,9 @@ Polymer({
* @private
*/
onChangePinTap_: function(event) {
+ event.stopPropagation();
if (!this.networkProperties || !this.networkProperties.Cellular)
return;
- event.stopPropagation();
this.error_ = ErrorType.NONE;
this.$.changePinOld.value = '';
this.$.changePinNew1.value = '';
@@ -178,6 +191,7 @@ Polymer({
* @private
*/
sendChangePin_: function(event) {
+ event.stopPropagation();
var guid = (this.networkProperties && this.networkProperties.GUID) || '';
var newPin = this.$.changePinNew1.value;
if (!this.validatePin_(newPin, this.$.changePinNew2.value))
@@ -219,6 +233,7 @@ Polymer({
* @private
*/
sendUnlockPin_: function(event) {
+ event.stopPropagation();
var guid = (this.networkProperties && this.networkProperties.GUID) || '';
var pin = this.$.unlockPin.value;
if (!this.validatePin_(pin))
@@ -257,6 +272,7 @@ Polymer({
* @private
*/
sendUnlockPuk_: function(event) {
+ event.stopPropagation();
var guid = (this.networkProperties && this.networkProperties.GUID) || '';
var puk = this.$.unlockPuk.value;
if (!this.validatePuk_(puk))
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 6a9295eea59..b1a730a7e82 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
@@ -36,7 +36,8 @@
</style>
<div actionable class="settings-box two-line" on-tap="onShowDetailsTap_">
<div id="details" no-flex$="[[showSimInfo_(deviceState)]]">
- <cr-network-icon network-state="[[activeNetworkState]]">
+ <cr-network-icon network-state="[[activeNetworkState]]"
+ device-state="[[deviceState]]">
</cr-network-icon>
<div class="flex">
<div id="networkName">[[getNetworkName_(activeNetworkState)]]</div>
@@ -46,8 +47,8 @@
</div>
</div>
- <template is="dom-if" if="[[showSimInfo_(deviceState)]]">
- <network-siminfo editable
+ <template is="dom-if" if="[[showSimInfo_(deviceState)]]" restamp>
+ <network-siminfo editable on-tap="doNothing_"
network-properties="[[getCellularState_(deviceState)]]"
networking-private="[[networkingPrivate]]">
</network-siminfo>
@@ -55,7 +56,8 @@
<template is="dom-if" if="[[showPolicyIndicator_(activeNetworkState)]]">
<cr-policy-indicator indicator-type="[[getIndicatorTypeForSource(
- activeNetworkState.Source)]]">
+ activeNetworkState.Source)]]"
+ on-tap="doNothing_">
</cr-policy-indicator>
</template>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
index 656d66606cd..9555d961bd8 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -85,8 +85,11 @@ Polymer({
return this.i18n('tetherEnableBluetooth');
}
// Enabled or enabling states.
- if (deviceState.State == CrOnc.DeviceState.ENABLED)
- return CrOncStrings.networkListItemNotConnected;
+ if (deviceState.State == CrOnc.DeviceState.ENABLED) {
+ if (this.networkStateList.length > 0)
+ return CrOncStrings.networkListItemNotConnected;
+ return CrOncStrings.networkListItemNoNetwork;
+ }
if (deviceState.State == CrOnc.DeviceState.ENABLING)
return this.i18n('internetDeviceEnabling');
}
@@ -306,4 +309,13 @@ Polymer({
// Make sure this does not propagate to onDetailsTap_.
event.stopPropagation();
},
+
+ /**
+ * Make sure events in embedded components do not propagate to onDetailsTap_.
+ * @param {!Event} event
+ * @private
+ */
+ doNothing_: function(event) {
+ event.stopPropagation();
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages.js b/chromium/chrome/browser/resources/settings/languages_page/languages.js
index 36da86dce34..47a7568bf09 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages.js
@@ -23,6 +23,7 @@ var kLanguageCodeToTranslateCode = {
'zh-HK': 'zh-TW',
'zh-MO': 'zh-TW',
'zh-SG': 'zh-CN',
+ 'zh': 'zh-CH',
};
// Some ISO 639 language codes have been renamed, e.g. "he" to "iw", but
@@ -294,6 +295,8 @@ Polymer({
this.languages.prospectiveUILanguage) {
continue;
}
+ // This conversion primarily strips away the region part.
+ // For example "fr-CA" --> "fr".
var translateCode = this.convertLanguageCodeForTranslate(
this.languages.enabled[i].language.code);
this.set(
@@ -542,7 +545,6 @@ Polymer({
return;
this.languageSettingsPrivate_.enableLanguage(languageCode);
- this.disableTranslateLanguage(languageCode);
},
/**
@@ -573,7 +575,6 @@ Polymer({
// Remove the language from preferred languages.
this.languageSettingsPrivate_.disableLanguage(languageCode);
- this.enableTranslateLanguage(languageCode);
},
/**
@@ -668,8 +669,8 @@ Polymer({
* @param {string} languageCode
*/
enableTranslateLanguage: function(languageCode) {
- languageCode = this.convertLanguageCodeForTranslate(languageCode);
- this.deletePrefListItem('translate_blocked_languages', languageCode);
+ this.languageSettingsPrivate_.setEnableTranslationForLanguage(
+ languageCode, true);
},
/**
@@ -678,9 +679,8 @@ Polymer({
* @param {string} languageCode
*/
disableTranslateLanguage: function(languageCode) {
- this.appendPrefListItem(
- 'translate_blocked_languages',
- this.convertLanguageCodeForTranslate(languageCode));
+ this.languageSettingsPrivate_.setEnableTranslationForLanguage(
+ languageCode, false);
},
/**
diff --git a/chromium/chrome/browser/resources/settings/lifetime_browser_proxy.js b/chromium/chrome/browser/resources/settings/lifetime_browser_proxy.js
index d97ac2d6b39..19bc02a2d69 100644
--- a/chromium/chrome/browser/resources/settings/lifetime_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/lifetime_browser_proxy.js
@@ -15,8 +15,13 @@ cr.define('settings', function() {
// First signs out current user and then performs a restart.
signOutAndRestart() {}
- // Triggers a factory reset.
- factoryReset() {}
+ /**
+ * Triggers a factory reset. The parameter indicates whether to install a
+ * TPM firmware update (if available) after the reset.
+ *
+ * @param {boolean=} requestTpmFirmwareUpdate
+ */
+ factoryReset(requestTpmFirmwareUpdate) {}
// </if>
}
@@ -41,8 +46,8 @@ cr.define('settings', function() {
}
/** @override */
- factoryReset() {
- chrome.send('factoryReset');
+ factoryReset(requestTpmFirmwareUpdate) {
+ chrome.send('factoryReset', [requestTpmFirmwareUpdate]);
}
// </if>
}
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
index fc03d5eee73..b7a407def99 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
@@ -1,20 +1,26 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="../prefs/prefs.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="settings-multidevice-page">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ settings-toggle-button {
+ -webkit-padding-end: 0;
+ flex: 1;
+ }
+ </style>
<div class="settings-box two-line">
- <div id="smsConnectToggleLabel" class="start">
- $i18n{smsConnect}
- <div class="secondary">$i18n{smsConnectSummary}</div>
+ <div class="icon-container">
+ <iron-icon icon="cr:sms-connect"></iron-icon>
</div>
- <paper-toggle-button checked="{{smsConnectToggleState_}}"
- aria-labelledby="smsConnectToggleLabel">
- </paper-toggle-button>
+ <settings-toggle-button
+ pref="{{prefs.multidevice.sms_connect_enabled}}"
+ label="$i18n{smsConnect}"
+ sub-label="$i18n{smsConnectSummary}">
+ </settings-toggle-button>
</div>
</template>
<script src="multidevice_page.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
index e402512aefe..0e1d72219d6 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
@@ -16,22 +16,5 @@ Polymer({
type: Object,
notify: true,
},
-
- /**
- * Reflects the current state of the toggle buttons (in this page and the
- * subpage). This will be set when the user changes the toggle.
- * @private
- */
- smsConnectToggleState_: {
- type: Boolean,
- observer: 'smsConnectToggleStateChanged_',
- },
- },
-
- /** @private */
- smsConnectToggleStateChanged_: function() {
- // TODO(orenb): Switch from paper-toggle-button to settings-toggle-button,
- // which will manage the underlying pref state, once the new pref has been
- // implemented. Propagate here the pref value to the SMS connect component.
},
});
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 b61b25173ec..92e674c24f6 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
@@ -61,6 +61,7 @@
'dependencies': [
'../compiled_resources2.gyp:global_scroll_target_behavior',
'<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_toast/compiled_resources2.gyp:cr_toast',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
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 f84bd884948..28f9cec9ad3 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
@@ -1,6 +1,7 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html
index 2bde5b23f8a..1d11c507149 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html
@@ -1,6 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../focus_row_behavior.html">
<link rel="import" href="../settings_shared_css.html">
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 a5293b941fa..55dd3fd8ed6 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,5 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.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/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
@@ -22,20 +23,10 @@
<settings-animated-pages id="pages" section="passwordsAndForms"
focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
- <div class="settings-box first two-line">
- <div class="start two-line" on-tap="onAutofillTap_" actionable
- id="autofillManagerButton">
- <div class="flex">
- $i18n{autofill}
- <div class="secondary" id="autofillSecondary">
- $i18n{autofillDetail}
- </div>
- </div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{autofill}"
- aria-describedby="autofillSecondary"></button>
- </div>
- </div>
+ <button is="cr-link-row" icon-class="subpage-arrow"
+ id="autofillManagerButton" label="$i18n{autofill}"
+ sub-label="$i18n{autofillDetail}" on-tap="onAutofillTap_">
+ </button>
<div class="settings-box two-line">
<div class="start two-line" on-tap="onPasswordsTap_" actionable
id="passwordManagerButton">
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 b621c11ca9a..9d9d0c6e90f 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
@@ -20,8 +20,7 @@ Polymer({
this.focusConfig_ = new Map();
if (settings.routes.AUTOFILL) {
this.focusConfig_.set(
- settings.routes.AUTOFILL.path,
- '#autofillManagerButton .subpage-arrow');
+ settings.routes.AUTOFILL.path, '#autofillManagerButton');
}
if (settings.routes.MANAGE_PASSWORDS) {
this.focusConfig_.set(
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 e9cdd80c0ee..fd2f647da10 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,10 +1,12 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
<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/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../controls/settings_toggle_button.html">
@@ -27,6 +29,29 @@
-webkit-padding-end: calc(
var(--cr-icon-ripple-size) + var(--cr-icon-button-margin-start));
}
+
+ #undoLabel {
+ color: #fff;
+ display: flex;
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ #undoButton {
+ -webkit-margin-end: 0;
+ -webkit-margin-start: 32px;
+ color: var(--google-blue-300);
+ font-weight: 500;
+ height: 32px;
+ min-width: 52px;
+ padding: 8px;
+ }
+
+ #undoToast {
+ z-index: 1;
+ }
</style>
<settings-toggle-button id="passwordToggle"
class="first primary-toggle"
@@ -58,7 +83,18 @@
<span>$i18nRaw{managePasswordsLabel}</span>
</div>
<div class="settings-box first">
- <h2>$i18n{savedPasswordsHeading}</h2>
+ <h2 class="start">$i18n{savedPasswordsHeading}</h2>
+ <template is="dom-if" if="[[showImportExportPasswords_]]">
+ <paper-button class="secondary-button header-aligned-button"
+ on-tap="onImportTap_" id="import">
+ $i18n{import}
+ </paper-button>
+ <paper-button class="secondary-button header-aligned-button"
+ on-tap="onExportTap_" id="export"
+ disabled$="[[!hasSome_(savedPasswords)]]">
+ $i18n{export}
+ </paper-button>
+ </template>
</div>
<div class="list-frame">
<div id="savedPasswordsHeading" class="list-item column-header"
@@ -98,6 +134,12 @@
item="[[activePassword]]">
</password-edit-dialog>
</template>
+ <cr-toast id="undoToast" duration="[[toastDuration_]]">
+ <div id="undoLabel">$i18n{passwordDeleted}</div>
+ <paper-button id="undoButton" on-tap="onUndoButtonTap_">
+ $i18n{undoRemovePassword}
+ </paper-button>
+ </cr-toast>
<div class="settings-box block first">
<h2>$i18n{passwordExceptionsHeading}</h2>
</div>
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 b426a015a25..9e5b23059c2 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
@@ -33,10 +33,10 @@ class PasswordManager {
/**
* Should remove the saved password and notify that the list has changed.
- * @param {!PasswordManager.LoginPair} loginPair The saved password that
- * should be removed from the list. No-op if |loginPair| is not found.
+ * @param {number} index The index for the password entry being removed.
+ * No-op if |index| is not in the list.
*/
- removeSavedPassword(loginPair) {}
+ removeSavedPassword(index) {}
/**
* Add an observer to the list of password exceptions.
@@ -58,18 +58,34 @@ class PasswordManager {
/**
* Should remove the password exception and notify that the list has changed.
- * @param {string} exception The exception that should be removed from the
- * list. No-op if |exception| is not in the list.
+ * @param {number} index The index for the exception url entry being removed.
+ * No-op if |index| is not in the list.
*/
- removeException(exception) {}
+ removeException(index) {}
+
+ /**
+ * Should undo the last saved password or exception removal and notify that
+ * the list has changed.
+ */
+ undoRemoveSavedPasswordOrException() {}
/**
* Gets the saved password for a given login pair.
- * @param {!PasswordManager.LoginPair} loginPair The saved password that
- * should be retrieved.
+ * @param {number} index The index for password entry that should be
+ * retrieved. No-op if |index| is not in the list.
* @param {function(!PasswordManager.PlaintextPasswordEvent):void} callback
*/
- getPlaintextPassword(loginPair, callback) {}
+ getPlaintextPassword(index, callback) {}
+
+ /**
+ * Triggers the dialogue for importing passwords.
+ */
+ importPasswords() {}
+
+ /**
+ * Triggers the dialogue for exporting passwords.
+ */
+ exportPasswords() {}
}
/** @typedef {chrome.passwordsPrivate.PasswordUiEntry} */
@@ -106,8 +122,8 @@ class PasswordManagerImpl {
}
/** @override */
- removeSavedPassword(loginPair) {
- chrome.passwordsPrivate.removeSavedPassword(loginPair);
+ removeSavedPassword(index) {
+ chrome.passwordsPrivate.removeSavedPassword(index);
}
/** @override */
@@ -128,23 +144,37 @@ class PasswordManagerImpl {
}
/** @override */
- removeException(exception) {
- chrome.passwordsPrivate.removePasswordException(exception);
+ removeException(index) {
+ chrome.passwordsPrivate.removePasswordException(index);
+ }
+
+ /** @override */
+ undoRemoveSavedPasswordOrException() {
+ chrome.passwordsPrivate.undoRemoveSavedPasswordOrException();
}
/** @override */
- getPlaintextPassword(loginPair, callback) {
+ getPlaintextPassword(index, callback) {
var listener = function(reply) {
// Only handle the reply for our loginPair request.
- if (reply.loginPair.urls.origin == loginPair.urls.origin &&
- reply.loginPair.username == loginPair.username) {
+ if (reply.index == index) {
chrome.passwordsPrivate.onPlaintextPasswordRetrieved.removeListener(
listener);
callback(reply);
}
};
chrome.passwordsPrivate.onPlaintextPasswordRetrieved.addListener(listener);
- chrome.passwordsPrivate.requestPlaintextPassword(loginPair);
+ chrome.passwordsPrivate.requestPlaintextPassword(index);
+ }
+
+ /** @override */
+ importPasswords() {
+ chrome.passwordsPrivate.importPasswords();
+ }
+
+ /** @override */
+ exportPasswords() {
+ chrome.passwordsPrivate.exportPasswords();
}
}
@@ -162,7 +192,11 @@ var ExceptionEntryEntryEvent;
Polymer({
is: 'passwords-section',
- behaviors: [settings.GlobalScrollTargetBehavior, I18nBehavior],
+ behaviors: [
+ I18nBehavior,
+ Polymer.IronA11yKeysBehavior,
+ settings.GlobalScrollTargetBehavior,
+ ],
properties: {
/** Preferences state. */
@@ -183,6 +217,15 @@ Polymer({
*/
passwordExceptions: Array,
+ /**
+ * Duration of the undo toast in ms
+ * @private
+ */
+ toastDuration_: {
+ type: Number,
+ value: 5000,
+ },
+
/** @override */
subpageRoute: {
type: Object,
@@ -195,6 +238,22 @@ Polymer({
*/
activePassword: Object,
+
+ /** The target of the key bindings defined below. */
+ keyEventTarget: {
+ type: Object,
+ value: () => document,
+ },
+
+ /** @private */
+ showImportExportPasswords_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.valueExists('showImportExportPasswords') &&
+ loadTimeData.getBoolean('showImportExportPasswords');
+ }
+ },
+
/** @private */
showPasswordEditDialog_: Boolean,
@@ -213,6 +272,15 @@ Polymer({
'password-menu-tap': 'onPasswordMenuTap_',
},
+ keyBindings: {
+ // <if expr="is_macosx">
+ 'meta+z': 'onUndoKeyBinding_',
+ // </if>
+ // <if expr="not is_macosx">
+ 'ctrl+z': 'onUndoKeyBinding_',
+ // </if>
+ },
+
/**
* The element to return focus to, when the currently active dialog is
* closed.
@@ -264,6 +332,10 @@ Polymer({
setSavedPasswordsListener);
this.passwordManager_.addExceptionListChangedListener(
setPasswordExceptionsListener);
+
+ Polymer.RenderStatus.afterNextRender(this, function() {
+ Polymer.IronA11yAnnouncer.requestAvailability();
+ });
},
/** @override */
@@ -326,17 +398,31 @@ Polymer({
* @private
*/
onMenuRemovePasswordTap_: function() {
- this.passwordManager_.removeSavedPassword(this.activePassword.loginPair);
+ this.passwordManager_.removeSavedPassword(this.activePassword.index);
+ this.fire('iron-announce', {text: this.$.undoLabel.textContent});
+ this.$.undoToast.show();
/** @type {CrActionMenuElement} */ (this.$.menu).close();
},
+ onUndoKeyBinding_: function(event) {
+ this.passwordManager_.undoRemoveSavedPasswordOrException();
+ this.$.undoToast.hide();
+ // Preventing the default is necessary to not conflict with a possible
+ // search action.
+ event.preventDefault();
+ },
+
+ onUndoButtonTap_: function() {
+ this.passwordManager_.undoRemoveSavedPasswordOrException();
+ this.$.undoToast.hide();
+ },
/**
* Fires an event that should delete the password exception.
* @param {!ExceptionEntryEntryEvent} e The polymer event.
* @private
*/
onRemoveExceptionButtonTap_: function(e) {
- this.passwordManager_.removeException(e.model.item.urls.origin);
+ this.passwordManager_.removeException(e.model.item.index);
},
/**
@@ -355,6 +441,26 @@ Polymer({
this.activeDialogAnchor_ = target;
},
+ undoRemoveSavedPasswordOrException_: function(event) {
+ this.passwordManager_.undoRemoveSavedPasswordOrException();
+ },
+
+ /**
+ * Fires an event that should trigger the password import process.
+ * @private
+ */
+ onImportTap_: function() {
+ this.passwordManager_.importPasswords();
+ },
+
+ /**
+ * Fires an event that should trigger the password export process.
+ * @private
+ */
+ onExportTap_: function() {
+ this.passwordManager_.exportPasswords();
+ },
+
/**
* Returns true if the list exists and has items.
* @param {Array<Object>} list
@@ -372,8 +478,7 @@ Polymer({
*/
showPassword_: function(event) {
this.passwordManager_.getPlaintextPassword(
- /** @type {!PasswordManager.LoginPair} */ (event.detail.item.loginPair),
- item => {
+ /** @type {!number} */ (event.detail.item.index), item => {
event.detail.password = item.plaintextPassword;
});
},
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 2b642c9f527..82cbc58d44a 100644
--- a/chromium/chrome/browser/resources/settings/people_page/change_picture.html
+++ b/chromium/chrome/browser/resources/settings/people_page/change_picture.html
@@ -82,9 +82,9 @@
image-src="[[getImageSrc_(selectedItem_)]]"
image-type="[[getImageType_(selectedItem_)]]"
discard-image-label="$i18n{discardPhoto}"
- flip-photo-label="$i18n{flipPhoto}"
preview-alt-text="$i18n{previewAltText}"
- take-photo-label="$i18n{takePhoto}">
+ take-photo-label="$i18n{takePhoto}"
+ switch-mode-label="$i18n{switchMode}">
</cr-picture-pane>
<div id="authorCredit"
hidden="[[!isAuthorCreditShown_(selectedItem_)]]">
@@ -103,7 +103,8 @@
choose-file-label="$i18n{chooseFile}"
old-image-label="$i18n{oldPhoto}"
profile-image-label="$i18n{profilePhoto}"
- take-photo-label="$i18n{takePhoto}">
+ take-photo-label="$i18n{takePhoto}"
+ switch-mode-label="$i18n{switchMode}">
</cr-picture-list>
</div>
</template>
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 d41dc4c36db..b610c1d4ac2 100644
--- a/chromium/chrome/browser/resources/settings/people_page/change_picture.js
+++ b/chromium/chrome/browser/resources/settings/people_page/change_picture.js
@@ -58,8 +58,8 @@ Polymer({
listeners: {
'discard-image': 'onDiscardImage_',
'image-activate': 'onImageActivate_',
- 'photo-flipped': 'onPhotoFlipped_',
'photo-taken': 'onPhotoTaken_',
+ 'switch-mode': 'onSwitchMode_',
},
/** @private {?settings.ChangePictureBrowserProxy} */
@@ -209,11 +209,10 @@ Polymer({
* @param {!{detail: boolean}} event
* @private
*/
- onPhotoFlipped_: function(event) {
- var flipped = event.detail;
- var flipMessageId = flipped ? 'photoFlippedAccessibleText' :
- 'photoFlippedBackAccessibleText';
- announceAccessibleMessage(loadTimeData.getString(flipMessageId));
+ onSwitchMode_: function(event) {
+ var videomode = event.detail;
+ announceAccessibleMessage(this.i18n(
+ videomode ? 'videoModeAccessibleText' : 'photoModeAccessibleText'));
},
/** @private */
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 d4e15b6a63e..d170ab31163 100644
--- a/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -150,6 +150,7 @@
'dependencies': [
'../compiled_resources2.gyp:route',
'../settings_page/compiled_resources2.gyp:settings_animated_pages',
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp:cr_png_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:icon',
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_screen.js b/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
index b8d3d02ff26..aaac86af6d1 100644
--- a/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
@@ -208,12 +208,14 @@ Polymer({
* @protected
*/
currentRouteChanged: function(newRoute, oldRoute) {
- if (newRoute == settings.routes.LOCK_SCREEN &&
- this.fingerprintUnlockEnabled_ && this.fingerprintBrowserProxy_) {
- this.fingerprintBrowserProxy_.getNumFingerprints().then(
- numFingerprints => {
- this.numFingerprints_ = numFingerprints;
- });
+ if (newRoute == settings.routes.LOCK_SCREEN) {
+ this.updateUnlockType();
+ if (this.fingerprintUnlockEnabled_ && this.fingerprintBrowserProxy_) {
+ this.fingerprintBrowserProxy_.getNumFingerprints().then(
+ numFingerprints => {
+ this.numFingerprints_ = numFingerprints;
+ });
+ }
}
if (this.shouldAskForPassword_(newRoute)) {
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_state_behavior.js b/chromium/chrome/browser/resources/settings/people_page/lock_state_behavior.js
index d40f58e59fc..b42fbee289c 100644
--- a/chromium/chrome/browser/resources/settings/people_page/lock_state_behavior.js
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_state_behavior.js
@@ -42,11 +42,11 @@ var LockStateBehavior = {
/** @override */
attached: function() {
- this.boundOnActiveModesChanged_ = this.updateUnlockType_.bind(this);
+ this.boundOnActiveModesChanged_ = this.updateUnlockType.bind(this);
this.quickUnlockPrivate_.onActiveModesChanged.addListener(
this.boundOnActiveModesChanged_);
- this.updateUnlockType_();
+ this.updateUnlockType();
},
/** @override */
@@ -59,10 +59,8 @@ var LockStateBehavior = {
* Updates the selected unlock type radio group. This function will get called
* after preferences are initialized, after the quick unlock mode has been
* changed, and after the lockscreen preference has changed.
- *
- * @private
*/
- updateUnlockType_: function() {
+ updateUnlockType: function() {
this.quickUnlockPrivate_.getActiveModes(modes => {
if (modes.includes(chrome.quickUnlockPrivate.QuickUnlockMode.PIN)) {
this.hasPin = true;
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 bcb99fcf3de..cec6369f63b 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.html
@@ -26,6 +26,7 @@
<if expr="chromeos">
<link rel="import" href="change_picture.html">
+<link rel="import" href="chrome://resources/cr_elements/chromeos/cr_picture/cr_png_behavior.html">
<link rel="import" href="fingerprint_list.html">
<link rel="import" href="lock_screen.html">
<link rel="import" href="lock_state_behavior.html">
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 1b1dec616e9..11610990843 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.js
@@ -12,7 +12,7 @@ Polymer({
behaviors: [
settings.RouteObserverBehavior, I18nBehavior, WebUIListenerBehavior,
// <if expr="chromeos">
- LockStateBehavior,
+ CrPngBehavior, LockStateBehavior,
// </if>
],
@@ -156,6 +156,9 @@ Polymer({
settings.getCurrentRoute() == settings.routes.IMPORT_DATA;
if (settings.getCurrentRoute() == settings.routes.SIGN_OUT) {
+ // <if expr="not chromeos">
+ settings.ProfileInfoBrowserProxyImpl.getInstance().getProfileStatsCount();
+ // </if>
// If the sync status has not been fetched yet, optimistically display
// the disconnect dialog. There is another check when the sync status is
// fetched. The dialog will be closed then the user is not signed in.
@@ -190,6 +193,18 @@ Polymer({
*/
handleProfileInfo_: function(info) {
this.profileName_ = info.name;
+ /**
+ * Extract first frame from image by creating a single frame PNG using
+ * url as input if base64 encoded and potentially animated.
+ */
+ // <if expr="chromeos">
+ if (info.iconUrl.startsWith('data:image/png;base64')) {
+ this.profileIconUrl_ =
+ CrPngBehavior.convertImageSequenceToPng([info.iconUrl]);
+ return;
+ }
+ // </if>
+
this.profileIconUrl_ = info.iconUrl;
},
@@ -229,11 +244,6 @@ Polymer({
if (!this.syncStatus && syncStatus && !syncStatus.signedIn)
chrome.metricsPrivate.recordUserAction('Signin_Impression_FromSettings');
- // <if expr="not chromeos">
- if (syncStatus.signedIn)
- settings.ProfileInfoBrowserProxyImpl.getInstance().getProfileStatsCount();
- // </if>
-
if (!syncStatus.signedIn && this.showDisconnectDialog_)
this.$$('#disconnectDialog').close();
diff --git a/chromium/chrome/browser/resources/settings/people_page/settings_icon_flip.svg b/chromium/chrome/browser/resources/settings/people_page/settings_icon_flip.svg
deleted file mode 100644
index b95e714b522..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/settings_icon_flip.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF" preserveAspectRatio="xMidYMid meet"><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></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/settings/people_page/user_list.js b/chromium/chrome/browser/resources/settings/people_page/user_list.js
index f897fc9ba59..8158f7c31a0 100644
--- a/chromium/chrome/browser/resources/settings/people_page/user_list.js
+++ b/chromium/chrome/browser/resources/settings/people_page/user_list.js
@@ -110,7 +110,8 @@ Polymer({
* @private
*/
getProfilePictureUrl_: function(user) {
- return 'chrome://userimage/' + user.email + '?id=' + Date.now();
+ return 'chrome://userimage/' + user.email + '?id=' + Date.now() +
+ '&frame=0';
},
/**
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
index 3b298a30f59..6ebd338e294 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -127,20 +127,20 @@ Polymer({
// We're abandoning discovery in favor of manual specification, so
// drop the selection if one exists.
this.selectedPrinter = getEmptyPrinter_();
- this.$$('add-printer-dialog').close();
+ this.close();
this.fire('open-manually-add-printer-dialog');
},
/** @private */
onCancelTap_: function() {
this.stopDiscoveringPrinters_();
- this.$$('add-printer-dialog').close();
+ this.close();
},
/** @private */
switchToConfiguringDialog_: function() {
this.stopDiscoveringPrinters_();
- this.$$('add-printer-dialog').close();
+ this.close();
this.fire('open-configuring-printer-dialog');
},
});
@@ -205,14 +205,20 @@ Polymer({
},
},
+ close: function() {
+ this.$$('add-printer-dialog').close();
+ },
+
/** @private */
onCancelTap_: function() {
- this.$$('add-printer-dialog').close();
+ this.close();
+ settings.CupsPrintersBrowserProxyImpl.getInstance().cancelPrinterSetUp(
+ this.activePrinter);
},
/** @private */
switchToConfiguringDialog_: function() {
- this.$$('add-printer-dialog').close();
+ this.close();
this.fire('open-configuring-printer-dialog');
},
@@ -244,7 +250,7 @@ Polymer({
/** @private */
onCancelConfiguringTap_: function() {
- this.$$('add-printer-dialog').close();
+ this.close();
this.fire('configuring-dialog-closed');
},
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html
index 36374ba0f2c..3df538af0ea 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.html
@@ -51,8 +51,9 @@
justify-content: space-around;
}
- #addPrinterErrorMessage a[is='action-link'] {
- text-transform: uppercase;
+ #addPrinterFailedMessage {
+ padding: 0 15px;
+ text-align: justify;
}
</style>
@@ -92,10 +93,9 @@
$i18n{printerAddedSuccessfulMessage}
</div>
<div class="center" id="addPrinterErrorMessage" hidden>
- <span>$i18n{printerAddedFailedMessage}</span>
- <a is="action-link" on-tap="onAddPrinterTap_">
- $i18n{printerAddedTryAgainMessage}
- </a>
+ <span id="addPrinterFailedMessage">
+ $i18n{printerAddedFailedMessage}
+ </span>
</div>
</div>
</template>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js
index b1e36c367b3..0957580006d 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_printers.js
@@ -95,19 +95,53 @@ Polymer({
},
/**
- * @param {boolean} success
+ * @param {PrinterSetupResult} result_code
* @param {string} printerName
* @private
*/
- onAddPrinter_: function(success, printerName) {
- if (success) {
+ onAddPrinter_: function(result_code, printerName) {
+ if (result_code == PrinterSetupResult.SUCCESS) {
this.updateCupsPrintersList_();
var message = this.$.addPrinterDoneMessage;
message.textContent =
loadTimeData.getStringF('printerAddedSuccessfulMessage', printerName);
} else {
var message = this.$.addPrinterErrorMessage;
+ var messageText = this.$.addPrinterFailedMessage;
+ switch (result_code) {
+ case PrinterSetupResult.FATAL_ERROR:
+ messageText.textContent =
+ loadTimeData.getString('printerAddedFatalErrorMessage');
+ break;
+ case PrinterSetupResult.PRINTER_UNREACHABLE:
+ messageText.textContent =
+ loadTimeData.getString('printerAddedPrinterUnreachableMessage');
+ break;
+ case PrinterSetupResult.DBUS_ERROR:
+ // Simply display a generic error message as this error should only
+ // occur when a call to Dbus fails which isn't meaningful to the user.
+ messageText.textContent =
+ loadTimeData.getString('printerAddedFailedmMessage');
+ break;
+ case PrinterSetupResult.PPD_TOO_LARGE:
+ messageText.textContent =
+ loadTimeData.getString('printerAddedPpdTooLargeMessage');
+ break;
+ case PrinterSetupResult.INVALID_PPD:
+ messageText.textContent =
+ loadTimeData.getString('printerAddedInvalidPpdMessage');
+ break;
+ case PrinterSetupResult.PPD_NOT_FOUND:
+ messageText.textContent =
+ loadTimeData.getString('printerAddedPpdNotFoundMessage');
+ break;
+ case PrinterSetupResult.PPD_UNRETRIEVABLE:
+ messageText.textContent =
+ loadTimeData.getString('printerAddedPpdUnretrievableMessage');
+ break;
+ }
}
+
message.hidden = false;
window.setTimeout(function() {
message.hidden = true;
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js b/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
index 29ad9bdb4b5..6cc0b682015 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
@@ -69,6 +69,22 @@ var PrinterMakeModel;
var PrinterPpdMakeModel;
/**
+ * @enum {number}
+ * These values must be kept in sync with the PrinterSetupResult enum in
+ * chrome/browser/chromeos/printing/printer_configurer.h.
+ */
+var PrinterSetupResult = {
+ FATAL_ERROR: 0,
+ SUCCESS: 1,
+ PRINTER_UNREACHABLE: 2,
+ DBUS_ERROR: 3,
+ PPD_TOO_LARGE: 10,
+ INVALID_PPD: 11,
+ PPD_NOT_FOUND: 12,
+ PPD_UNRETRIEVABLE: 13,
+};
+
+/**
* @typedef {{
* message: string
* }}
@@ -135,6 +151,12 @@ cr.define('settings', function() {
* @param{string} printerId
*/
addDiscoveredPrinter(printerId) {}
+
+ /**
+ * Report to the handler that setup was cancelled.
+ * @param {!CupsPrinterInfo} newPrinter
+ */
+ cancelPrinterSetUp(newPrinter) {}
}
/**
@@ -200,6 +222,11 @@ cr.define('settings', function() {
addDiscoveredPrinter(printerId) {
chrome.send('addDiscoveredPrinter', [printerId]);
}
+
+ /** @override */
+ cancelPrinterSetUp(newPrinter) {
+ chrome.send('cancelPrinterSetUp', [newPrinter]);
+ }
}
cr.addSingletonGetter(CupsPrintersBrowserProxyImpl);
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 9485e7c1659..52fff4a8457 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -219,7 +219,8 @@
category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}">
+ category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -232,7 +233,8 @@
category="{{ContentSettingsTypes.BACKGROUND_SYNC}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.BACKGROUND_SYNC}}">
+ category="{{ContentSettingsTypes.BACKGROUND_SYNC}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -246,7 +248,8 @@
"$i18n{siteSettingsAskBeforeAccessingRecommended}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.CAMERA}}" read-only-list>
+ category="{{ContentSettingsTypes.CAMERA}}" read-only-list
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -271,7 +274,8 @@
</button>
</div>
<category-setting-exceptions
- category="{{ContentSettingsTypes.COOKIES}}">
+ category="{{ContentSettingsTypes.COOKIES}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -291,7 +295,8 @@
toggle-on-label="$i18n{siteSettingsShowAllRecommended}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.IMAGES}}">
+ category="{{ContentSettingsTypes.IMAGES}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -303,7 +308,8 @@
category="{{ContentSettingsTypes.GEOLOCATION}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.GEOLOCATION}}" read-only-list>
+ category="{{ContentSettingsTypes.GEOLOCATION}}" read-only-list
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -333,7 +339,8 @@
category="{{ContentSettingsTypes.JAVASCRIPT}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.JAVASCRIPT}}">
+ category="{{ContentSettingsTypes.JAVASCRIPT}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -347,7 +354,8 @@
category="{{ContentSettingsTypes.SOUND}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.SOUND}}">
+ category="{{ContentSettingsTypes.SOUND}}"
+ block-header="$i18n{siteSettingsBlockSound}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -362,7 +370,8 @@
"$i18n{siteSettingsAskBeforeAccessingRecommended}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.MIC}}" read-only-list>
+ category="{{ContentSettingsTypes.MIC}}" read-only-list
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -374,7 +383,8 @@
category="{{ContentSettingsTypes.NOTIFICATIONS}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.NOTIFICATIONS}}">
+ category="{{ContentSettingsTypes.NOTIFICATIONS}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -394,7 +404,8 @@
</a>
</if>
<category-setting-exceptions
- category="{{ContentSettingsTypes.PLUGINS}}">
+ category="{{ContentSettingsTypes.PLUGINS}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -405,7 +416,8 @@
toggle-on-label="$i18n{siteSettingsAllowed}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.POPUPS}}">
+ category="{{ContentSettingsTypes.POPUPS}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -420,7 +432,8 @@
</category-default-setting>
<category-setting-exceptions
category="{{ContentSettingsTypes.ADS}}"
- read-only-list>
+ read-only-list
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -434,7 +447,8 @@
category="{{ContentSettingsTypes.UNSANDBOXED_PLUGINS}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.UNSANDBOXED_PLUGINS}}">
+ category="{{ContentSettingsTypes.UNSANDBOXED_PLUGINS}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -447,7 +461,8 @@
category="{{ContentSettingsTypes.MIDI_DEVICES}}">
</category-default-setting>
<category-setting-exceptions
- category="{{ContentSettingsTypes.MIDI_DEVICES}}" read-only-list>
+ category="{{ContentSettingsTypes.MIDI_DEVICES}}" read-only-list
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</settings-subpage>
</template>
@@ -494,7 +509,8 @@
<template is="dom-if"
if="[[prefs.settings.privacy.drm_enabled.value]]">
<category-setting-exceptions
- category="{{ContentSettingsTypes.PROTECTED_CONTENT}}">
+ category="{{ContentSettingsTypes.PROTECTED_CONTENT}}"
+ block-header="$i18n{siteSettingsBlock}">
</category-setting-exceptions>
</template>
</if>
diff --git a/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.js b/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.js
index ae48f3d09ba..2ff5c06ee71 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.js
+++ b/chromium/chrome/browser/resources/settings/reset_page/powerwash_dialog.js
@@ -4,12 +4,17 @@
/**
* @fileoverview
- * 'settings-reset-page' is the settings page containing reset
- * settings.
+ * 'settings-powerwash-dialog' is a dialog shown to request confirmation from
+ * the user for a device reset (aka powerwash).
*/
Polymer({
is: 'settings-powerwash-dialog',
+ properties: {
+ /** @public */
+ requestTpmFirmwareUpdate: Boolean,
+ },
+
/** @override */
attached: function() {
settings.ResetBrowserProxyImpl.getInstance().onPowerwashDialogShow();
@@ -23,6 +28,7 @@ Polymer({
/** @private */
onRestartTap_: function() {
- settings.LifetimeBrowserProxyImpl.getInstance().factoryReset();
+ settings.LifetimeBrowserProxyImpl.getInstance().factoryReset(
+ this.requestTpmFirmwareUpdate);
},
});
diff --git a/chromium/chrome/browser/resources/settings/route.js b/chromium/chrome/browser/resources/settings/route.js
index d4dee7d83f3..20b8d4b29a7 100644
--- a/chromium/chrome/browser/resources/settings/route.js
+++ b/chromium/chrome/browser/resources/settings/route.js
@@ -160,6 +160,15 @@ cr.define('settings', function() {
}
/**
+ * Returns the absolute path string for this Route, assuming this function
+ * has been called from within chrome://settings.
+ * @return {string}
+ */
+ getAbsolutePath() {
+ return window.location.origin + this.path;
+ }
+
+ /**
* Returns true if this route matches or is an ancestor of the parameter.
* @param {!settings.Route} route
* @return {boolean}
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
index cd6e4d6f295..947dcbefc39 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.js
@@ -85,6 +85,8 @@ cr.define('settings', function() {
/** @param {boolean} enabled */
setHotwordSearchEnabled(enabled) {}
+
+ turnOnGoogleAssistant() {}
}
/**
@@ -140,6 +142,11 @@ cr.define('settings', function() {
setHotwordSearchEnabled(enabled) {
chrome.send('setHotwordSearchEnabled', [enabled]);
}
+
+ /** @override */
+ turnOnGoogleAssistant() {
+ chrome.send('turnOnGoogleAssistant');
+ }
}
// The singleton instance_ is replaced with a test version of this wrapper
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 ad39252a6b1..e10d8141330 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.html
@@ -150,20 +150,29 @@
<if expr="chromeos">
<!-- Google Assistant -->
- <template is="dom-if" if="[[showAssistantSection_(
- voiceInteractionFeatureEnabled_, prefs.arc.enabled.value,
- prefs.arc.voice_interaction_value_prop.accepted.value)]]">
+ <template is="dom-if" if="[[voiceInteractionFeatureEnabled_]]">
<div id="assistant-subpage-trigger" class="settings-box two-line"
on-tap="onGoogleAssistantTap_" actionable>
- <div class="start">
- $i18n{searchGoogleAssistant}
- <div class="secondary">
- [[getAssistantEnabledDisabledLabel_(
- prefs.settings.voice_interaction.enabled.value)]]
+ <div class="start">
+ $i18n{searchGoogleAssistant}
+ <div class="secondary">
+ [[getAssistantEnabledDisabledLabel_(
+ prefs.settings.voice_interaction.enabled.value)]]
+ </div>
</div>
- </div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label="$i18n{searchGoogleAssistant}"></button>
+ <template is="dom-if" if="[[assistantOn_]]">
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label="$i18n{searchGoogleAssistant}"></button>
+ </template>
+ <template is="dom-if" if="[[!assistantOn_]]">
+ <div class="separator"></div>
+ <paper-button id="enable" class="secondary-button"
+ on-tap="onAssistantTurnOnTap_"
+ aria-label="$i18n{searchPageTitle}"
+ aria-describedby="secondaryText">
+ $i18n{assistantTurnOn}
+ </paper-button>
+ </template>
</div>
</template>
</if>
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 0d89eee48c0..3dbfcf19d69 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.js
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.js
@@ -14,6 +14,12 @@ Polymer({
properties: {
prefs: Object,
+ // <if expr="chromeos">
+ arcEnabled: Boolean,
+
+ voiceInteractionValuePropAccepted: Boolean,
+ // </if>
+
/**
* List of default search engines available.
* @private {!Array<!SearchEngine>}
@@ -50,6 +56,13 @@ Polymer({
value: function() {
return loadTimeData.getBoolean('enableVoiceInteraction');
},
+ },
+
+ /** @private */
+ assistantOn_: {
+ type: Boolean,
+ computed:
+ 'isAssistantTurnedOn_(arcEnabled, voiceInteractionValuePropAccepted)',
}
// </if>
},
@@ -112,8 +125,18 @@ Polymer({
/** @private */
onGoogleAssistantTap_: function() {
assert(this.voiceInteractionFeatureEnabled_);
+
+ if (!this.assistantOn_) {
+ return;
+ }
+
settings.navigateTo(settings.routes.GOOGLE_ASSISTANT);
},
+
+ /** @private */
+ onAssistantTurnOnTap_: function(event) {
+ this.browserProxy_.turnOnGoogleAssistant();
+ },
// </if>
/**
@@ -190,15 +213,13 @@ Polymer({
'searchGoogleAssistantDisabled');
},
- /**
- * @param {boolean} featureAvailable
- * @param {boolean} arcEnabled
- * @return {boolean}
- * @private
+ /** @private
+ * @param {boolean} arcEnabled
+ * @param {boolean} valuePropAccepted
+ * @return {boolean}
*/
- showAssistantSection_: function(
- featureAvailable, arcEnabled, valuePropAccepted) {
- return featureAvailable && arcEnabled && valuePropAccepted;
+ isAssistantTurnedOn_: function(arcEnabled, valuePropAccepted) {
+ return arcEnabled && valuePropAccepted;
},
// </if>
diff --git a/chromium/chrome/browser/resources/settings/search_settings.js b/chromium/chrome/browser/resources/settings/search_settings.js
index 2fb5a818ce4..b05aa1106f4 100644
--- a/chromium/chrome/browser/resources/settings/search_settings.js
+++ b/chromium/chrome/browser/resources/settings/search_settings.js
@@ -213,13 +213,10 @@ cr.define('settings', function() {
// Dynamically position the bubble at the edge the associated control
// element.
var updatePosition = function() {
- if (innards.classList.contains('above')) {
- searchBubble.style.top =
- element.offsetTop - searchBubble.offsetHeight + 'px';
- } else {
- searchBubble.style.top =
- element.offsetTop + element.offsetHeight + 'px';
- }
+ searchBubble.style.top = element.offsetTop +
+ (innards.classList.contains('above') ? -searchBubble.offsetHeight :
+ element.offsetHeight) +
+ 'px';
};
updatePosition();
diff --git a/chromium/chrome/browser/resources/settings/settings.html b/chromium/chrome/browser/resources/settings/settings.html
index f56ed01b94b..8732184b614 100644
--- a/chromium/chrome/browser/resources/settings/settings.html
+++ b/chromium/chrome/browser/resources/settings/settings.html
@@ -3,8 +3,8 @@
<head>
<meta charset="utf-8">
<title>$i18n{settings}</title>
-<if expr="not use_vulcanize">
- <base href="chrome://$i18n{hostname}">
+<if expr="not optimize_webui">
+ <base href="chrome://settings">
</if>
<style>
html {
diff --git a/chromium/chrome/browser/resources/settings/settings_icons_css.html b/chromium/chrome/browser/resources/settings/settings_icons_css.html
index 6936eac4e18..8e4bc428719 100644
--- a/chromium/chrome/browser/resources/settings/settings_icons_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_icons_css.html
@@ -4,12 +4,6 @@
<dom-module id="settings-icons">
<template>
<style>
- button[is='paper-icon-button-light'].icon-visibility {
- background-image: url(./images/settings_icon_visibility.svg);
- }
- button[is='paper-icon-button-light'].icon-visibility-off {
- background-image: url(./images/settings_icon_visibility_off.svg);
- }
<if expr="chromeos">
button[is='paper-icon-button-light'].icon-add-circle {
background-image: url(./images/settings_icon_add_circle.svg);
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 735fdfe0324..ffe06b5ee5a 100644
--- a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -73,15 +73,15 @@
-webkit-margin-end: 22px; /* 24px - 2px from margin for outline. */
}
- .separator {
- /* Per Alan@, this line is different from the other separator lines. */
+ #menuSeparator {
+ /* Per bettes@, this is different from the other separator lines. */
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
margin-bottom: 8px;
margin-top: 8px;
}
</style>
<iron-selector id="topMenu" selectable="a" attr-for-selected="href"
- on-iron-activate="onSelectorActivate_">
+ on-iron-activate="onSelectorActivate_" role="navigation">
<if expr="chromeos">
<a href="/internet">
<iron-icon icon="settings:network-wifi"></iron-icon>
@@ -137,7 +137,8 @@
</iron-icon></paper-button>
<iron-collapse id="advancedSubmenu" opened="[[advancedOpened]]"
hidden="[[!pageVisibility.advancedSettings]]">
- <iron-selector id="subMenu" selectable="a" attr-for-selected="href">
+ <iron-selector id="subMenu" selectable="a" attr-for-selected="href"
+ role="navigation">
<if expr="chromeos">
<a href="/dateTime">
<iron-icon icon="settings:access-time"></iron-icon>
@@ -167,7 +168,7 @@
</a>
<if expr="chromeos">
<a href="/multidevice" hidden="[[!showMultidevice]]">
- <iron-icon icon="settings:sync"></iron-icon>
+ <iron-icon icon="settings:devices-other"></iron-icon>
$i18n{multidevicePageTitle}
</a>
</if>
@@ -187,7 +188,7 @@
</a>
</iron-selector>
</iron-collapse>
- <div class="separator"></div>
+ <div id="menuSeparator"></div>
<a id="about-menu" href="/help">$i18n{aboutPageTitle}</a>
</iron-selector>
</template>
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
index d4dd9b9d3f9..7fca4be7942 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
@@ -150,13 +150,19 @@ Polymer({
if (oldRoute) {
if (oldRoute.isSubpage() && newRoute.depth > oldRoute.depth) {
- // Slide left for a deeper subpage.
- this.$.animatedPages.exitAnimation = 'slide-left-animation';
- this.$.animatedPages.entryAnimation = 'slide-from-right-animation';
+ var isRtl = loadTimeData.getString('textdirection') == 'rtl';
+ var exit = isRtl ? 'right' : 'left';
+ var entry = isRtl ? 'left' : 'right';
+ this.$.animatedPages.exitAnimation = 'slide-' + exit + '-animation';
+ this.$.animatedPages.entryAnimation =
+ 'slide-from-' + entry + '-animation';
} else if (oldRoute.depth > newRoute.depth) {
- // Slide right for a shallower subpage.
- this.$.animatedPages.exitAnimation = 'slide-right-animation';
- this.$.animatedPages.entryAnimation = 'slide-from-left-animation';
+ var isRtl = loadTimeData.getString('textdirection') == 'rtl';
+ var exit = isRtl ? 'left' : 'right';
+ var entry = isRtl ? 'right' : 'left';
+ this.$.animatedPages.exitAnimation = 'slide-' + exit + '-animation';
+ this.$.animatedPages.entryAnimation =
+ 'slide-from-' + entry + '-animation';
} else {
// The old route is not a subpage or is at the same level, so just fade.
this.$.animatedPages.exitAnimation = 'settings-fade-out-animation';
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 ae615482e8b..cdbdcb2689a 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
@@ -46,10 +46,8 @@
}
h1 {
- color: var(--settings-nav-grey);
flex: 1; /* Push other items to the end. */
- font-size: 107.6923%; /* Go to 14px from 13px */
- font-weight: 500;
+ @apply(--cr-title-text);
}
settings-subpage-search {
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js
index 46ede2dd2bc..d00516cda67 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js
@@ -49,6 +49,31 @@ Polymer({
},
},
+ /** @override */
+ attached: function() {
+ if (!!this.searchLabel) {
+ // |searchLabel| should not change dynamically.
+ this.listen(this, 'clear-subpage-search', 'onClearSubpageSearch_');
+ }
+ },
+
+ /** @override */
+ detached: function() {
+ if (!!this.searchLabel) {
+ // |searchLabel| should not change dynamically.
+ this.unlisten(this, 'clear-subpage-search', 'onClearSubpageSearch_');
+ }
+ },
+
+ /**
+ * Clear the value of the search field.
+ * @param {!Event} e
+ */
+ onClearSubpageSearch_: function(e) {
+ e.stopPropagation();
+ this.$$('settings-subpage-search').setValue('');
+ },
+
/** @private */
onTapBack_: function() {
settings.navigateToPreviousRoute();
diff --git a/chromium/chrome/browser/resources/settings/settings_resources.grd b/chromium/chrome/browser/resources/settings/settings_resources.grd
index de0aeb34fa1..93c5edf1a72 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources.grd
@@ -76,7 +76,8 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_ALL_SITES_JS"
file="site_settings/all_sites.js"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_CATEGORY_DEFAULT_SETTING_HTML"
file="site_settings/category_default_setting.html"
type="chrome_html" />
@@ -417,9 +418,6 @@
<structure name="IDR_SETTINGS_COOKIE_INFO_JS"
file="site_settings/cookie_info.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_COOKIE_TREE_NODE_JS"
- file="site_settings/cookie_tree_node.js"
- type="chrome_html" />
<if expr="not chromeos">
<structure name="IDR_SETTINGS_DEFAULT_BROWSER_BROWSER_PROXY_HTML"
file="default_browser_page/default_browser_browser_proxy.html"
@@ -523,12 +521,6 @@
type="chrome_html" />
</if>
- <structure name="IDR_SETTINGS_DIRECTION_DELEGATE_HTML"
- file="direction_delegate.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DIRECTION_DELEGATE_JS"
- file="direction_delegate.js"
- type="chrome_html" />
<structure name="IDR_SETTINGS_DOWNLOADS_BROWSER_PROXY_HTML"
file="downloads_page/downloads_browser_proxy.html"
type="chrome_html" />
@@ -681,7 +673,8 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_PASSWORDS_SECTION_JS"
file="passwords_and_forms_page/passwords_section.js"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_PASSWORD_EDIT_DIALOG_HTML"
file="passwords_and_forms_page/password_edit_dialog.html"
type="chrome_html" />
@@ -826,6 +819,12 @@
<structure name="IDR_SETTINGS_CLOUD_PRINTING_PAGE_JS"
file="printing_page/cloud_printers.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_LOCAL_DATA_BROWSER_PROXY_HTML"
+ file="site_settings/local_data_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_LOCAL_DATA_BROWSER_PROXY_JS"
+ file="site_settings/local_data_browser_proxy.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PAGE_VISIBILITY_HTML"
file="page_visibility.html"
type="chrome_html" />
@@ -868,12 +867,6 @@
file="route.js"
type="chrome_html"
preprocess="true" />
- <structure name="IDR_SETTINGS_COOKIE_TREE_BEHAVIOR_HTML"
- file="site_settings/cookie_tree_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_COOKIE_TREE_BEHAVIOR_JS"
- file="site_settings/cookie_tree_behavior.js"
- type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_DATA_HTML"
file="site_settings/site_data.html"
type="chrome_html" />
@@ -900,8 +893,7 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_CONSTANTS_JS"
file="site_settings/constants.js"
- type="chrome_html"
- preprocess="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_CONSTANTS_HTML"
file="site_settings/constants.html"
type="chrome_html" />
@@ -910,7 +902,8 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_SETTINGS_PAGE_JS"
file="site_settings_page/site_settings_page.js"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_SITE_SETTINGS_PREFS_BROWSER_PROXY_HTML"
file="site_settings/site_settings_prefs_browser_proxy.html"
type="chrome_html" />
@@ -919,16 +912,19 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_DETAILS_HTML"
file="site_settings/site_details.html"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_SITE_DETAILS_JS"
file="site_settings/site_details.js"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_SITE_DETAILS_PERMISSION_HTML"
file="site_settings/site_details_permission.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_DETAILS_PERMISSION_JS"
file="site_settings/site_details_permission.js"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_DIALOG_JS"
file="search_engines_page/search_engine_dialog.js"
type="chrome_html" />
@@ -1148,18 +1144,6 @@
<structure name="IDR_SETTINGS_MULTIDEVICE_PAGE_JS"
file="multidevice_page/multidevice_page.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_CONFIG_INPUT_HTML"
- file="internet_page/network_config_input.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_CONFIG_INPUT_JS"
- file="internet_page/network_config_input.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_CONFIG_SELECT_HTML"
- file="internet_page/network_config_select.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_CONFIG_SELECT_JS"
- file="internet_page/network_config_select.js"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_SECTION_HTML"
file="internet_page/network_proxy_section.html"
type="chrome_html" />
diff --git a/chromium/chrome/browser/resources/settings/settings_shared_css.html b/chromium/chrome/browser/resources/settings/settings_shared_css.html
index 4f0c690a92b..36f43725cd7 100644
--- a/chromium/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_shared_css.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/paper_checkbox_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_input_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/paper_toggle_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
@@ -10,7 +11,7 @@
<!-- Common styles for Material Design settings. -->
<dom-module id="settings-shared">
<template>
- <style include="settings-icons paper-button-style paper-checkbox-style paper-toggle-style cr-shared-style">
+ <style include="settings-icons paper-button-style paper-checkbox-style paper-input-style paper-toggle-style cr-shared-style">
/* Prevent action-links from being selected to avoid accidental
* selection when trying to click it. */
a[is=action-link] {
@@ -62,6 +63,11 @@
-webkit-margin-start: var(--cr-icon-ripple-margin);
}
+ neon-animatable {
+ display: flex;
+ flex-direction: column;
+ }
+
/* For "Advanced" toggle button. */
paper-button[toggles][active] {
background-color: var(--paper-grey-300);
@@ -84,7 +90,7 @@
}
/* Adjust the margin between the separator and the first button. */
- .settings-box .separator + paper-button {
+ .separator + paper-button {
-webkit-margin-start: calc(var(--cr-button-edge-spacing) * -1);
}
@@ -111,9 +117,6 @@
a[href] {
color: var(--google-blue-700);
- }
-
- a[href] {
text-decoration: none;
}
@@ -131,11 +134,6 @@
color: var(--google-blue-500);
}
- paper-input {
- /* Fix issue with focus animation making labels wiggle. */
- transform: translate3d(0, 0, 0);
- }
-
controlled-radio-button,
paper-radio-button {
--paper-radio-button-checked-color: var(--google-blue-500);
@@ -168,10 +166,6 @@
min-width: 0;
}
- .button-strip {
- text-align: end;
- }
-
.header-aligned-button {
margin-top: 12px; /* Align paper-button with <h2>. */
}
@@ -318,11 +312,6 @@
min-width: 0; /* Workaround for text elision in sub-elements. */
}
- /* Expand to fill-up available space. */
- .settings-row.wide {
- flex: 1;
- }
-
.no-outline {
background: none;
outline: none;
@@ -347,7 +336,7 @@
/* The separator a vertical line like a horizontal rule <hr> tag, but goes
* the other way. An example is near the |sign out| button on the People
* settings. */
- :-webkit-any(.settings-box, .list-item) .separator {
+ .separator {
-webkit-border-start: var(--settings-separator-line);
-webkit-margin-end: var(--settings-box-row-padding);
-webkit-margin-start: var(--settings-box-row-padding);
@@ -357,7 +346,7 @@
var(--settings-separator-gaps));
}
- :-webkit-any(.settings-box, .list-item).two-line .separator {
+ .two-line .separator {
height: calc(var(--settings-row-two-line-min-height) -
2 * var(--settings-separator-gaps));
}
diff --git a/chromium/chrome/browser/resources/settings/settings_ui/compiled_resources2.gyp b/chromium/chrome/browser/resources/settings/settings_ui/compiled_resources2.gyp
index 4000384e577..57468081491 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/settings_ui/compiled_resources2.gyp
@@ -7,11 +7,11 @@
'target_name': 'settings_ui',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_container_shadow_behavior',
'<(DEPTH)/ui/webui/resources/cr_elements/cr_drawer/compiled_resources2.gyp:cr_drawer',
'<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar',
'<(DEPTH)/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp:cr_toolbar_search_field',
'<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_indicator_behavior',
- '../compiled_resources2.gyp:direction_delegate',
'../compiled_resources2.gyp:global_scroll_target_behavior',
'../prefs/compiled_resources2.gyp:prefs',
'../settings_main/compiled_resources2.gyp:settings_main',
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 27bc50b5909..0b217e7ada0 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html
+++ b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -1,10 +1,10 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="../direction_delegate.html">
<link rel="import" href="../global_scroll_target_behavior.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../icons.html">
@@ -33,12 +33,6 @@
user-select: text;
}
- .last {
- display: flex;
- justify-content: flex-end;
- width: 100%;
- }
-
dialog[is='cr-drawer'] {
z-index: 2;
}
@@ -58,25 +52,6 @@
overflow: overlay;
position: relative;
}
-
- #dropShadow {
- /* TODO(dpapad): This box-shadow is repeated in Settings, History and
- Downloads. Define a CSS variable instead and re-use. */
- box-shadow: inset 0 5px 6px -3px rgba(0, 0, 0, 0.4);
- height: 6px;
- left: 0;
- opacity: 0;
- pointer-events: none;
- position: absolute;
- right: 0;
- top: 56px;
- transition: opacity 500ms;
- z-index: 1;
- }
-
- #dropShadow.has-shadow {
- opacity: 1;
- }
</style>
<settings-prefs id="prefs" prefs="{{prefs}}"></settings-prefs>
<cr-toolbar page-name="$i18n{settings}"
@@ -86,11 +61,11 @@
spinner-active="[[toolbarSpinnerActive_]]"
menu-label="$i18n{menuButtonLabel}"
on-search-changed="onSearchChanged_"
- role="none"
+ role="banner"
show-menu>
</cr-toolbar>
<dialog id="drawer" is="cr-drawer" on-close="onMenuClosed_"
- heading="$i18n{settings}">
+ heading="$i18n{settings}" align="$i18n{textdirection}">
<div class="drawer-content">
<template is="dom-if" id="drawerTemplate">
<settings-menu page-visibility="[[pageVisibility_]]"
@@ -103,10 +78,7 @@
</template>
</div>
</dialog>
- <div id="dropShadow"></div>
<div id="container" class="no-outline">
- <!-- Used by IntersectionObserver, has a 0px height intentionally -->
- <div id="intersectionProbe"></div>
<settings-main id="main" prefs="{{prefs}}"
toolbar-spinner-active="{{toolbarSpinnerActive_}}"
page-visibility="[[pageVisibility_]]"
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 cb96a4ffd15..9a00a856991 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -20,7 +20,7 @@ settings.defaultResourceLoaded = true;
Polymer({
is: 'settings-ui',
- behaviors: [settings.RouteObserverBehavior],
+ behaviors: [settings.RouteObserverBehavior, CrContainerShadowBehavior],
properties: {
/**
@@ -28,13 +28,6 @@ Polymer({
*/
prefs: Object,
- /** @type {?settings.DirectionDelegate} */
- directionDelegate: {
- observer: 'directionDelegateChanged_',
- type: Object,
- value: new settings.DirectionDelegateImpl(),
- },
-
/** @private */
advancedOpened_: {
type: Boolean,
@@ -127,13 +120,15 @@ Polymer({
loadTimeData.getString('networkListItemInitializing'),
networkListItemNotConnected:
loadTimeData.getString('networkListItemNotConnected'),
+ networkListItemNoNetwork:
+ loadTimeData.getString('networkListItemNoNetwork'),
vpnNameTemplate: loadTimeData.getString('vpnNameTemplate'),
};
// </if>
this.showAndroidApps_ = loadTimeData.valueExists('androidAppsVisible') &&
loadTimeData.getBoolean('androidAppsVisible');
- this.showMultidevice_ =
+ this.showMultidevice_ = this.showAndroidApps_ &&
loadTimeData.valueExists('enableMultideviceSettings') &&
loadTimeData.getBoolean('enableMultideviceSettings');
this.havePlayStoreApp_ = loadTimeData.valueExists('havePlayStoreApp') &&
@@ -148,9 +143,6 @@ Polymer({
});
},
- /** @private {?IntersectionObserver} */
- intersectionObserver_: null,
-
/** @override */
attached: function() {
document.documentElement.classList.remove('loading');
@@ -164,27 +156,11 @@ Polymer({
// Preload bold Roboto so it doesn't load and flicker the first time used.
document.fonts.load('bold 12px Roboto');
settings.setGlobalScrollTarget(this.$.container);
-
- // Setup drop shadow logic.
- var callback = entries => {
- this.$.dropShadow.classList.toggle(
- 'has-shadow', entries[entries.length - 1].intersectionRatio == 0);
- };
-
- this.intersectionObserver_ = new IntersectionObserver(
- callback,
- /** @type {IntersectionObserverInit} */ ({
- root: this.$.container,
- threshold: 0,
- }));
- this.intersectionObserver_.observe(this.$.intersectionProbe);
},
/** @override */
detached: function() {
settings.resetRouteForTesting();
- this.intersectionObserver_.disconnect();
- this.intersectionObserver_ = null;
},
/** @param {!settings.Route} route */
@@ -265,9 +241,4 @@ Polymer({
this.$.container.removeAttribute('tabindex');
});
},
-
- /** @private */
- directionDelegateChanged_: function() {
- this.$.drawer.align = this.directionDelegate.isRtl() ? 'right' : 'left';
- },
});
diff --git a/chromium/chrome/browser/resources/settings/settings_vars_css.html b/chromium/chrome/browser/resources/settings/settings_vars_css.html
index 9efc68e9f65..595e689d955 100644
--- a/chromium/chrome/browser/resources/settings/settings_vars_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_vars_css.html
@@ -59,38 +59,11 @@
--iron-icon-height: var(--cr-icon-size);
--iron-icon-width: var(--cr-icon-size);
- --paper-input-container-focus-color: var(--google-blue-500);
- --paper-input-container-input: {
- color: inherit;
- font-size: inherit;
- font-weight: inherit;
- line-height: 1.54;
- vertical-align: baseline;
- };
- --paper-input-container-label: {
- font-size: inherit;
- line-height: 1.54;
- };
- --paper-input-container-label-floating: {
- /* Using "rem" to make it easier to equalize with other labels. */
- font-size: 1rem;
- line-height: 1.65rem;
- };
- --paper-input-error: {
- font-size: 92.31%; /* Should be 12px when 100% is 13px. */
- line-height: 1.54;
- overflow: visible; /* Half-visible error message is not useful at all. */
- };
- --paper-input-max-width: 264px;
--paper-radio-button-ink-size: 40px;
--paper-radio-button-label-color: inherit;
--paper-radio-button-size: 16px;
--paper-radio-group-item-padding: 0;
- --settings-input-underline: {
- border-color: var(--paper-grey-300);
- };
-
- --paper-input-container-underline: var(--settings-input-underline);
+ --paper-tabs-selection-bar-color: var(--paper-blue-500);
}
</style>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/all_sites.js b/chromium/chrome/browser/resources/settings/site_settings/all_sites.js
index 3ac0f36bbc7..23f37fd1441 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/all_sites.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/all_sites.js
@@ -46,6 +46,10 @@ Polymer({
var types = Object.values(settings.ContentSettingsTypes);
for (var i = 0; i < types.length; i++) {
var type = types[i];
+ // <if expr="not chromeos">
+ if (type == settings.ContentSettingsTypes.PROTECTED_CONTENT)
+ continue;
+ // </if>
if (type == settings.ContentSettingsTypes.PROTOCOL_HANDLERS ||
type == settings.ContentSettingsTypes.USB_DEVICES ||
type == settings.ContentSettingsTypes.ZOOM_LEVELS) {
diff --git a/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js b/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js
index 316f8bbed74..08f2e59a2fa 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/category_default_setting.js
@@ -82,9 +82,15 @@ Polymer({
/**
* A handler for changing the default permission value for a content type.
+ * This is also called during page setup after we get the default state.
* @private
*/
onChangePermissionControl_: function() {
+ // Don't override user settings with enforced settings.
+ if (this.controlParams_.enforcement ==
+ chrome.settingsPrivate.Enforcement.ENFORCED) {
+ return;
+ }
switch (this.category) {
case settings.ContentSettingsTypes.ADS:
case settings.ContentSettingsTypes.BACKGROUND_SYNC:
diff --git a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
index ab0925dea92..091cc75e231 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.html
@@ -18,7 +18,7 @@
<site-list
category="[[category]]"
category-subtype="[[ContentSetting.BLOCK]]"
- category-header="$i18n{siteSettingsBlock}"
+ category-header="[[blockHeader]]"
read-only-list="[[readOnlyList]]">
</site-list>
<site-list
diff --git a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
index 0d4a2107300..3bfe4e986d8 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/category_setting_exceptions.js
@@ -20,6 +20,11 @@ Polymer({
type: Boolean,
value: false,
},
+
+ /**
+ * The heading text for the blocked exception list.
+ */
+ blockHeader: String,
},
/** @override */
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 8130e09241a..fbc1a37e421 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
+++ b/chromium/chrome/browser/resources/settings/site_settings/compiled_resources2.gyp
@@ -57,36 +57,28 @@
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'media_picker',
+ 'target_name': 'local_data_browser_proxy',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
- 'site_settings_behavior',
- ],
- 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
- },
- {
- 'target_name': 'cookie_info',
- 'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(EXTERNS_GYP):chrome_send',
+ '<(EXTERNS_GYP):settings_private',
+ 'constants',
+ 'cookie_info',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'cookie_tree_behavior',
+ 'target_name': 'media_picker',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
- 'cookie_info',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'site_settings_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'cookie_tree_node',
+ 'target_name': 'cookie_info',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
- 'cookie_info',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -112,11 +104,15 @@
'target_name': 'site_data',
'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:web_ui_listener_behavior',
'<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
+ '../compiled_resources2.gyp:global_scroll_target_behavior',
'../settings_page/compiled_resources2.gyp:settings_subpage_search',
- 'cookie_tree_behavior',
- 'cookie_tree_node',
+ 'cookie_info',
+ 'local_data_browser_proxy',
+ 'site_settings_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -126,7 +122,7 @@
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'../compiled_resources2.gyp:route',
- 'site_settings_prefs_browser_proxy',
+ 'local_data_browser_proxy',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -150,6 +146,7 @@
'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)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'constants',
@@ -197,7 +194,6 @@
'<(EXTERNS_GYP):chrome_send',
'<(EXTERNS_GYP):settings_private',
'constants',
- 'cookie_tree_node',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/chrome/browser/resources/settings/site_settings/constants.js b/chromium/chrome/browser/resources/settings/site_settings/constants.js
index 163fc33fca4..44fbc1546d1 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/constants.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/constants.js
@@ -7,9 +7,9 @@ cr.exportPath('settings');
/**
* 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 in site_settings_helper.cc and the values
- * should be kept in sync.
+ * individual permissions under Site Details should appear here.
+ * This should be kept in sync with the |kContentSettingsTypeGroupNames| array
+ * in chrome/browser/ui/webui/site_settings_helper.cc
* @enum {string}
*/
settings.ContentSettingsTypes = {
@@ -30,9 +30,7 @@ settings.ContentSettingsTypes = {
MIDI_DEVICES: 'midi-sysex',
USB_DEVICES: 'usb-chooser-data',
ZOOM_LEVELS: 'zoom-levels',
- // <if expr="chromeos">
PROTECTED_CONTENT: 'protectedContent',
- // </if>
ADS: 'ads',
};
@@ -58,13 +56,16 @@ settings.ContentSetting = {
* @enum {string}
*/
settings.SiteSettingSource = {
+ DEFAULT: 'default',
+ // This source is for the Protected Media Identifier / Protected Content
+ // content setting only, which is only available on ChromeOS.
+ DRM_DISABLED: 'drm-disabled',
EMBARGO: 'embargo',
EXTENSION: 'extension',
INSECURE_ORIGIN: 'insecure-origin',
KILL_SWITCH: 'kill-switch',
POLICY: 'policy',
PREFERENCE: 'preference',
- DEFAULT: 'default',
};
/**
diff --git a/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.html b/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.html
deleted file mode 100644
index a9d7fd711e4..00000000000
--- a/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<link rel="import" href="site_settings_behavior.html">
-<link rel="import" href="site_settings_prefs_browser_proxy.html">
-<script src="cookie_tree_behavior.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.js b/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.js
deleted file mode 100644
index 38d95db2506..00000000000
--- a/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_behavior.js
+++ /dev/null
@@ -1,100 +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 A behavior for managing a tree of cookies.
- */
-
-/** @polymerBehavior */
-var CookieTreeBehaviorImpl = {
- properties: {
- /**
- * A summary list of all sites and how many entities each contain.
- * @type {!Array<!CookieDataSummaryItem>}
- */
- sites: Array,
-
- /**
- * The cookie tree with the details needed to display individual sites and
- * their contained data.
- * @type {!settings.CookieTreeNode}
- * @protected
- */
- rootCookieNode: Object,
- },
-
- /** @override */
- ready: function() {
- cr.addWebUIListener(
- 'onTreeItemRemoved', this.onTreeItemRemoved_.bind(this));
- this.rootCookieNode = new settings.CookieTreeNode(null);
- },
-
- /**
- * Called when the cookie list is ready to be shown.
- * @param {!CookieList} list The cookie list to show.
- * @return {Promise}
- * @private
- */
- loadChildren_: function(list) {
- var loadChildrenRecurse = childList => {
- var parentId = childList.id;
- var children = childList.children;
- var prefix = '';
- if (parentId !== null) {
- this.rootCookieNode.populateChildNodes(
- parentId, this.rootCookieNode, children);
- prefix = parentId + ', ';
- }
- var promises = [];
- for (var i = 0; i < children.length; i++) {
- var child = children[i];
- if (child.hasChildren) {
- promises.push(this.browserProxy.loadCookieChildren(prefix + child.id)
- .then(loadChildrenRecurse.bind(this)));
- }
- }
- return Promise.all(promises);
- };
-
- // New root being added, clear the list and add the nodes.
- this.sites = [];
- this.rootCookieNode.addChildNodes(this.rootCookieNode, list.children);
- return loadChildrenRecurse(list).then(() => {
- this.sites = this.rootCookieNode.getSummaryList();
- return Promise.resolve();
- });
- },
-
- /**
- * Loads (or reloads) the whole cookie list.
- * @return {Promise}
- */
- loadCookies: function() {
- return this.browserProxy.reloadCookies().then(
- this.loadChildren_.bind(this));
- },
-
- /**
- * Called when a single item has been removed (not during delete all).
- * @param {!CookieRemovePacket} args The details about what to remove.
- * @private
- */
- onTreeItemRemoved_: function(args) {
- this.rootCookieNode.removeByParentId(args.id, args.start, args.count);
- this.sites = this.rootCookieNode.getSummaryList();
- },
-
- /**
- * Deletes site data for multiple sites.
- * @return {Promise}
- */
- removeAllCookies: function() {
- return this.browserProxy.removeAllCookies().then(
- this.loadChildren_.bind(this));
- },
-};
-
-/** @polymerBehavior */
-var CookieTreeBehavior = [SiteSettingsBehavior, CookieTreeBehaviorImpl];
diff --git a/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_node.js b/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_node.js
deleted file mode 100644
index 2e27145a167..00000000000
--- a/chromium/chrome/browser/resources/settings/site_settings/cookie_tree_node.js
+++ /dev/null
@@ -1,234 +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.
-
-/**
- * @typedef {{title: string,
- * id: string,
- * data: CookieDetails}}
- */
-var CookieDataItem;
-
-/**
- * @typedef {{site: string,
- * id: string,
- * localData: string}}
- */
-var CookieDataSummaryItem;
-
-/**
- * @typedef {{id: string,
- * start: number,
- * children: !Array<CookieDetails>}}
- */
-var CookieList;
-
-/**
- * @typedef {{id: string,
- * start: number,
- * count: number}}
- */
-var CookieRemovePacket;
-
-var categoryLabels = {
- 'app_cache': loadTimeData.getString('cookieAppCache'),
- 'cache_storage': loadTimeData.getString('cookieCacheStorage'),
- 'channel_id': loadTimeData.getString('cookieChannelId'),
- 'cookie': loadTimeData.getString('cookieSingular'),
- 'database': loadTimeData.getString('cookieDatabaseStorage'),
- 'file_system': loadTimeData.getString('cookieFileSystem'),
- 'flash_lso': loadTimeData.getString('cookieFlashLso'),
- 'indexed_db': loadTimeData.getString('cookieDatabaseStorage'),
- 'local_storage': loadTimeData.getString('cookieLocalStorage'),
- 'service_worker': loadTimeData.getString('cookieServiceWorker'),
- 'media_license': loadTimeData.getString('cookieMediaLicense'),
-};
-
-/**
- * Retrieves the human friendly text to show for the type of cookie.
- * @param {string} dataType The datatype to look up.
- * @param {string} totalUsage How much data is being consumed.
- * @return {string} The human-friendly description for this cookie.
- */
-function getCookieDataCategoryText(dataType, totalUsage) {
- if (dataType == 'quota')
- return totalUsage;
- return categoryLabels[dataType];
-}
-
-cr.define('settings', function() {
- 'use strict';
-
- class CookieTreeNode {
- constructor(data) {
- /**
- * The data for this cookie node.
- * @type {CookieDetails}
- */
- this.data = data;
-
- /**
- * The child cookie nodes.
- * @private {!Array<!settings.CookieTreeNode>}
- */
- this.children_ = [];
- }
-
- /**
- * Converts a list of cookies and add them as CookieTreeNode children to
- * the given parent node.
- * @param {!settings.CookieTreeNode} parentNode The parent node to add
- * children to.
- * @param {!Array<!CookieDetails>} newNodes The list containing the data to
- * add.
- */
- addChildNodes(parentNode, newNodes) {
- var nodes = newNodes.map(function(x) {
- return new settings.CookieTreeNode(x);
- });
- parentNode.children_ = nodes;
- }
-
- /**
- * Looks up a parent node and adds a list of CookieTreeNodes to them.
- * @param {string} parentId The ID of the parent to add the nodes to.
- * @param {!settings.CookieTreeNode} startingNode The node to start with
- * when looking for the parent node to add the children to.
- * @param {!Array<!CookieDetails>} newNodes The list containing the data to
- add.
- * @return {boolean} True if the parent node was found.
- */
- populateChildNodes(parentId, startingNode, newNodes) {
- for (var i = 0; i < startingNode.children_.length; ++i) {
- if (startingNode.children_[i].data.id == parentId) {
- this.addChildNodes(startingNode.children_[i], newNodes);
- return true;
- }
-
- if (this.populateChildNodes(
- parentId, startingNode.children_[i], newNodes)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Removes child nodes from a node with a given id.
- * @param {string} id The id of the parent node to delete from.
- * @param {number} firstChild The index of the first child to start deleting
- * from.
- * @param {number} count The number of children to delete.
- */
- removeByParentId(id, firstChild, count) {
- var node = id == null ? this : this.fetchNodeById(id, true);
- node.children_.splice(firstChild, count);
- }
-
- /**
- * Returns an array of cookies from the current node within the cookie tree.
- * @return {!Array<!CookieDataItem>} The Cookie List.
- */
- getCookieList() {
- var list = [];
- for (var i = 0; i < this.children_.length; i++) {
- var child = this.children_[i];
- for (var j = 0; j < child.children_.length; j++) {
- var cookie = child.children_[j];
- list.push({
- title: cookie.data.title,
- id: cookie.data.id,
- data: cookie.data
- });
- }
- }
-
- return list;
- }
-
- /**
- * Get a summary list of all sites and their stored data.
- * @return {!Array<!CookieDataSummaryItem>} The summary list.
- */
- getSummaryList() {
- var list = [];
- for (var i = 0; i < this.children_.length; ++i) {
- var siteEntry = this.children_[i];
- var title = siteEntry.data.title;
- var id = siteEntry.data.id;
- var description = '';
-
- if (siteEntry.children_.length == 0)
- continue;
-
- for (var j = 0; j < siteEntry.children_.length; ++j) {
- var descriptionNode = siteEntry.children_[j];
- if (j > 0)
- description += ', ';
-
- // Some types, like quota, have no description nodes.
- var dataType = '';
- if (descriptionNode.data.type != undefined) {
- dataType = descriptionNode.data.type;
- } else {
- // A description node might not have children when it's deleted.
- if (descriptionNode.children_.length > 0)
- dataType = descriptionNode.children_[0].data.type;
- }
-
- var count =
- (dataType == 'cookie') ? descriptionNode.children_.length : 0;
- if (count > 1) {
- description += loadTimeData.getStringF('cookiePlural', count);
- } else {
- description += getCookieDataCategoryText(
- dataType, descriptionNode.data.totalUsage);
- }
- }
- list.push({site: title, id: id, localData: description});
- }
- list.sort(function(a, b) {
- return a.site.localeCompare(b.site);
- });
- return list;
- }
-
- /**
- * Fetch a CookieTreeNode by ID.
- * @param {string} id The ID to look up.
- * @param {boolean} recursive Whether to search the children also.
- * @return {settings.CookieTreeNode} The node found, if any.
- */
- fetchNodeById(id, recursive) {
- for (var i = 0; i < this.children_.length; ++i) {
- if (this.children_[i] == null)
- return null;
- if (this.children_[i].data.id == id)
- return this.children_[i];
- if (recursive) {
- var node = this.children_[i].fetchNodeById(id, true);
- if (node != null)
- return node;
- }
- }
- return null;
- }
-
- /**
- * Fetch a CookieTreeNode by site.
- * @param {string} site The web site to look up.
- * @return {?settings.CookieTreeNode} The node found, if any.
- */
- fetchNodeBySite(site) {
- for (var i = 0; i < this.children_.length; ++i) {
- if (this.children_[i].data.title == site)
- return this.children_[i];
- }
- return null;
- }
- }
-
- return {
- CookieTreeNode: CookieTreeNode,
- };
-});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html b/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html
new file mode 100644
index 00000000000..00f30d023ca
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html
@@ -0,0 +1 @@
+<script src="local_data_browser_proxy.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js b/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
new file mode 100644
index 00000000000..28d4a1dccce
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
@@ -0,0 +1,140 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used from the Cookies and Local Storage Data
+ * section.
+ */
+
+/**
+ * @typedef {{
+ * id: string,
+ * start: number,
+ * children: !Array<CookieDetails>,
+ * }}
+ */
+var CookieList;
+
+/**
+ * @typedef {{
+ * data: !Object,
+ * id: string,
+ * }}
+ */
+var LocalDataItem;
+
+/**
+ * TODO(dschuyler): add |filter| and |order|.
+ * @typedef {{
+ * items: !Array<!LocalDataItem>,
+ * start: number,
+ * total: number,
+ * }}
+ */
+var LocalDataList;
+
+cr.define('settings', function() {
+ /** @interface */
+ class LocalDataBrowserProxy {
+ /**
+ * @param {string} filter Search filter (use "" for none).
+ * @param {number} begin Which element to start with. (Similar to 'offset'
+ * in SQL). The first item is at 0.
+ * @param {number} count How many list elements are displayed. (Similar to
+ * 'limit' in SQL). Pass -1 to get all remaining items.
+ * @return {!Promise<!LocalDataList>}
+ */
+ getDisplayList(filter, begin, count) {}
+
+ /**
+ * Removes all local data (local storage, cookies, etc.).
+ * Note: on-tree-item-removed will not be sent.
+ * @return {!Promise} To signal completion.
+ */
+ removeAll() {}
+
+ /**
+ * Remove items that pass the current filter. Completion signaled by
+ * on-tree-item-removed.
+ */
+ removeShownItems() {}
+
+ /**
+ * Remove a specific list item. Completion signaled by on-tree-item-removed.
+ * @param {string} id Which element to delete.
+ */
+ removeItem(id) {}
+
+ /**
+ * Gets the cookie details for a particular site.
+ * @param {string} site The name of the site.
+ * @return {!Promise<!CookieList>}
+ */
+ getCookieDetails(site) {}
+
+ /**
+ * Reloads all local data.
+ * TODO(dschuyler): rename function to reload().
+ * @return {!Promise} To signal completion.
+ */
+ reloadCookies() {}
+
+ /**
+ * TODO(dschuyler): merge with removeItem().
+ * Removes a given cookie.
+ * @param {string} path The path to the parent cookie.
+ */
+ removeCookie(path) {}
+ }
+
+ /**
+ * @implements {settings.LocalDataBrowserProxy}
+ */
+ class LocalDataBrowserProxyImpl {
+ /** @override */
+ getDisplayList(filter, begin, count) {
+ return cr.sendWithPromise(
+ 'localData.getDisplayList', filter, begin, count);
+ }
+
+ /** @override */
+ removeAll() {
+ return cr.sendWithPromise('localData.removeAll');
+ }
+
+ /** @override */
+ removeShownItems() {
+ chrome.send('localData.removeShownItems');
+ }
+
+ /** @override */
+ removeItem(id) {
+ chrome.send('localData.removeItem', [id]);
+ }
+
+ /** @override */
+ getCookieDetails(site) {
+ return cr.sendWithPromise('localData.getCookieDetails', site);
+ }
+
+ /** @override */
+ reloadCookies() {
+ return cr.sendWithPromise('localData.reload');
+ }
+
+ /** @override */
+ removeCookie(path) {
+ chrome.send('localData.removeCookie', [path]);
+ }
+ }
+
+ // The singleton instance_ is replaced with a test version of this wrapper
+ // during testing.
+ cr.addSingletonGetter(LocalDataBrowserProxyImpl);
+
+ return {
+ LocalDataBrowserProxy: LocalDataBrowserProxy,
+ LocalDataBrowserProxyImpl: LocalDataBrowserProxyImpl,
+ };
+});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data.html b/chromium/chrome/browser/resources/settings/site_settings/site_data.html
index eb8408f3dc5..eb7d2da4117 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data.html
@@ -3,13 +3,16 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/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/iron-list/iron-list.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="../global_scroll_target_behavior.html">
<link rel="import" href="../settings_page/settings_subpage_search.html">
<link rel="import" href="../settings_shared_css.html">
-<link rel="import" href="cookie_tree_behavior.html">
+<link rel="import" href="local_data_browser_proxy.html">
<link rel="import" href="site_settings_behavior.html">
<dom-module id="site-data">
@@ -23,38 +26,38 @@
-webkit-margin-start: auto;
}
- #removeSecondary {
+ .separator {
-webkit-padding-start: 0;
}
</style>
<div class="settings-box continuation">
<paper-button class="secondary-button" id="removeShowingSites"
- on-tap="onRemoveShowingSitesTap_"
- hidden$="[[!isRemoveButtonVisible_(sites, renderedItemCount)]]">
+ on-tap="onRemoveShowingSitesTap_" hidden$="[[!sites.length]]">
[[computeRemoveLabel_(filter)]]
</paper-button>
</div>
- <template is="dom-repeat" id="list" items="[[sites]]" filter="showItem_"
- rendered-item-count="{{renderedItemCount::dom-change}}"
- notify-dom-change>
- <div class="settings-box two-line" first$="[[!index]]" id="siteItem"
- on-tap="onSiteTap_" actionable>
- <div class="favicon-image" style$="[[computeSiteIcon(item.site)]]">
+ <iron-list id="list" items="[[sites]]"
+ scroll-target="[[subpageScrollTarget]]">
+ <template>
+ <div class="settings-box two-line site-item" first$="[[!index]]"
+ on-tap="onSiteTap_" actionable>
+ <div class="favicon-image"
+ style$="background-image: [[favicon_(item.site)]]">
+ </div>
+ <div class="middle">
+ [[item.site]]
+ <div class="secondary">[[item.localData]]</div>
+ </div>
+ <button class="subpage-arrow" is="paper-icon-button-light"
+ aria-label$="[[item.site]]"></button>
+ <div class="separator"></div>
+ <button is="paper-icon-button-light" class="icon-delete-gray"
+ title$="[[i18n('siteSettingsCookieRemoveSite', item.site)]]"
+ on-tap="onRemoveSiteTap_">
+ </button>
</div>
- <div class="middle">
- [[item.site]]
- <div class="secondary" id="siteSecondary">[[item.localData]]</div>
- </div>
- <button class="subpage-arrow" is="paper-icon-button-light"
- aria-label$="[[item.site]]"
- aria-describedby="siteSecondary"></button>
- <div class="separator" id="removeSecondary"></div>
- <button is="paper-icon-button-light" class="icon-delete-gray"
- title$="[[i18n('siteSettingsCookieRemoveSite', item.site)]]"
- on-tap="onRemoveSiteTap_">
- </button>
- </div>
- </template>
+ </template>
+ </iron-list>
<!-- Confirm Delete dialog -->
<dialog is="cr-dialog" id="confirmDeleteDialog" close-text="$i18n{close}"
@@ -62,7 +65,7 @@
<div slot="title">
$i18n{siteSettingsCookieRemoveDialogTitle}
</div>
- <div slot="body">[[confirmationDeleteMsg_]]</div>
+ <div slot="body">$i18n{siteSettingsCookieRemoveMultipleConfirmation}</div>
<div slot="button-container">
<paper-button class="cancel-button" on-tap="onCloseDialog_">
$i18n{cancel}
@@ -74,6 +77,5 @@
</dialog>
</template>
<script src="cookie_info.js"></script>
- <script src="cookie_tree_node.js"></script>
<script src="site_data.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data.js b/chromium/chrome/browser/resources/settings/site_settings/site_data.js
index d199c4b05c7..097465dbc0a 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data.js
@@ -8,6 +8,24 @@
*/
/**
+ * @typedef {{
+ * site: string,
+ * id: string,
+ * localData: string,
+ * }}
+ */
+var CookieDataSummaryItem;
+
+/**
+ * @typedef {{
+ * id: string,
+ * start: number,
+ * count: number,
+ * }}
+ */
+var CookieRemovePacket;
+
+/**
* TODO(dbeam): upstream to polymer externs?
* @constructor
* @extends {Event}
@@ -21,7 +39,9 @@ Polymer({
is: 'site-data',
behaviors: [
- CookieTreeBehavior,
+ I18nBehavior,
+ settings.GlobalScrollTargetBehavior,
+ WebUIListenerBehavior,
],
properties: {
@@ -29,25 +49,68 @@ Polymer({
* The current filter applied to the cookie data list.
*/
filter: {
- observer: 'onSearchChanged_',
+ observer: 'updateSiteList_',
notify: true,
type: String,
- value: '',
},
- /** @private */
- confirmationDeleteMsg_: String,
-
/** @type {!Map<string, string>} */
focusConfig: {
type: Object,
observer: 'focusConfigChanged_',
},
+
+ /** @type {!Array<!LocalDataItem>} */
+ sites: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /**
+ * settings.GlobalScrollTargetBehavior
+ * @override
+ */
+ subpageRoute: {
+ type: Object,
+ value: settings.routes.SITE_SETTINGS_SITE_DATA,
+ },
},
+ /** @private {settings.LocalDataBrowserProxy} */
+ browserProxy_: null,
+
/** @override */
ready: function() {
- this.loadCookies();
+ this.browserProxy_ = settings.LocalDataBrowserProxyImpl.getInstance();
+ this.addWebUIListener(
+ 'on-tree-item-removed', this.updateSiteList_.bind(this));
+ },
+
+ /**
+ * Reload cookies when the site data page is visited.
+ *
+ * settings.RouteObserverBehavior
+ * @param {!settings.Route} currentRoute
+ * @protected
+ */
+ currentRouteChanged: function(currentRoute) {
+ settings.GlobalScrollTargetBehaviorImpl.currentRouteChanged.call(
+ this, currentRoute);
+ if (currentRoute == settings.routes.SITE_SETTINGS_SITE_DATA) {
+ this.browserProxy_.reloadCookies().then(this.updateSiteList_.bind(this));
+ }
+ },
+
+ /**
+ * Returns the icon to use for a given site.
+ * @param {string} url The url of the site to fetch the icon for.
+ * @return {string} Value for background-image style.
+ * @private
+ */
+ favicon_: function(url) {
+ return cr.icon.getFavicon(url);
},
/**
@@ -71,33 +134,22 @@ Polymer({
},
/**
- * A filter function for the list.
- * @param {!CookieDataSummaryItem} item The item to possibly filter out.
- * @return {boolean} Whether to show the item.
+ * Gather all the site data.
* @private
*/
- showItem_: function(item) {
- if (this.filter.length == 0)
- return true;
- return item.site.indexOf(this.filter) > -1;
- },
-
- /** @private */
- onSearchChanged_: function() {
- this.$.list.render();
- },
-
- /**
- * @return {boolean} Whether to show the multiple site remove button.
- * @private
- */
- isRemoveButtonVisible_: function(sites, renderedItemCount) {
- return renderedItemCount != 0;
+ updateSiteList_: function() {
+ this.browserProxy_
+ .getDisplayList(this.filter, 0 /* start */, -1 /* count */)
+ .then((listInfo) => {
+ this.sites = listInfo.items;
+ this.fire('site-data-list-complete');
+ });
},
/**
* Returns the string to use for the Remove label.
- * @return {string} filter The current filter string.
+ * @param {string} filter The current filter string.
+ * @return {string}
* @private
*/
computeRemoveLabel_: function(filter) {
@@ -123,8 +175,6 @@ Polymer({
*/
onRemoveShowingSitesTap_: function(e) {
e.preventDefault();
- this.confirmationDeleteMsg_ =
- loadTimeData.getString('siteSettingsCookieRemoveMultipleConfirmation');
this.$.confirmDeleteDialog.showModal();
},
@@ -134,17 +184,14 @@ Polymer({
*/
onConfirmDelete_: function() {
this.$.confirmDeleteDialog.close();
-
if (this.filter.length == 0) {
- this.removeAllCookies();
+ this.browserProxy_.removeAll().then(() => {
+ this.sites = [];
+ });
} else {
- var items = this.$.list.items;
- for (var i = 0; i < items.length; ++i) {
- if (this.showItem_(items[i]))
- this.browserProxy.removeCookie(items[i].id);
- }
+ this.browserProxy_.removeShownItems();
// We just deleted all items found by the filter, let's reset the filter.
- /** @type {SettingsSubpageSearchElement} */ (this.$.filter).setValue('');
+ this.fire('clear-subpage-search');
}
},
@@ -155,7 +202,7 @@ Polymer({
*/
onRemoveSiteTap_: function(e) {
e.stopPropagation();
- this.browserProxy.removeCookie(e.model.item.id);
+ this.browserProxy_.removeItem(e.model.item.site);
},
/**
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html b/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html
index 7ab3d55d292..5544d8ffdbc 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html
@@ -6,7 +6,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html">
-<link rel="import" href="site_settings_prefs_browser_proxy.html">
+<link rel="import" href="local_data_browser_proxy.html">
<dom-module id="site-data-details-subpage">
<template>
@@ -45,6 +45,5 @@
</template>
</template>
<script src="cookie_info.js"></script>
- <script src="cookie_tree_node.js"></script>
<script src="site_data_details_subpage.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js b/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
index 0e913982cc0..8e8b802b64a 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data_details_subpage.js
@@ -5,6 +5,19 @@
(function() {
'use strict';
+var categoryLabels = {
+ app_cache: loadTimeData.getString('cookieAppCache'),
+ cache_storage: loadTimeData.getString('cookieCacheStorage'),
+ channel_id: loadTimeData.getString('cookieChannelId'),
+ database: loadTimeData.getString('cookieDatabaseStorage'),
+ file_system: loadTimeData.getString('cookieFileSystem'),
+ flash_lso: loadTimeData.getString('cookieFlashLso'),
+ indexed_db: loadTimeData.getString('cookieDatabaseStorage'),
+ local_storage: loadTimeData.getString('cookieLocalStorage'),
+ service_worker: loadTimeData.getString('cookieServiceWorker'),
+ media_license: loadTimeData.getString('cookieMediaLicense'),
+};
+
/**
* 'site-data-details-subpage' Display cookie contents.
*/
@@ -36,17 +49,16 @@ Polymer({
/**
* The browser proxy used to retrieve and change cookies.
- * @private {?settings.SiteSettingsPrefsBrowserProxy}
+ * @private {?settings.LocalDataBrowserProxy}
*/
browserProxy_: null,
/** @override */
ready: function() {
- this.browserProxy_ =
- settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
+ this.browserProxy_ = settings.LocalDataBrowserProxyImpl.getInstance();
this.addWebUIListener(
- 'onTreeItemRemoved', this.getCookieDetails_.bind(this));
+ 'on-tree-item-removed', this.getCookieDetails_.bind(this));
},
/**
@@ -59,7 +71,7 @@ Polymer({
settings.routes.SITE_SETTINGS_DATA_DETAILS)
return;
var site = settings.getQueryParameters().get('site');
- if (!site || site == this.site_)
+ if (!site)
return;
this.site_ = site;
this.pageTitle = loadTimeData.getStringF('siteSettingsCookieSubpage', site);
@@ -119,7 +131,9 @@ Polymer({
// cookie to differentiate them.
if (item.type == 'cookie')
return item.title;
- return getCookieDataCategoryText(item.type, item.totalUsage);
+ if (item.type == 'quota')
+ return item.totalUsage;
+ return categoryLabels[item.type];
},
/**
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 204d19eae53..4f903171bb8 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.html
@@ -111,12 +111,11 @@
icon="settings:sync" id="backgroundSync"
label="$i18n{siteSettingsBackgroundSync}">
</site-details-permission>
- <template is="dom-if" if="[[enableSoundContentSetting_]]" no-search>
- <site-details-permission category="{{ContentSettingsTypes.SOUND}}"
- icon="settings:volume-up" id="sound"
- label="$i18n{siteSettingsSound}">
- </site-details-permission>
- </template>
+ <site-details-permission category="{{ContentSettingsTypes.SOUND}}"
+ icon="settings:volume-up" id="sound"
+ label="$i18n{siteSettingsSound}"
+ hidden$="[[!enableSoundContentSetting_]]">
+ </site-details-permission>
<site-details-permission
category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}"
icon="cr:file-download" id="automaticDownloads"
@@ -131,6 +130,13 @@
icon="cr:extension" id="unsandboxedPlugins"
label="$i18n{siteSettingsUnsandboxedPlugins}">
</site-details-permission>
+<if expr="chromeos">
+ <site-details-permission
+ category="{{ContentSettingsTypes.PROTECTED_CONTENT}}"
+ icon="settings:security" id="protectedContent"
+ label="$i18n{siteSettingsProtectedContentIdentifiers}">
+ </site-details-permission>
+</if>
</div>
<div id="clearAndReset" class="settings-box"
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 b45b86d5e2f..cc2e9aec5c9 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.js
@@ -74,6 +74,11 @@ Polymer({
this.addWebUIListener(
'contentSettingSitePermissionChanged',
this.onPermissionChanged_.bind(this));
+
+ // <if expr="chromeos">
+ this.addWebUIListener(
+ 'prefEnableDrmChanged', this.prefEnableDrmChanged_.bind(this));
+ // </if>
},
/** @override */
@@ -108,7 +113,6 @@ Polymer({
this.updatePermissions_(this.getCategoryList_());
}
});
-
},
/**
@@ -132,6 +136,12 @@ Polymer({
this.updatePermissions_([category]);
},
+ // <if expr="chromeos">
+ prefEnableDrmChanged_: function() {
+ this.updatePermissions_([settings.ContentSettingsTypes.PROTECTED_CONTENT]);
+ },
+ // </if>
+
/**
* Retrieves the permissions listed in |categoryList| from the backend for
* |this.origin|.
@@ -222,10 +232,12 @@ Polymer({
* @private
*/
getCategoryList_: function() {
- return Array.prototype.map.call(
- this.root.querySelectorAll('site-details-permission'), (element) => {
- return element.category;
- });
+ var categoryList = [];
+ this.root.querySelectorAll('site-details-permission').forEach((element) => {
+ if (!element.hidden)
+ categoryList.push(element.category);
+ });
+ return categoryList;
},
/**
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 b356f183552..c55f5716acf 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,6 +1,7 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="../settings_shared_css.html">
@@ -13,7 +14,8 @@
<template>
<style include="settings-shared md-select"></style>
<div id="details">
- <div id="permissionItem" class="list-item">
+ <div id="permissionItem"
+ class$="list-item [[permissionSourceStringClass_(site.source)]]">
<div>
<iron-icon icon="[[icon]]">
</iron-icon>
@@ -21,8 +23,8 @@
<div class="middle" id="permissionHeader">
[[label]]
<div class="secondary"
- hidden$="[[!hasPermissionSourceString_(site.source)]]">
- [[permissionSourceString_(
+ hidden$="[[!hasPermissionSourceString_(site.source)]]"
+ inner-h-t-m-l="[[permissionSourceString_(
site.source,
'$i18nPolymer{siteSettingsSourceEmbargo}',
'$i18nPolymer{siteSettingsSourceInsecureOrigin}',
@@ -32,13 +34,14 @@
'$i18nPolymer{siteSettingsSourceExtensionAsk}',
'$i18nPolymer{siteSettingsSourcePolicyAllow}',
'$i18nPolymer{siteSettingsSourcePolicyBlock}',
- '$i18nPolymer{siteSettingsSourcePolicyAsk}')]]
+ '$i18nPolymer{siteSettingsSourcePolicyAsk}')]]">
</div>
</div>
<div class="md-select-wrapper">
<select id="permission" class="md-select"
aria-labelledby="permissionHeader"
- on-change="onPermissionSelectionChange_">
+ on-change="onPermissionSelectionChange_"
+ disabled$="[[!isPermissionUserControlled_(site.source)]]">
<option id="default" value$="[[ContentSetting.DEFAULT]]">
[[defaultSettingString_(
defaultSetting_,
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 26d8fd7237c..27c34c2dce2 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
@@ -10,7 +10,7 @@
Polymer({
is: 'site-details-permission',
- behaviors: [SiteSettingsBehavior, WebUIListenerBehavior],
+ behaviors: [SiteSettingsBehavior, WebUIListenerBehavior, I18nBehavior],
properties: {
/**
@@ -51,18 +51,6 @@ Polymer({
this.$.permission.value = site.setting;
}
- // Handle non-default sources.
- if (site.source == settings.SiteSettingSource.DEFAULT ||
- site.source == settings.SiteSettingSource.PREFERENCE) {
- this.$.permissionItem.classList.remove('two-line');
- this.$.permission.disabled = false;
- } else {
- this.$.permissionItem.classList.add('two-line');
- // Users are able to override embargo, so leave enabled in that case.
- this.$.permission.disabled =
- site.source != settings.SiteSettingSource.EMBARGO;
- }
-
if (this.isNonDefaultAsk_(site.setting, site.source)) {
assert(
this.$.permission.disabled,
@@ -143,6 +131,28 @@ Polymer({
},
/**
+ * Checks if there's a permission source string to display, and returns the
+ * class name to apply to permissions if so.
+ * @return {string} CSS class applied when there is an additional description
+ * string.
+ * @private
+ */
+ permissionSourceStringClass_: function(source) {
+ return this.hasPermissionSourceString_(source) ? 'two-line' : '';
+ },
+
+ /**
+ * Returns true if this permission's source is controlled by the user.
+ * @return {boolean}
+ * @private
+ */
+ isPermissionUserControlled_: function(source) {
+ // Users are able override embargo.
+ return !this.hasPermissionSourceString_(source) ||
+ source == settings.SiteSettingSource.EMBARGO;
+ },
+
+ /**
* Returns true if the permission is set to a non-default 'ask'. Currently,
* this only gets called when |this.site| is updated.
* @param {!settings.ContentSetting} setting The setting of the permission.
@@ -194,7 +204,18 @@ Polymer({
policyStrings[settings.ContentSetting.BLOCK] = policyBlockString;
policyStrings[settings.ContentSetting.ASK] = policyAskString;
- if (source == settings.SiteSettingSource.EMBARGO) {
+ if (source == settings.SiteSettingSource.DRM_DISABLED) {
+ assert(
+ settings.ContentSetting.BLOCK == this.site.setting,
+ 'If DRM is disabled, Protected Content must be blocked.');
+ assert(
+ settings.ContentSettingsTypes.PROTECTED_CONTENT == this.category,
+ 'The DRM disabled source only applies to Protected Content.');
+ return this.i18nAdvanced('siteSettingsSourceDrmDisabled', {
+ substitutions:
+ [settings.routes.SITE_SETTINGS_PROTECTED_CONTENT.getAbsolutePath()]
+ });
+ } else if (source == settings.SiteSettingSource.EMBARGO) {
assert(
settings.ContentSetting.BLOCK == this.site.setting,
'Embargo is only used to block permissions.');
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 899936a22cb..4f0141e4d32 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list.html
@@ -20,7 +20,11 @@
<dom-module id="site-list">
<template>
- <style include="settings-shared iron-flex"></style>
+ <style include="settings-shared">
+ .settings-row {
+ flex: 1
+ }
+ </style>
<div id="category">
<div class="settings-box first">
<h2 class="start">[[categoryHeader]]</h2>
@@ -59,7 +63,7 @@
<div class="list-frame menu-content vertical-list" id="listContainer">
<template is="dom-repeat" items="[[sites]]">
<div class="list-item">
- <div class="settings-row wide"
+ <div class="settings-row"
actionable$="[[enableSiteSettings_]]" on-tap="onOriginTap_">
<div class="favicon-image"
style$="[[computeSiteIcon(item.origin)]]">
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 0fe74d5f9da..6ab9c0a38a5 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
@@ -99,13 +99,6 @@ cr.define('settings', function() {
setDefaultValueForContentType(contentType, defaultValue) {}
/**
- * Gets the cookie details for a particular site.
- * @param {string} site The name of the site.
- * @return {!Promise<!CookieList>}
- */
- getCookieDetails(site) {}
-
- /**
* Gets the default value for a site settings category.
* @param {string} contentType The name of the category to query.
* @return {!Promise<!DefaultContentSetting>}
@@ -201,34 +194,6 @@ cr.define('settings', function() {
setDefaultCaptureDevice(type, defaultValue) {}
/**
- * Reloads all cookies.
- * @return {!Promise<!CookieList>} Returns the full cookie
- * list.
- */
- reloadCookies() {}
-
- /**
- * Fetches all children of a given cookie.
- * @param {string} path The path to the parent cookie.
- * @return {!Promise<!Array<!CookieDataSummaryItem>>} Returns a cookie list
- * for the given path.
- */
- loadCookieChildren(path) {}
-
- /**
- * Removes a given cookie.
- * @param {string} path The path to the parent cookie.
- */
- removeCookie(path) {}
-
- /**
- * Removes all cookies.
- * @return {!Promise<!CookieList>} Returns the up to date
- * cookie list once deletion is complete (empty list).
- */
- removeAllCookies() {}
-
- /**
* observes _all_ of the the protocol handler state, which includes a list
* that is returned through JS calls to 'setProtocolHandlers' along with
* other state sent with the messages 'setIgnoredProtocolHandler' and
@@ -285,7 +250,7 @@ cr.define('settings', function() {
removeUsbDevice(origin, embeddingOrigin, usbDevice) {}
/**
- * Fetches the incognito status of the current profile (whether an icognito
+ * Fetches the incognito status of the current profile (whether an incognito
* profile exists). Returns the results via onIncognitoStatusChanged.
*/
updateIncognitoStatus() {}
@@ -313,11 +278,6 @@ cr.define('settings', function() {
}
/** @override */
- getCookieDetails(site) {
- return cr.sendWithPromise('getCookieDetails', site);
- }
-
- /** @override */
getDefaultValueForContentType(contentType) {
return cr.sendWithPromise('getDefaultValueForContentType', contentType);
}
@@ -378,26 +338,6 @@ cr.define('settings', function() {
}
/** @override */
- reloadCookies() {
- return cr.sendWithPromise('reloadCookies');
- }
-
- /** @override */
- loadCookieChildren(path) {
- return cr.sendWithPromise('loadCookie', path);
- }
-
- /** @override */
- removeCookie(path) {
- chrome.send('removeCookie', [path]);
- }
-
- /** @override */
- removeAllCookies() {
- return cr.sendWithPromise('removeAllCookies');
- }
-
- /** @override */
observeProtocolHandlers() {
chrome.send('observeProtocolHandlers');
}
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 e41cefd7258..e3354d023cb 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
@@ -115,11 +115,16 @@ Polymer({
if (key == settings.ContentSettingsTypes.USB_DEVICES ||
key == settings.ContentSettingsTypes.ZOOM_LEVELS)
continue;
- // Some values are not available (and will DCHECK) in guest mode.
+ // Protocol handlers are not available (and will DCHECK) in guest mode.
if (this.isGuest_ &&
key == settings.ContentSettingsTypes.PROTOCOL_HANDLERS) {
continue;
}
+ // Similarly, protected content is only available in CrOS.
+ // <if expr="not chromeos">
+ if (key == settings.ContentSettingsTypes.PROTECTED_CONTENT)
+ continue;
+ // </if>
this.updateDefaultValueLabel_(key);
}
diff --git a/chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.html b/chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.html
deleted file mode 100644
index 54136bcd87c..00000000000
--- a/chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!doctype html>
-<html>
- <head>
- <meta charset="utf-8">
- <link rel="import" href="chrome://resources/html/polymer.html">
- <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
- <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
- <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="import" href="chrome://resources/html/cr.html">
- <link rel="import" href="chrome://resources/html/util.html">
- <style is="custom-style">
- .top-title-bar {
- align-items: center;
- border-bottom: 1px solid var(--paper-grey-300);
- display: flex;
- font-size: 16px;
- height: 52px;
- padding: 0 24px;
- }
- .container {
- background-color: white;
- color: #333;
- width: 448px;
- }
- .action-container {
- display: flex;
- justify-content: flex-start;
- padding: 16px;
- }
- paper-button.primary-action {
- --paper-button-flat-keyboard-focus: {
- background: rgb(58, 117, 215);
- font-weight: 500;
- };
- background: var(--google-blue-500);
- color: white;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <div class="top-title-bar">Desktop Identity Consistency Internals</div>
- <div class="action-container">
- <paper-button class="primary-action" id="enableSyncButton">
- Enable Sync
- </paper-button>
- </div>
- </div>
- </body>
- <script src="signin_dice_internals.js"></script>
-</html>
diff --git a/chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.js b/chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.js
deleted file mode 100644
index 4a63983482f..00000000000
--- a/chromium/chrome/browser/resources/signin/signin_dice_internals/signin_dice_internals.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright 2017 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-cr.define('signin.dice', function() {
- 'use strict';
-
- function initialize() {
- $('enableSyncButton').addEventListener('click', onEnableSync);
- }
-
- function onEnableSync(e) {
- chrome.send('enableSync');
- }
-
- return {
- initialize: initialize,
- };
-});
-
-document.addEventListener('DOMContentLoaded', signin.dice.initialize);
diff --git a/chromium/chrome/browser/resources/snippets_internals.html b/chromium/chrome/browser/resources/snippets_internals.html
index 9519cf97f50..07898877d79 100644
--- a/chromium/chrome/browser/resources/snippets_internals.html
+++ b/chromium/chrome/browser/resources/snippets_internals.html
@@ -5,7 +5,7 @@ found in the LICENSE file.
-->
<!DOCTYPE html>
<meta charset="utf-8">
-<if expr="is_android or is_ios">
+<if expr="is_android">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</if>
<title>Snippets Internals</title>
@@ -92,8 +92,13 @@ found in the LICENSE file.
<div id="snippets">
<h2>NTPSnippetsService</h2>
<div class="forms">
- <button id="submit-download" type="button">Add snippets</button>
- <span id="remote-status" class="detail"></span>
+ <div>
+ <button id="submit-download" type="button">Add snippets</button>
+ <span id="remote-status" class="detail"></span>
+ </div>
+ <div>
+ <button id="debug-log-dump" type="button">Dump the debug log</button>
+ </div>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/snippets_internals.js b/chromium/chrome/browser/resources/snippets_internals.js
index 69a4cb5ac14..63f19c5267c 100644
--- a/chromium/chrome/browser/resources/snippets_internals.js
+++ b/chromium/chrome/browser/resources/snippets_internals.js
@@ -7,6 +7,7 @@ cr.define('chrome.SnippetsInternals', function() {
// Stores the list of suggestions we received in receiveContentSuggestions.
var lastSuggestions = [];
+ var lastDebugLog = '';
function initialize() {
$('submit-download').addEventListener('click', function(event) {
@@ -19,6 +20,11 @@ cr.define('chrome.SnippetsInternals', function() {
event.preventDefault();
});
+ $('debug-log-dump').addEventListener('click', function(event) {
+ downloadDebugLog(lastDebugLog);
+ event.preventDefault();
+ });
+
$('last-json-button').addEventListener('click', function(event) {
$('last-json-container').classList.toggle('hidden');
});
@@ -66,6 +72,7 @@ cr.define('chrome.SnippetsInternals', function() {
window.addEventListener('focus', refreshContent);
window.setInterval(refreshContent, 1000);
+ chrome.send('initializationCompleted');
refreshContent();
}
@@ -136,6 +143,14 @@ cr.define('chrome.SnippetsInternals', function() {
}
}
+ function receiveDebugLog(debugLog) {
+ if (!debugLog) {
+ lastDebugLog = 'empty';
+ } else {
+ lastDebugLog = debugLog;
+ }
+ }
+
function receiveClassification(
userClass, timeToOpenNTP, timeToShow, timeToUse) {
receiveProperty('user-class', userClass);
@@ -155,6 +170,10 @@ cr.define('chrome.SnippetsInternals', function() {
lastRemoteSuggestionsBackgroundFetchTime);
}
+ function receiveWhetherSuggestionPushingPossible(possible) {
+ $('push-dummy-suggestion-10-seconds-button').disabled = !possible;
+ }
+
function downloadJson(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;
@@ -165,6 +184,17 @@ cr.define('chrome.SnippetsInternals', function() {
link.click();
}
+ function downloadDebugLog(debugLog) {
+ // Redirect the browser to download data in |debugLog| as a file
+ // "debug_log.txt" (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 = 'debug_log.txt';
+ link.href = 'data:text/plain,' + encodeURI(debugLog);
+ link.click();
+ }
+
function refreshContent() {
chrome.send('refreshContent');
}
@@ -205,10 +235,13 @@ cr.define('chrome.SnippetsInternals', function() {
receiveProperty: receiveProperty,
receiveContentSuggestions: receiveContentSuggestions,
receiveJson: receiveJson,
+ receiveDebugLog: receiveDebugLog,
receiveClassification: receiveClassification,
receiveRankerDebugData: receiveRankerDebugData,
receiveLastRemoteSuggestionsBackgroundFetchTime:
receiveLastRemoteSuggestionsBackgroundFetchTime,
+ receiveWhetherSuggestionPushingPossible:
+ receiveWhetherSuggestionPushingPossible,
receiveContextualSuggestions: receiveContextualSuggestions,
};
});
diff --git a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb b/chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb
index f98d4385429..4c68cda3468 100644
--- a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb
+++ b/chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb
@@ -6,7 +6,7 @@
# certificates. See chrome/browser/ssl/ssl_error_assistant.proto for the full
# format.
-version_id: 3
+version_id: 4
# https://captive-portal.badssl.com leaf.
# This is a test certificate, always keep it at the top.
@@ -151,7 +151,128 @@ captive_portal_cert {
sha256_hash: "sha256/LKtpdq9q7F7msGK0w1+b/gKoDHaQcZKTHIf9PTz2u+U="
}
+# https://mitm-software.badssl.com leaf.
+# This is a test certificate, keep it at the top of the MITM software list.
+mitm_software {
+ name: "BadSSL Antivirus",
+ issuer_common_name_regex: "BadSSL MITM Software Test"
+}
+
+################################################################################
+# The rest of the MITM software certificates are sorted alphabetically by name.
+
+mitm_software {
+ name: "Avast Antivirus",
+ issuer_common_name_regex: "avast! Web/Mail Shield Root",
+ issuer_organization_regex: "avast! Web/Mail Shield"
+}
+
+mitm_software {
+ name: "Bitdefender Antivirus",
+ issuer_common_name_regex: "Bitdefender Personal CA\.Net-Defender",
+ issuer_organization_regex: "Bitdefender"
+}
+
+mitm_software {
+ name: "Cisco Umbrella",
+ issuer_common_name_regex: "Cisco Umbrella Root CA",
+ issuer_organization_regex: "Cisco"
+}
+
+mitm_software {
+ name: "Cisco Umbrella",
+ issuer_common_name_regex: "Cisco Umbrella Primary SubCA",
+ issuer_organization_regex: "Cisco"
+}
+
+mitm_software {
+ name: "ContentKeeper",
+ issuer_common_name_regex: "ContentKeeper Appliance CA \(\d+\)",
+ issuer_organization_regex: "ContentKeeper Technologies"
+}
+
+mitm_software {
+ name: "Cyberoam Firewall",
+ issuer_organization_regex: "Cyberoam Certificate Authority"
+}
+
+mitm_software {
+ name: "ForcePoint",
+ issuer_common_name_regex: "Forcepoint Cloud CA",
+ issuer_organization_regex: "Forcepoint LLC"
+}
+
+mitm_software {
+ name: "Fortigate",
+ issuer_common_name_regex: "FortiGate CA",
+ issuer_organization_regex: "Fortinet"
+}
+
+mitm_software {
+ name: "Fortinet",
+ issuer_organization_regex: "Fortinet( Ltd\.)?"
+}
+
mitm_software {
name: "Kaspersky Internet Security",
issuer_common_name_regex: "Kaspersky Anti-Virus Personal Root Certificate"
}
+
+mitm_software {
+ name: "McAfee Web Gateway",
+ issuer_common_name_regex: "McAfee Web Gateway"
+}
+
+mitm_software {
+ name: "NetSpark",
+ issuer_common_name_regex: "www\.netspark\.com",
+ issuer_organization_regex: "NetSpark"
+}
+
+mitm_software {
+ name: "SmoothWall Firewall",
+ issuer_common_name_regex: "Smoothwall-default-root-certificate-authority"
+}
+
+mitm_software {
+ name: "SonicWall Firewall",
+ issuer_organization_regex: "HTTPS Management Certificate for SonicWALL"
+}
+
+mitm_software {
+ name: "Sophos",
+ issuer_common_name_regex: "Sophos SSL CA_[A-Z0-9\-]+",
+ issuer_organization_regex: "Sophos"
+}
+
+mitm_software {
+ name: "Sophos",
+ issuer_common_name_regex: "Sophos_CA_[A-Z0-9]+"
+}
+
+mitm_software {
+ name: "Sophos UTM",
+ issuer_common_name_regex: "sophosutm Proxy CA",
+ issuer_organization_regex: "sophosutm"
+}
+
+mitm_software {
+ name: "Sophos Web Appliance",
+ issuer_common_name_regex: "Sophos Web Appliance",
+ issuer_organization_regex: "Sophos Plc"
+}
+
+mitm_software {
+ name: "Symantec Blue Coat",
+ issuer_organization_regex: "Blue Coat.*"
+}
+
+mitm_software {
+ name: "Trend Micro InterScan Web Security Suite (IWSS)",
+ issuer_common_name_regex: "IWSS\.TREND"
+}
+
+mitm_software {
+ name: "Zscaler",
+ issuer_organization_regex: "Zscaler Inc\."
+}
diff --git a/chromium/chrome/browser/resources/sync_file_system_internals/main.css b/chromium/chrome/browser/resources/sync_file_system_internals/main.css
index 62858f5c664..857f05218ee 100644
--- a/chromium/chrome/browser/resources/sync_file_system_internals/main.css
+++ b/chromium/chrome/browser/resources/sync_file_system_internals/main.css
@@ -70,7 +70,7 @@ tbody tr:nth-child(odd) {
width: 18px;
}
-<if expr="not is_macosx and not is_ios">
+<if expr="not is_macosx">
html[dir=rtl] .file-icon-cell .folder-image {
transform: scaleX(-1);
}
diff --git a/chromium/chrome/browser/resources/translate_internals/prefs.html b/chromium/chrome/browser/resources/translate_internals/prefs.html
index 7b8aa04031d..5b84ad8da35 100644
--- a/chromium/chrome/browser/resources/translate_internals/prefs.html
+++ b/chromium/chrome/browser/resources/translate_internals/prefs.html
@@ -29,12 +29,10 @@ found in the LICENSE file.
<h2>UX</h2>
<p id="prefs-too-often-denied">Refrain from showing the translation prompt</p>
</section>
-<if expr="not is_ios">
<section id="prefs-cld-version">
<h2>CLD Version</h2>
<p i18n-content="cld-version"></p>
</section>
-</if>
</div>
<div>
<section id="prefs-dump">
diff --git a/chromium/chrome/browser/resources/uber/OWNERS b/chromium/chrome/browser/resources/uber/OWNERS
deleted file mode 100644
index adf0fa51b92..00000000000
--- a/chromium/chrome/browser/resources/uber/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-# COMPONENT: UI>Browser>WebUI
diff --git a/chromium/chrome/browser/resources/uber/uber.css b/chromium/chrome/browser/resources/uber/uber.css
deleted file mode 100644
index 9831d083ca1..00000000000
--- a/chromium/chrome/browser/resources/uber/uber.css
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-body {
- /* http://crbug.com/129406 --- horizontal scrollbars flicker when changing
- * sections. */
- overflow-x: hidden;
-}
-
-#navigation {
- height: 100%;
- left: 0;
- /* This is a hack to prevent the navigation bar from occluding pointer events
- * from the bottom scroll bar (which shows when one needs to horizontally
- * scroll). Corresponding padding-top to offset this is in uber_frame.css */
- margin-top: -20px;
- position: absolute;
- /* This value is different from the left value to compensate for the scroll
- * bar (which is always on and to the right) in RTL. */
- right: 15px;
- width: 155px;
- z-index: 3;
-}
-
-#navigation.background {
- z-index: 1;
-}
-
-#navigation.changing-content {
- transition: transform 100ms, width 100ms;
-}
-
-.iframe-container {
- -webkit-margin-start: -20px;
- bottom: 0;
- left: 0;
- opacity: 0;
- position: absolute;
- right: 0;
- top: 0;
- transition: margin 100ms, opacity 100ms;
- z-index: 1;
-}
-
-.iframe-container.selected {
- -webkit-margin-start: 0;
- opacity: 1;
- transition: margin 200ms, opacity 200ms;
- transition-delay: 100ms;
- z-index: 2;
-}
-
-.iframe-container.expanded {
- left: 0;
-}
-
-iframe {
- border: none;
- display: block;
- height: 100%;
- width: 100%;
-}
diff --git a/chromium/chrome/browser/resources/uber/uber.html b/chromium/chrome/browser/resources/uber/uber.html
deleted file mode 100644
index f68a151e0d7..00000000000
--- a/chromium/chrome/browser/resources/uber/uber.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!doctype html>
-<html id="uber" class="loading" i18n-values="dir:textdirection;lang:language">
-<head>
-<meta charset="utf-8">
-<title i18n-content="pageTitle"></title>
-<link id="favicon" rel="icon" type="image/png" sizes="16x16">
-<link id="favicon2x" rel="icon" type="image/png" sizes="32x32">
-
-<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
-<link rel="stylesheet" href="uber.css">
-
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/cr/ui/focus_manager.js"></script>
-<script src="chrome://resources/js/load_time_data.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-
-<script src="chrome://chrome/uber.js"></script>
-<script src="chrome://chrome/uber_utils.js"></script>
-</head>
-
-<body>
-
-<div id="navigation"><iframe src="chrome://uber-frame/" name="chrome" role="presentation"></iframe></div>
-
-<div class="iframe-container"
- i18n-values="id:extensionsHost; data-url:extensionsFrameURL;"
- data-favicon="IDR_EXTENSIONS_FAVICON"></div>
-<div class="iframe-container"
- i18n-values="id:settingsHost; data-url:settingsFrameURL;"
- data-favicon="IDR_SETTINGS_FAVICON"></div>
-<div class="iframe-container"
- i18n-values="id:helpHost; data-url:helpFrameURL;"
- data-favicon="IDR_PRODUCT_LOGO_16"></div>
-
-<script src="chrome://chrome/strings.js"></script>
-<script src="chrome://resources/js/i18n_template.js"></script>
-
-</body>
-</html>
diff --git a/chromium/chrome/browser/resources/uber/uber.js b/chromium/chrome/browser/resources/uber/uber.js
deleted file mode 100644
index 483d475c74d..00000000000
--- a/chromium/chrome/browser/resources/uber/uber.js
+++ /dev/null
@@ -1,476 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('uber', function() {
- /**
- * Options for how web history should be handled.
- */
- var HISTORY_STATE_OPTION = {
- PUSH: 1, // Push a new history state.
- REPLACE: 2, // Replace the current history state.
- NONE: 3, // Ignore this history state change.
- };
-
- /**
- * We cache a reference to the #navigation frame here so we don't need to grab
- * it from the DOM on each scroll.
- * @type {Node}
- * @private
- */
- var navFrame;
-
- /**
- * A queue of method invocations on one of the iframes; if the iframe has not
- * loaded by the time there is a method to invoke, delay the invocation until
- * it is ready.
- * @type {Object}
- * @private
- */
- var queuedInvokes = {};
-
- /**
- * Handles page initialization.
- */
- function onLoad(e) {
- navFrame = $('navigation');
- navFrame.dataset.width = navFrame.offsetWidth;
-
- // Select a page based on the page-URL.
- var params = resolvePageInfo();
- showPage(params.id, HISTORY_STATE_OPTION.NONE, params.path);
-
- window.addEventListener('message', handleWindowMessage);
- window.setTimeout(function() {
- document.documentElement.classList.remove('loading');
- }, 0);
-
- // HACK(dbeam): This makes the assumption that any second part to a path
- // will result in needing background navigation. We shortcut it to avoid
- // flicker on load.
- // HACK(csilv): Search URLs aren't overlays, special case them.
- if (params.id == 'settings' && params.path &&
- !params.path.startsWith('search')) {
- backgroundNavigation();
- }
-
- ensureNonSelectedFrameContainersAreHidden();
- }
-
- /**
- * Find page information from window.location. If the location doesn't
- * point to one of our pages, return default parameters.
- * @return {Object} An object containing the following parameters:
- * id - The 'id' of the page.
- * path - A path into the page, including search and hash. Optional.
- */
- function resolvePageInfo() {
- var params = {};
- var path = window.location.pathname;
- if (path.length > 1) {
- // Split the path into id and the remaining path.
- path = path.slice(1);
- var index = path.indexOf('/');
- if (index != -1) {
- params.id = path.slice(0, index);
- params.path = path.slice(index + 1);
- } else {
- params.id = path;
- }
-
- var container = $(params.id);
- if (container) {
- // The id is valid. Add the hash and search parts of the URL to path.
- params.path = (params.path || '') + window.location.search +
- window.location.hash;
- } else {
- // The target sub-page does not exist, discard the params we generated.
- params.id = undefined;
- params.path = undefined;
- }
- }
- // If we don't have a valid page, get a default.
- if (!params.id)
- params.id = getDefaultIframe().id;
-
- return params;
- }
-
- /**
- * Handler for window.onpopstate.
- * @param {Event} e The history event.
- */
- function onPopHistoryState(e) {
- // Use the URL to determine which page to route to.
- var params = resolvePageInfo();
-
- // If the page isn't the current page, load it fresh. Even if the page is
- // already loaded, it may have state not reflected in the URL, such as the
- // history page's "Remove selected items" overlay. http://crbug.com/377386
- if (getRequiredElement(params.id) !== getSelectedIframeContainer())
- showPage(params.id, HISTORY_STATE_OPTION.NONE, params.path);
-
- // Either way, send the state down to it.
- //
- // Note: This assumes that the state and path parameters for every page
- // under this origin are compatible. All of the downstream pages which
- // navigate use pushState and replaceState.
- invokeMethodOnPage(params.id, 'popState',
- {state: e.state, path: '/' + params.path});
- }
-
- /**
- * @return {Object} The default iframe container.
- */
- function getDefaultIframe() {
- return $(loadTimeData.getString('helpHost'));
- }
-
- /**
- * @return {Object} The currently selected iframe container.
- */
- function getSelectedIframeContainer() {
- return document.querySelector('.iframe-container.selected');
- }
-
- /**
- * @return {Object} The currently selected iframe's contentWindow.
- */
- function getSelectedIframeWindow() {
- return getSelectedIframeContainer().querySelector('iframe').contentWindow;
- }
-
- /**
- * Handles postMessage calls from the iframes of the contained pages.
- *
- * The pages request functionality from this object by passing an object of
- * the following form:
- *
- * { method : "methodToInvoke",
- * params : {...}
- * }
- *
- * |method| is required, while |params| is optional. Extra parameters required
- * by a method must be specified by that method's documentation.
- *
- * @param {Event} e The posted object.
- */
- function handleWindowMessage(e) {
- e = /** @type {!MessageEvent<!{method: string, params: *}>} */(e);
- if (e.data.method === 'beginInterceptingEvents') {
- backgroundNavigation();
- } else if (e.data.method === 'stopInterceptingEvents') {
- foregroundNavigation();
- } else if (e.data.method === 'ready') {
- pageReady(e.origin);
- } else if (e.data.method === 'updateHistory') {
- updateHistory(e.origin, e.data.params.state, e.data.params.path,
- e.data.params.replace);
- } else if (e.data.method === 'setTitle') {
- setTitle(e.origin, e.data.params.title);
- } else if (e.data.method === 'showPage') {
- showPage(e.data.params.pageId,
- HISTORY_STATE_OPTION.PUSH,
- e.data.params.path);
- } else if (e.data.method === 'navigationControlsLoaded') {
- onNavigationControlsLoaded();
- } else if (e.data.method === 'adjustToScroll') {
- adjustToScroll(/** @type {number} */(e.data.params));
- } else if (e.data.method === 'mouseWheel') {
- forwardMouseWheel(/** @type {Object} */(e.data.params));
- } else if (e.data.method === 'mouseDown') {
- forwardMouseDown();
- } else {
- console.error('Received unexpected message', e.data);
- }
- }
-
- /**
- * Sends the navigation iframe to the background.
- */
- function backgroundNavigation() {
- navFrame.classList.add('background');
- navFrame.firstChild.tabIndex = -1;
- navFrame.firstChild.setAttribute('aria-hidden', true);
- }
-
- /**
- * Retrieves the navigation iframe from the background.
- */
- function foregroundNavigation() {
- navFrame.classList.remove('background');
- navFrame.firstChild.tabIndex = 0;
- navFrame.firstChild.removeAttribute('aria-hidden');
- }
-
- /**
- * Enables or disables animated transitions when changing content while
- * horizontally scrolled.
- * @param {boolean} enabled True if enabled, else false to disable.
- */
- function setContentChanging(enabled) {
- navFrame.classList[enabled ? 'add' : 'remove']('changing-content');
-
- if (isRTL()) {
- uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
- 'setContentChanging', enabled);
- }
- }
-
- /**
- * Get an iframe based on the origin of a received post message.
- * @param {string} origin The origin of a post message.
- * @return {!Element} The frame associated to |origin| or null.
- */
- function getIframeFromOrigin(origin) {
- assert(origin.substr(-1) != '/', 'invalid origin given');
- var query = '.iframe-container > iframe[src^="' + origin + '/"]';
- var element = document.querySelector(query);
- assert(element);
- return /** @type {!Element} */(element);
- }
-
- /**
- * Changes the path past the page title (i.e. chrome://chrome/settings/(.*)).
- * @param {Object} state The page's state object for the navigation.
- * @param {string} path The new /path/ to be set after the page name.
- * @param {number} historyOption The type of history modification to make.
- */
- function changePathTo(state, path, historyOption) {
- assert(!path || path.substr(-1) != '/', 'invalid path given');
-
- var histFunc;
- if (historyOption == HISTORY_STATE_OPTION.PUSH)
- histFunc = window.history.pushState;
- else if (historyOption == HISTORY_STATE_OPTION.REPLACE)
- histFunc = window.history.replaceState;
-
- assert(histFunc, 'invalid historyOption given ' + historyOption);
-
- var pageId = getSelectedIframeContainer().id;
- var args = [state, '', '/' + pageId + '/' + (path || '')];
- histFunc.apply(window.history, args);
- }
-
- /**
- * Adds or replaces the current history entry based on a navigation from the
- * source iframe.
- * @param {string} origin The origin of the source iframe.
- * @param {Object} state The source iframe's state object.
- * @param {string} path The new "path" (e.g. "/createProfile").
- * @param {boolean} replace Whether to replace the current history entry.
- */
- function updateHistory(origin, state, path, replace) {
- assert(!path || path[0] != '/', 'invalid path sent from ' + origin);
- var historyOption =
- replace ? HISTORY_STATE_OPTION.REPLACE : HISTORY_STATE_OPTION.PUSH;
- // Only update the currently displayed path if this is the visible frame.
- var container = getIframeFromOrigin(origin).parentNode;
- if (container == getSelectedIframeContainer())
- changePathTo(state, path, historyOption);
- }
-
- /**
- * Sets the title of the page.
- * @param {string} origin The origin of the source iframe.
- * @param {string} title The title of the page.
- */
- function setTitle(origin, title) {
- // Cache the title for the client iframe, i.e., the iframe setting the
- // title. querySelector returns the actual iframe element, so use parentNode
- // to get back to the container.
- var container = getIframeFromOrigin(origin).parentNode;
- container.dataset.title = title;
-
- // Only update the currently displayed title if this is the visible frame.
- if (container == getSelectedIframeContainer())
- document.title = title;
- }
-
- /**
- * Invokes a method on a subpage. If the subpage has not signaled readiness,
- * queue the message for when it does.
- * @param {string} pageId Should match an id of one of the iframe containers.
- * @param {string} method The name of the method to invoke.
- * @param {Object=} opt_params Optional property page of parameters to pass to
- * the invoked method.
- */
- function invokeMethodOnPage(pageId, method, opt_params) {
- var frame = $(pageId).querySelector('iframe');
- if (!frame || !frame.hasAttribute('ready')) {
- queuedInvokes[pageId] = (queuedInvokes[pageId] || []);
- queuedInvokes[pageId].push([method, opt_params]);
- } else {
- uber.invokeMethodOnWindow(frame.contentWindow, method, opt_params);
- }
- }
-
- /**
- * Called in response to a page declaring readiness. Calls any deferred method
- * invocations from invokeMethodOnPage.
- * @param {string} origin The origin of the source iframe.
- */
- function pageReady(origin) {
- var frame = getIframeFromOrigin(origin);
- var container = frame.parentNode;
- frame.setAttribute('ready', '');
- var queue = queuedInvokes[container.id] || [];
- queuedInvokes[container.id] = undefined;
- for (var i = 0; i < queue.length; i++) {
- uber.invokeMethodOnWindow(frame.contentWindow, queue[i][0], queue[i][1]);
- }
- }
-
- /**
- * Selects and navigates a subpage. This is called from uber-frame.
- * @param {string} pageId Should match an id of one of the iframe containers.
- * @param {number} historyOption Indicates whether we should push or replace
- * browser history.
- * @param {string} path A sub-page path.
- */
- function showPage(pageId, historyOption, path) {
- var container = $(pageId);
-
- // Lazy load of iframe contents.
- var sourceUrl = container.dataset.url + (path || '');
- var frame = container.querySelector('iframe');
- if (!frame) {
- frame = container.ownerDocument.createElement('iframe');
- frame.name = pageId;
- frame.setAttribute('role', 'presentation');
- container.appendChild(frame);
- frame.src = sourceUrl;
- } else {
- // There's no particularly good way to know what the current URL of the
- // content frame is as we don't have access to its contentWindow's
- // location, so just replace every time until necessary to do otherwise.
- frame.contentWindow.location.replace(sourceUrl);
- frame.removeAttribute('ready');
- }
-
- // If the last selected container is already showing, ignore the rest.
- var lastSelected = document.querySelector('.iframe-container.selected');
- if (lastSelected === container)
- return;
-
- if (lastSelected) {
- lastSelected.classList.remove('selected');
- // Setting aria-hidden hides the container from assistive technology
- // immediately. The 'hidden' attribute is set after the transition
- // finishes - that ensures it's not possible to accidentally focus
- // an element in an unselected container.
- lastSelected.setAttribute('aria-hidden', 'true');
- }
-
- // Containers that aren't selected have to be hidden so that their
- // content isn't focusable.
- container.hidden = false;
- container.setAttribute('aria-hidden', 'false');
-
- // Trigger a layout after making it visible and before setting
- // the class to 'selected', so that it animates in.
- /** @suppress {uselessCode} */
- container.offsetTop;
- container.classList.add('selected');
-
- setContentChanging(true);
- adjustToScroll(0);
-
- var selectedWindow = getSelectedIframeWindow();
- uber.invokeMethodOnWindow(selectedWindow, 'frameSelected');
- selectedWindow.focus();
-
- if (historyOption != HISTORY_STATE_OPTION.NONE)
- changePathTo({}, path, historyOption);
-
- if (container.dataset.title)
- document.title = container.dataset.title;
- assert('favicon' in container.dataset);
-
- var dataset = /** @type {{favicon: string}} */(container.dataset);
- $('favicon').href = 'chrome://theme/' + dataset.favicon;
- $('favicon2x').href = 'chrome://theme/' + dataset.favicon + '@2x';
-
- updateNavigationControls();
- }
-
- function onNavigationControlsLoaded() {
- updateNavigationControls();
- }
-
- /**
- * Sends a message to uber-frame to update the appearance of the nav controls.
- * It should be called whenever the selected iframe changes.
- */
- function updateNavigationControls() {
- var container = getSelectedIframeContainer();
- uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
- 'changeSelection', {pageId: container.id});
- }
-
- /**
- * Forwarded scroll offset from a content frame's scroll handler.
- * @param {number} scrollOffset The scroll offset from the content frame.
- */
- function adjustToScroll(scrollOffset) {
- // NOTE: The scroll is reset to 0 and easing turned on every time a user
- // switches frames. If we receive a non-zero value it has to have come from
- // a real user scroll, so we disable easing when this happens.
- if (scrollOffset != 0)
- setContentChanging(false);
-
- if (isRTL()) {
- uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow,
- 'adjustToScroll',
- scrollOffset);
- var navWidth = Math.max(0, +navFrame.dataset.width + scrollOffset);
- navFrame.style.width = navWidth + 'px';
- } else {
- navFrame.style.transform = 'translateX(' + -scrollOffset + 'px)';
- }
- }
-
- /**
- * Forward scroll wheel events to subpages.
- * @param {Object} params Relevant parameters of wheel event.
- */
- function forwardMouseWheel(params) {
- uber.invokeMethodOnWindow(getSelectedIframeWindow(), 'mouseWheel', params);
- }
-
- /** Forward mouse down events to subpages. */
- function forwardMouseDown() {
- uber.invokeMethodOnWindow(getSelectedIframeWindow(), 'mouseDown');
- }
-
- /**
- * Make sure that iframe containers that are not selected are
- * hidden, so that elements in those frames aren't part of the
- * focus order. Containers that are unselected later get hidden
- * when the transition ends. We also set the aria-hidden attribute
- * because that hides the container from assistive technology
- * immediately, rather than only after the transition ends.
- */
- function ensureNonSelectedFrameContainersAreHidden() {
- var containers = document.querySelectorAll('.iframe-container');
- for (var i = 0; i < containers.length; i++) {
- var container = containers[i];
- if (!container.classList.contains('selected')) {
- container.hidden = true;
- container.setAttribute('aria-hidden', 'true');
- }
- container.addEventListener('transitionend', function(event) {
- if (!event.target.classList.contains('selected'))
- event.target.hidden = true;
- });
- }
- }
-
- return {
- onLoad: onLoad,
- onPopHistoryState: onPopHistoryState
- };
-});
-
-window.addEventListener('popstate', uber.onPopHistoryState);
-document.addEventListener('DOMContentLoaded', uber.onLoad);
diff --git a/chromium/chrome/browser/resources/uber/uber_frame.css b/chromium/chrome/browser/resources/uber/uber_frame.css
deleted file mode 100644
index 8445c554c7d..00000000000
--- a/chromium/chrome/browser/resources/uber/uber_frame.css
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-html:not(.focus-outline-visible) :focus {
- outline: none;
-}
-
-body {
- overflow: hidden;
- padding-top: 20px;
-}
-
-html.changing-content body {
- transition: transform 100ms;
-}
-
-h1 {
- -webkit-margin-start: 23px;
- color: rgb(92, 97, 102);
- margin-bottom: 1em;
- /* This value must match the top padding of the uber page header. */
- margin-top: 21px;
-}
-
-ul {
- list-style-type: none;
- padding: 0;
-}
-
-li {
- -webkit-border-start: 6px solid transparent;
- -webkit-padding-start: 18px;
- cursor: pointer;
- user-select: none;
-}
-
-li:hover {
- color: #777;
-}
-
-li.selected {
- -webkit-border-start-color: rgb(78, 87, 100);
- cursor: default;
- pointer-events: none;
-}
-
-/* Separates the Help nav item if there are at least 3 items. */
-li:not([hidden]) ~ li:not([hidden]) ~ #help {
- margin-top: 27px;
-}
-
-button {
- background-color: white;
- border: 0;
- color: #999;
- cursor: pointer;
- font: inherit;
- line-height: 1.417em; /* 17px based on default 12px font size. */
- margin: 6px 0;
- padding: 0;
-}
-
-.selected > button {
- color: rgb(70, 78, 90);
-}
-
-html[guestMode='true'] .hide-in-guest {
- display: none;
-}
diff --git a/chromium/chrome/browser/resources/uber/uber_frame.html b/chromium/chrome/browser/resources/uber/uber_frame.html
deleted file mode 100644
index 05c89a7749b..00000000000
--- a/chromium/chrome/browser/resources/uber/uber_frame.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!doctype html>
-<html i18n-values="dir:textdirection;lang:language;guestMode:profileIsGuest"
- id="uber">
-<head>
-<meta charset="utf-8">
-
-<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
-<link rel="stylesheet" href="uber_frame.css">
-
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/cr/ui/focus_manager.js"></script>
-<script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
-<script src="chrome://resources/js/load_time_data.js"></script>
-<script src="chrome://uber-frame/uber_frame.js"></script>
-</head>
-
-<body>
-
-<h1 i18n-content="shortProductName"></h1>
-<ul role="tablist">
- <li i18n-values="controls:extensionsHost" role="tab" id="extensions"
- class="hide-in-guest">
- <button class="custom-appearance"
- i18n-content="extensionsDisplayName"></button>
- </li>
- <li i18n-values="controls:settingsHost" role="tab" id="settings">
- <button class="custom-appearance"
- i18n-content="settingsDisplayName"></button>
- </li>
- <li i18n-values="controls:helpHost" role="tab" id="help">
- <button class="custom-appearance" i18n-content="helpDisplayName"></button>
- </li>
-</ul>
-
-<script src="chrome://uber-frame/strings.js"></script>
-<script src="chrome://resources/js/i18n_template.js"></script>
-
-</body>
-</html>
diff --git a/chromium/chrome/browser/resources/uber/uber_frame.js b/chromium/chrome/browser/resources/uber/uber_frame.js
deleted file mode 100644
index b60feaed92b..00000000000
--- a/chromium/chrome/browser/resources/uber/uber_frame.js
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains the navigation controls that are visible on the left side
-// of the uber page. It exists separately from uber.js so that it may be loaded
-// in an iframe. Iframes can be layered on top of each other, but not mixed in
-// with page content, so all overlapping content on uber must be framed.
-
-// <include src="../../../../ui/webui/resources/js/util.js">
-// <include src="uber_utils.js">
-
-cr.define('uber_frame', function() {
-
- /**
- * Handles page initialization.
- */
- function onLoad() {
- var navigationItems = document.querySelectorAll('li');
-
- for (var i = 0; i < navigationItems.length; ++i) {
- navigationItems[i].addEventListener('click', onNavItemClicked);
- }
-
- cr.ui.FocusOutlineManager.forDocument(this);
-
- window.addEventListener('message', handleWindowMessage);
- uber.invokeMethodOnParent('navigationControlsLoaded');
-
- document.documentElement.addEventListener('mousewheel', onMouseWheel);
- document.documentElement.addEventListener('mousedown', onMouseDown);
- }
-
- /**
- * Handles clicks on the navigation controls (switches the page and updates
- * the URL).
- * @param {Event} e The click event.
- */
- function onNavItemClicked(e) {
- // Though pointer-event: none; is applied to the .selected nav item, users
- // can still tab to them and press enter/space which simulates a click.
- if (e.target.classList.contains('selected'))
- return;
-
- uber.invokeMethodOnParent('showPage',
- {pageId: e.currentTarget.getAttribute('controls')});
-
- setSelection(/** @type {Element} */(e.currentTarget));
- }
-
- /**
- * Handles postMessage from chrome://chrome.
- * @param {Event} e The post data.
- */
- function handleWindowMessage(e) {
- if (e.data.method === 'changeSelection')
- changeSelection(e.data.params);
- else if (e.data.method === 'adjustToScroll')
- adjustToScroll(e.data.params);
- else if (e.data.method === 'setContentChanging')
- setContentChanging(e.data.params);
- else
- console.error('Received unexpected message', e.data);
- }
-
- /**
- * Changes the selected nav control.
- * @param {Object} params Must contain pageId.
- */
- function changeSelection(params) {
- var navItem =
- document.querySelector('li[controls="' + params.pageId + '"]');
- setSelection(navItem);
- showNavItems();
- }
-
- /**
- * @return {Element} The currently selected nav item, if any.
- */
- function getSelectedNavItem() {
- return document.querySelector('li.selected');
- }
-
- /**
- * Sets selection on the given nav item.
- * @param {Element} newSelection The item to be selected.
- */
- function setSelection(newSelection) {
- var items = document.querySelectorAll('li');
- for (var i = 0; i < items.length; ++i) {
- items[i].classList.toggle('selected', items[i] == newSelection);
- items[i].setAttribute('aria-selected', items[i] == newSelection);
- }
- }
-
- /**
- * Shows nav items belonging to the same group as the selected item.
- */
- function showNavItems() {
- var hideSettingsAndHelp = loadTimeData.getBoolean('hideSettingsAndHelp');
- $('settings').hidden = hideSettingsAndHelp;
- $('help').hidden = hideSettingsAndHelp;
- $('extensions').hidden = loadTimeData.getBoolean('hideExtensions');
- }
-
- /**
- * Adjusts this frame's content to scrolls from the outer frame. This is done
- * to obscure text in RTL as a user scrolls over the content of this frame (as
- * currently RTL scrollbars still draw on the right).
- * @param {number} scrollLeft document.body.scrollLeft of the content frame.
- */
- function adjustToScroll(scrollLeft) {
- assert(isRTL());
- document.body.style.transform = 'translateX(' + -scrollLeft + 'px)';
- }
-
- /**
- * Enable/disable an animation to ease the nav bar back into view when
- * changing content while horizontally scrolled.
- * @param {boolean} enabled Whether easing should be enabled.
- */
- function setContentChanging(enabled) {
- assert(isRTL());
- document.documentElement.classList.toggle('changing-content', enabled);
- }
-
- /**
- * Handles mouse wheels on the top level element. Forwards them to uber.js.
- * @param {Event} e The mouse wheel event.
- */
- function onMouseWheel(e) {
- uber.invokeMethodOnParent('mouseWheel',
- {deltaX: e.wheelDeltaX, deltaY: e.wheelDeltaY});
- }
-
- /**
- * Handles mouse presses on the top level element. Forwards them to uber.js.
- * @param {Event} e The mouse down event.
- */
- function onMouseDown(e) {
- uber.invokeMethodOnParent('mouseDown');
- }
-
- /**
- * @return {Element} The currently selected iframe container.
- * @private
- */
- function getSelectedIframe() {
- return document.querySelector('.iframe-container.selected');
- }
-
- return {onLoad: onLoad};
-});
-
-document.addEventListener('DOMContentLoaded', uber_frame.onLoad);
diff --git a/chromium/chrome/browser/resources/uber/uber_page_manager_observer.js b/chromium/chrome/browser/resources/uber/uber_page_manager_observer.js
deleted file mode 100644
index effea4e48b2..00000000000
--- a/chromium/chrome/browser/resources/uber/uber_page_manager_observer.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.define('uber', function() {
- var PageManager = cr.ui.pageManager.PageManager;
-
- /**
- * A PageManager observer that updates the uber page.
- * @constructor
- * @implements {cr.ui.pageManager.PageManager.Observer}
- */
- function PageManagerObserver() {}
-
- PageManagerObserver.prototype = {
- __proto__: PageManager.Observer.prototype,
-
- /**
- * Informs the uber page when a top-level overlay is opened or closed.
- * @param {cr.ui.pageManager.Page} page The page that is being shown or was
- * hidden.
- * @override
- */
- onPageVisibilityChanged: function(page) {
- if (PageManager.isTopLevelOverlay(page)) {
- if (page.visible)
- uber.invokeMethodOnParent('beginInterceptingEvents');
- else
- uber.invokeMethodOnParent('stopInterceptingEvents');
- }
- },
-
- /**
- * Uses uber to set the title.
- * @param {string} title The title to set.
- * @override
- */
- updateTitle: function(title) {
- uber.setTitle(title);
- },
-
- /**
- * Pushes the current page onto the history stack, replacing the current
- * entry if appropriate.
- * @param {string} path The path of the page to push onto the stack.
- * @param {boolean} replace If true, allow no history events to be created.
- * @override
- */
- updateHistory: function(path, replace) {
- var historyFunction = replace ? uber.replaceState : uber.pushState;
- historyFunction({}, path);
- },
- };
-
- // Export
- return {
- PageManagerObserver: PageManagerObserver
- };
-});
diff --git a/chromium/chrome/browser/resources/uber/uber_utils.js b/chromium/chrome/browser/resources/uber/uber_utils.js
deleted file mode 100644
index e1db645b2f9..00000000000
--- a/chromium/chrome/browser/resources/uber/uber_utils.js
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A collection of utility methods for UberPage and its contained
- * pages.
- */
-
-cr.define('uber', function() {
- /**
- * Fixed position header elements on the page to be shifted by handleScroll.
- * @type {NodeList}
- */
- var headerElements;
-
- /**
- * This should be called by uber content pages when DOM content has loaded.
- */
- function onContentFrameLoaded() {
- headerElements = document.getElementsByTagName('header');
- document.addEventListener('scroll', handleScroll);
- document.addEventListener('mousedown', handleMouseDownInFrame, true);
-
- invokeMethodOnParent('ready');
-
- // Prevent the navigation from being stuck in a disabled state when a
- // content page is reloaded while an overlay is visible (crbug.com/246939).
- invokeMethodOnParent('stopInterceptingEvents');
-
- // Trigger the scroll handler to tell the navigation if our page started
- // with some scroll (happens when you use tab restore).
- handleScroll();
-
- window.addEventListener('message', handleWindowMessage);
- }
-
- /**
- * Handles scroll events on the document. This adjusts the position of all
- * headers and updates the parent frame when the page is scrolled.
- */
- function handleScroll() {
- var scrollLeft = scrollLeftForDocument(document);
- var offset = scrollLeft * -1;
- for (var i = 0; i < headerElements.length; i++) {
- // As a workaround for http://crbug.com/231830, set the transform to
- // 'none' rather than 0px.
- headerElements[i].style.transform = offset ?
- 'translateX(' + offset + 'px)' : 'none';
- }
-
- invokeMethodOnParent('adjustToScroll', scrollLeft);
- }
-
- /**
- * Tells the parent to focus the current frame if the mouse goes down in the
- * current frame (and it doesn't already have focus).
- * @param {Event} e A mousedown event.
- */
- function handleMouseDownInFrame(e) {
- if (!e.isSynthetic && !document.hasFocus())
- window.focus();
- }
-
- /**
- * Handles 'message' events on window.
- * @param {Event} e The message event.
- */
- function handleWindowMessage(e) {
- e = /** @type {!MessageEvent<!{method: string, params: *}>} */(e);
- if (e.data.method === 'frameSelected') {
- handleFrameSelected();
- } else if (e.data.method === 'mouseWheel') {
- handleMouseWheel(
- /** @type {{deltaX: number, deltaY: number}} */(e.data.params));
- } else if (e.data.method === 'mouseDown') {
- handleMouseDown();
- } else if (e.data.method === 'popState') {
- handlePopState(e.data.params.state, e.data.params.path);
- }
- }
-
- /**
- * This is called when a user selects this frame via the navigation bar
- * frame (and is triggered via postMessage() from the uber page).
- */
- function handleFrameSelected() {
- setScrollTopForDocument(document, 0);
- }
-
- /**
- * Called when a user mouse wheels (or trackpad scrolls) over the nav frame.
- * The wheel event is forwarded here and we scroll the body.
- * There's no way to figure out the actual scroll amount for a given delta.
- * It differs for every platform and even initWebKitWheelEvent takes a
- * pixel amount instead of a wheel delta. So we just choose something
- * reasonable and hope no one notices the difference.
- * @param {{deltaX: number, deltaY: number}} params A structure that holds
- * wheel deltas in X and Y.
- */
- function handleMouseWheel(params) {
- window.scrollBy(-params.deltaX * 49 / 120, -params.deltaY * 49 / 120);
- }
-
- /**
- * Fire a synthetic mousedown on the body to dismiss transient things like
- * bubbles or menus that listen for mouse presses outside of their UI. We
- * dispatch a fake mousedown rather than a 'mousepressedinnavframe' so that
- * settings/history/extensions don't need to know about their embedder.
- */
- function handleMouseDown() {
- var mouseEvent = new MouseEvent('mousedown');
- mouseEvent.isSynthetic = true;
- document.dispatchEvent(mouseEvent);
- }
-
- /**
- * Called when the parent window restores some state saved by uber.pushState
- * or uber.replaceState. Simulates a popstate event.
- * @param {PopStateEvent} state A state object for replaceState and pushState.
- * @param {string} path The path the page navigated to.
- * @suppress {checkTypes}
- */
- function handlePopState(state, path) {
- window.history.replaceState(state, '', path);
- window.dispatchEvent(new PopStateEvent('popstate', {state: state}));
- }
-
- /**
- * @return {boolean} Whether this frame has a parent.
- */
- function hasParent() {
- return window != window.parent;
- }
-
- /**
- * Invokes a method on the parent window (UberPage). This is a convenience
- * method for API calls into the uber page.
- * @param {string} method The name of the method to invoke.
- * @param {?=} opt_params Optional property bag of parameters to pass to the
- * invoked method.
- */
- function invokeMethodOnParent(method, opt_params) {
- if (!hasParent())
- return;
-
- invokeMethodOnWindow(window.parent, method, opt_params, 'chrome://chrome');
- }
-
- /**
- * Invokes a method on the target window.
- * @param {string} method The name of the method to invoke.
- * @param {?=} opt_params Optional property bag of parameters to pass to the
- * invoked method.
- * @param {string=} opt_url The origin of the target window.
- */
- function invokeMethodOnWindow(targetWindow, method, opt_params, opt_url) {
- var data = {method: method, params: opt_params};
- targetWindow.postMessage(data, opt_url ? opt_url : '*');
- }
-
- /**
- * Updates the page's history state. If the page is embedded in a child,
- * forward the information to the parent for it to manage history for us. This
- * is a replacement of history.replaceState and history.pushState.
- * @param {Object} state A state object for replaceState and pushState.
- * @param {string} path The path the page navigated to.
- * @param {boolean} replace If true, navigate with replacement.
- */
- function updateHistory(state, path, replace) {
- var historyFunction = replace ?
- window.history.replaceState :
- window.history.pushState;
-
- if (hasParent()) {
- // If there's a parent, always replaceState. The parent will do the actual
- // pushState.
- historyFunction = window.history.replaceState;
- invokeMethodOnParent('updateHistory', {
- state: state, path: path, replace: replace});
- }
- historyFunction.call(window.history, state, '', '/' + path);
- }
-
- /**
- * Sets the current title for the page. If the page is embedded in a child,
- * forward the information to the parent. This is a replacement for setting
- * document.title.
- * @param {string} title The new title for the page.
- */
- function setTitle(title) {
- document.title = title;
- invokeMethodOnParent('setTitle', {title: title});
- }
-
- /**
- * Pushes new history state for the page. If the page is embedded in a child,
- * forward the information to the parent; when embedded, all history entries
- * are attached to the parent. This is a replacement of history.pushState.
- * @param {Object} state A state object for replaceState and pushState.
- * @param {string} path The path the page navigated to.
- */
- function pushState(state, path) {
- updateHistory(state, path, false);
- }
-
- /**
- * Replaces the page's history state. If the page is embedded in a child,
- * forward the information to the parent; when embedded, all history entries
- * are attached to the parent. This is a replacement of history.replaceState.
- * @param {Object} state A state object for replaceState and pushState.
- * @param {string} path The path the page navigated to.
- */
- function replaceState(state, path) {
- updateHistory(state, path, true);
- }
-
- return {
- invokeMethodOnParent: invokeMethodOnParent,
- invokeMethodOnWindow: invokeMethodOnWindow,
- onContentFrameLoaded: onContentFrameLoaded,
- pushState: pushState,
- replaceState: replaceState,
- setTitle: setTitle,
- };
-});
diff --git a/chromium/chrome/browser/resources/uber/uber_shared.css b/chromium/chrome/browser/resources/uber_shared.css
index a53533c2af0..1aa69c4a5f3 100644
--- a/chromium/chrome/browser/resources/uber/uber_shared.css
+++ b/chromium/chrome/browser/resources/uber_shared.css
@@ -173,7 +173,7 @@ body .section-header > h3 {
.page-banner-text {
-webkit-padding-end: 8px;
-webkit-padding-start: 26px;
- background-image: url(../../../../ui/webui/resources/images/business.svg);
+ background-image: url(../../../ui/webui/resources/images/business.svg);
background-position: 0 center;
background-repeat: no-repeat;
background-size: 18px;
diff --git a/chromium/chrome/browser/resources/unpack_pak.py b/chromium/chrome/browser/resources/unpack_pak.py
index cf747600db7..8eda2e871fb 100755
--- a/chromium/chrome/browser/resources/unpack_pak.py
+++ b/chromium/chrome/browser/resources/unpack_pak.py
@@ -11,6 +11,10 @@ import sys
_HERE_PATH = os.path.join(os.path.dirname(__file__))
+# The name of a dummy file to be updated always after all other files have been
+# written. This file is declared as the "output" for GN's purposes
+_TIMESTAMP_FILENAME = os.path.join('unpack.stamp')
+
_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..'))
sys.path.insert(1, os.path.join(_SRC_PATH, 'tools', 'grit'))
@@ -62,6 +66,10 @@ def main():
unpack(args.pak_file, args.out_folder)
+ timestamp_file_path = os.path.join(args.out_folder, _TIMESTAMP_FILENAME)
+ with open(timestamp_file_path, 'a'):
+ os.utime(timestamp_file_path, None)
+
if __name__ == '__main__':
main()